Skip to content

CLOUDFLARE

Read original ↗

Your Worker can now have its own cache in front of it

Summary

Cloudflare launches Workers Cache — a regionally-tiered cache that sits in front of a Worker (reversing the original 2017 architecture where the Worker sat in front of the cache). Configured via a single "cache": { "enabled": true } Wrangler config block + standard Cache-Control headers on responses. On a cache hit the Worker doesn't run and CPU billing stays at zero. The cache belongs to the Worker (not the zone), follows the Worker across hostnames / workers.dev / previews / service bindings, and is regionally tiered by default with no additional configuration.

Key Takeaways

  1. Architecture inversion: Workers originally ran in front of the zone cache (transforming requests on the way to an origin). As Workers became the origin (Astro, Next.js, Remix, SvelteKit adapters), there was nothing to cache. Workers Cache flips the model — the cache now sits in front of the Worker. (Section: Why server-rendered apps need a cache in front)

  2. Tiered by default, zero configuration: Two-tier architecture — a lower tier in the POP closest to the user and an upper tier aggregating fills regionally. The first request anywhere populates the upper tier; subsequent requests from any data center can be served without the Worker running. No tiered-cache toggle required. (Section: Two tiers, every Worker, no configuration)

  3. stale-while-revalidate makes sites feel static: The stale-while-revalidate directive (RFC 5861) lets Cloudflare serve the stale copy immediately while refreshing in the background. Combined with a Worker origin, this delivers "the speed of a static site without the build time, and the freshness of server rendering without the cost" — replacing ISR-style framework machinery with standard HTTP caching. (Section: stale-while-revalidate is the part that makes it feel instant)

  4. Worker-owned, not zone-owned: The cache belongs to the Worker, not a zone. Zone Cache Rules, Page Rules, file-extensions list — none apply. The Worker's Cache-Control headers are the only configuration. The cache works on workers.dev, preview URLs (isolated per-preview), and Workers for Platforms (isolated per-tenant). Purges are scoped to the Worker's entrypoint. (Section: This is your Worker's cache, not your zone's)

  5. Vary support for content negotiation: Standard HTTP Vary header stores separate cached variants per distinct header combination. No allowlist restriction — any request header can be varied on. Purges invalidate all variants of a URL together. (Section: One URL, many representations: Vary works)

  6. Multi-tenant safety via ctx.props in cache key: When one Worker calls another via a service binding with ctx.props, callers with different props get separate cache entries. Authentication in a gateway Worker → strip Authorization → set user ID into ctx.props → cached backend Worker runs per-user cache entries. "We don't know of another CDN that offers this as a built-in model for authenticated, multi-tenant APIs." (Section: Multi-tenant by default, with ctx.props)

  7. Per-entrypoint cache stages: Workers Cache sits in front of every Worker entrypoint — the default export, every named WorkerEntrypoint, and every ctx.exports call. Each entrypoint can independently opt in or out of caching via the Wrangler exports map. This creates composable memoization stages within a single deployable unit. (Section: A cache between every Worker entrypoint)

  8. Near-user + near-data composition: With service bindings, a gateway Worker (near user) calls a cached backend Worker (near data via Smart Placement). On a cache hit, the backend never runs — no data-center hop. The "two Workers, one caches" shape resolves the user-proximity vs. data-proximity tension without expert configuration. (Section: Run your app near the user and near the data)

  9. Framework integration (Astro first): Astro's Cloudflare adapter wires up Workers Cache via a cacheCloudflare provider — auto-sets headers, attaches Cache-Tag, and provides a cache.invalidate() helper. Other frameworks forthcoming. (Section: First-class support in your framework)

  10. Billing model: Cache hits bill a standard request rate but zero CPU time. No separate SKU, no per-GB storage fee, tiering/purges/SWR/analytics all included. Caveat: normally-free requests (static assets, worker-to-worker) are billed at standard rate when caching is enabled because they now consult the cache. (Section: See your cache on the same dashboard as your Worker)

Architectural Numbers

Metric Value
Configuration surface 1 JSON block ("cache": { "enabled": true })
Cache tiers 2 (lower-tier per-POP + upper-tier regional)
Cache hit CPU billing Zero
Max response size (launch) 512 MB (Free-plan limit, temporary)
Framework integrations (launch) Astro (built-in); TanStack Start + Vinext planned

Systems Extracted

Concepts Extracted

Patterns Extracted

Caveats

  • Launch-day size limit: All responses limited to 512 MB regardless of plan (stated as temporary).
  • Smart Placement interaction: Upper-tier cache and Smart Placement target chosen separately today; on a full miss the request may travel between Cloudflare locations twice. Fix in progress.
  • Normally-free requests billed: Static assets and worker-to-worker invocations that enable caching are now billed at standard request rate.
  • No ctx.cache.invalidate() yet: Only purge() (hard delete) exists; a soft-invalidation API (mark stale, still serve SWR) is planned.

Source

Last updated · 568 distilled / 1,686 read