Cloudflare Workers Cache: tiered edge cache for your Worker
2 min read
Originally from blog.cloudflare.com
View source
My notes
Summary
Cloudflare launched Workers Cache: a tiered cache that sits in front of a Cloudflare Worker itself (not just in front of an origin), configured with one Wrangler config line plus standard Cache-Control headers. Cache hits skip the Worker entirely (no CPU billing), while stale-while-revalidate lets stale content serve instantly during background refreshes, giving server-rendered apps static-site speed without static-site rebuild delays.
Key Insight
- The architectural shift: Workers used to run in front of the cache (a CDN transforming requests to an origin). Frameworks like Astro, Next.js, Remix, and SvelteKit now ship Cloudflare adapters where the Worker is the origin, so there was nothing to cache in front of it until now.
- Billing model is the real story: cache HIT = standard request charge, zero CPU billing. MISS and BYPASS both bill request + CPU normally. A previously-free path (static assets, worker-to-worker calls via service bindings/ctx.exports) now bills at standard request rate once caching is enabled, because each one consults the cache.
- Per-entrypoint cache control is the standout feature: a single Worker can have multiple
WorkerEntrypoints, each opted in/out of caching independently via theexportsmap in Wrangler config. A gateway entrypoint (auth/routing) stays uncached; an inner “expensive work” entrypoint gets cached, enabling patterns no other platform offers (per their claim): authenticated, multi-tenant APIs cached at the edge without leaking data between users. - Multi-tenant safety via
ctx.props: passing auserId(or tenant ID) intoctx.propswhen calling a cached entrypoint makes it part of the cache key automatically, so different users hitting the same URL get separate cache entries. Pattern: gateway authenticates, stripsAuthorizationheader (otherwise Cloudflare’s automatic bypass kills caching), forwards withctx.props: { userId }. - Two-tier topology, no config: a lower tier per data center, an upper tier that aggregates fills network-wide. First request anywhere populates the upper tier, so subsequent requests from any data center can hit without ever touching the Worker, giving dramatically higher hit ratios than a flat single-layer cache, and it’s automatic (no “enable tiered cache” toggle).
- Vary header support done properly (RFC 9110/9111): separate cached variants per distinct header combination (Accept, Accept-Language, Accept-Encoding, etc.), no allowlist restriction, but
Vary: *disables caching entirely, and unbounded variant fan-out is a real footgun if headers aren’t normalized upstream. - Concrete TTL guidance from the post: product catalog updating every few minutes gets
max-age=300, stale-while-revalidate=3600. Near-static blog archive getsmax-age=86400, stale-while-revalidate=2592000(Worker runs once/day per page). - Launch caveat: at launch, cacheable response size is capped at the Free plan limit (512 MB) regardless of paid plan (temporary, with per-plan limits coming later). Astro has first-class integration today (
cacheCloudflareprovider); TanStack Start and Next.js (via Vinext) integrations are in progress. - No new SKU: no separate cache pricing, no per-GB storage fee, all folded into the existing Workers billing model.