One Header to Rule the Cache Layers

Modern web architectures rarely have a single cache between origin and visitor. Responses may pass through origin-side caches, one or more CDNs, and finally a browser cache. All of these layers interpret the same Cache-Control response header — but they do not interpret it uniformly. The result is unpredictable behavior as directives like stale-while-revalidate get applied, stripped, or forwarded inconsistently.

To close this gap, we now support CDN-Cache-Control and a Cloudflare-specific variant, Cloudflare-CDN-Cache-Control. Both are response headers defined in an IETF draft being developed with input from other major CDN operators. They support the exact same directives — and the same precedence rules — as Cache-Control, so you can copy an existing Cache-Control value into either header and get identical caching behavior, but scoped specifically to the CDN layer.

CDN-Cache-Control: Precision Control for your CDN(s)

How Precedence Works

The value of these headers only becomes clear when you control what each cache layer sees. The behavior is straightforward depending on which headers an origin returns:

  1. Return only CDN-Cache-Control. Cloudflare uses it to make caching decisions. Any Cache-Control value from the origin is proxied downstream unchanged and ignored by Cloudflare for cache decisions. CDN-Cache-Control itself is also proxied downstream, so other CDNs that honor the draft can use it.

  2. Return only Cloudflare-CDN-Cache-Control. Syntax and behavior are identical to case 1, except this header is not forwarded downstream. This is the right choice when you want a different behavior on Cloudflare specifically while other caches rely on Cache-Control — or when you do not want the CDN-Cache-Control header leaked onward.

  3. Return both. Cloudflare evaluates only Cloudflare-CDN-Cache-Control because it is the most specific signal, and forwards CDN-Cache-Control downstream for other CDNs. This is the setup for giving Cloudflare one TTL and a downstream CDN a different one.

A request can therefore traverse a chain of caches, each instructed with different TTLs and stale-while-revalidate windows:

Caches Control Headers
Origin Server Cache Cache-Control
Shared Cache on the Origin Network Cache-Control
CDN #1 CDN-Cache-Control
Cloudflare CDN Cloudflare-CDN-Cache-Control/CDN-Cache-Control
CDN #N CDN-Cache-Control
Browser Cache Cache-Control

Interactions With Existing Cloudflare Settings

Edge Cache TTL Page Rule

The Edge Cache TTL page rule overrides the amount of time an asset is cached at Cloudflare's edge. It therefore takes precedence over any TTL directive in Cloudflare-CDN-Cache-Control or CDN-Cache-Control.

Browser Cache TTL Page Rule

This page rule only changes what the browser cache stores and therefore only modifies the Cache-Control header passed downstream. The two CDN-specific headers are never rewritten by this rule.

Other Origin Response Headers

An Expires header from the origin is ignored by Cloudflare when either CDN-Cache-Control header is present. If Cloudflare receives none of the three headers (Cache-Control, CDN-Cache-Control, or Cloudflare-CDN-Cache-Control), its standard default values for cacheable assets apply.

Use Cases

Multiple cache hops used to force a compromise: either you set TTLs via Page Rules, or you lost control at some layer because intermediaries proxied or stripped Cache-Control unpredictably. The new headers remove that guesswork.

Different TTLs Per Layer

Consider a site that previously relied on a Page Rule to give Cloudflare a longer TTL than what browser and origin caches saw:

Before:

  • Cache-Control: max-age=14400, s-maxage=84000, plus an Edge Cache TTL Page Rule of 24400 seconds.
Caches Cache TTL (seconds)
Origin Server Cache 14400
Cloudflare Edge 24400
Other CDNs 84000
Browser Cache 14400

Now: the same result is achieved purely on the origin. The origin can also give different CDN providers different TTLs by returning both CDN-specific headers with distinct values:

  • Cache-Control: max-age=14400, s-maxage=84000
  • Cloudflare-CDN-Cache-Control: max-age=24400
  • CDN-Cache-Control: 18000
Caches Cache TTL (seconds)
Origin Server Cache 14400
Network Shared Cache 84000
Cloudflare Edge 24400
Other CDNs 18000
Browser Cache 14400
BLOG-510 Embedded Image - BlpluX

Stale Content Control

In another scenario, a site behind multiple CDNs wants precise control over which layer serves stale content during revalidation or after a 5XX error. Before, this was impossible because each intermediary had to guess whether stale-if-error applied to it, and whether it should pass the header on.

Before: With only Cache-Control: stale-if-error=400, each CDN may behave differently upon a 5XX response.

Caches Stale served (seconds) in response to error
Origin Cache Layer 400 (if it assumes the directive applies)
Cloudflare Edge 400 (we assume the directive applies if we get it from upstream)
Unknown CDN/Network caches/Browser Cache 0 (if they assume the directives doesn’t apply or they don’t get them from upstream); or 400 (if they do assume it applies)

Now: the origin can state explicitly that Cloudflare should serve stale for 60 seconds while the downstream CDN does so for 200 seconds:

  • Cache-Control: stale-if-error=400
  • Cloudflare-CDN-Cache-Control: stale-if-error=60
  • CDN-Cache-Control: stale-if-error=200
Caches Stale served (seconds) in response to error
Origin Cache Layer/Network Cache/Browser Cache 400 (if it assumes the directive applies)
Cloudflare Edge 60
Other CDN 200
BLOG-510 Embedded Image - Pw77NX

Putting It To Work

CDN-Cache-Control gives origin operators finer per-asset control over cache lifetimes and revalidation behavior across all CDN layers — without affecting browsers or upstream caches. If your architecture involves more than one cache hop, consider setting these headers at the origin and dropping the equivalent Page Rules. CDN operators evaluating the draft should similarly look at supporting it to bring consistent behavior to the whole chain.