Skip to main content
Concepts

Edge Resolution and Cache

How Cloudflare Workers resolve aliases and cache deployed assets.

Odyn serves deployed code through a Cloudflare Worker running at the edge. The Worker resolves project identifiers and version aliases, fetches the built asset from R2, and returns it with appropriate cache headers. This page describes the resolution flow and caching behavior.

Request Flow

When a browser requests a CDN URL, the Cloudflare Worker handles the request in this order:

Request Flow
Browser request
    |
    v
Cloudflare Worker (edge)
    |
    +-- Parse URL: environment, project, version, file path
    |
    +-- Resolve project identifier (short ID, slug, or UUID)
    |
    +-- Resolve version:
    |     Staging: no version resolution needed (fixed R2 path)
    |     Production @latest: KV lookup for current version
    |     Production @N: KV lookup for pinned version timestamp
    |
    +-- Domain protection check (if configured)
    |
    +-- Fetch asset from R2
    |
    +-- Return response with cache headers

Project Identifier Resolution

CDN URLs accept three project identifier formats, resolved in this priority:

  1. Short ID: abc123 — a compact identifier assigned to each project.
  2. Owner/slug: john/my-project — the owner's slug and the project's slug.
  3. UUID: f47ac10b-58cc-4372-a567-0e02b2c3d479 — the full project ID.

The Worker checks each format against KV or the project registry to find the canonical project ID.

Version Resolution

Staging

Staging URLs resolve to a fixed R2 path:

R2 Path
projects/{projectId}/staging/bundle.{js|css}

No version lookup is needed. The path is deterministic and overwritten on each staging deploy.

Production (Floating)

URLs without an explicit version resolve @latest:

CDN URL
https://cdn.odyn.dev/p/{project}/bundle.js

The Worker reads the KV key {projectId}_prod_{assetType} to get the current version's timestamp, then constructs the R2 path:

R2 Path
projects/{projectId}/prod/bundle-{timestamp}.{js|css}

Production (Pinned)

URLs with an explicit version number:

CDN URL
https://cdn.odyn.dev/p/{project}@42/bundle.js

The Worker reads the KV key ver:{projectId}:prod:{versionNumber}:{assetType} to get the pinned version's timestamp.

Cache Behavior

EnvironmentCache-ControlBehavior
Stagingno-cache, no-storeNever cached. Every request fetches from R2.
Production (floating)Short TTLCached at edge briefly. Updated when KV propagates.
Production (pinned)public, max-age=31536000, immutableCached indefinitely. Content never changes.

Staging: No Cache

Staging assets carry no-cache headers so that refreshing the browser always loads the latest deploy. This supports the rapid edit-deploy-verify cycle.

Production Floating: Short TTL

The floating alias depends on KV propagation. After a new deploy updates the KV pointer, edge nodes that cached the previous response continue serving it until their TTL expires. In practice, Cloudflare KV propagates globally within approximately 60 seconds.

Production Pinned: Immutable

Pinned URLs point to a specific version whose underlying R2 object never changes. Edge nodes and browsers can cache the response permanently. This is the most efficient caching strategy: zero revalidation, zero origin fetches after the first request.

KV Propagation

Cloudflare KV is eventually consistent. After a production deploy writes a new @latest pointer:

  1. The nearest edge node picks up the change almost immediately (typically under 1 second).
  2. Global propagation completes within approximately 60 seconds.
  3. During the propagation window, some edge nodes may serve the previous version.

This is acceptable for production workflows because:

  • The previous version is still valid (it is the version that was live moments ago).
  • Pinned URLs are not affected (they do not use the @latest pointer).
  • Critical deployments can verify propagation by requesting the CDN URL from different regions.

Domain Protection at the Edge

If domain protection is enabled for a project, the Worker checks the Referer or Origin header against the project's allowed domain list before serving the asset. Domain rules are stored in KV and propagate with the same ~60 second delay.

localhost is always allowed regardless of the domain list. See Domain Protection.