Guide · RFC 9213 and Cloudflare documentation · 25 Oct 2026
CDN-targeted Cache-Control
RFC 9213 lets an origin give a targeted cache its own response policy. The target cache selects one targeted field; it does not merge that field with ordinary Cache-Control.
Short answer
s-maxage is an ordinary Cache-Control directive for shared caches generally. RFC 9213 adds a targeting mechanism: a conforming CDN can use CDN-Cache-Control for its policy while a browser or other cache uses ordinary response controls. Each cache applies its own selected freshness policy to the same end-to-end response age. RFC 9213 §§2–2.3; RFC 9111 §4.2.
Keep the fields distinct
| Field | Scope | What it does not mean |
|---|---|---|
Cache-Control: s-maxage=… | Shared caches that use ordinary HTTP cache-control rules; it overrides max-age and Expires for those caches. [RFC 9111] | It is not CDN-only. A shared proxy may apply it too. |
CDN-Cache-Control: max-age=… | The standardized CDN target field in RFC 9213. A CDN uses it only when its target list selects it. [RFC 9213] | Its field name alone does not prove that a CDN recognizes or enables RFC 9213. |
Cloudflare-CDN-Cache-Control: max-age=… | A Cloudflare-specific field. Cloudflare documentation places it ahead of CDN-Cache-Control in its documented precedence. [Cloudflare] | It is not a standard field for other CDNs and does not show a live zone’s effective configuration. |
RFC 9213 targeted values are Structured Field Dictionaries. Similar-looking syntax does not make a targeted field an ordinary Cache-Control field; RFC 9213 cautions against using a non-Structured-Fields parser for it. RFC 9213 §2.1; RFC 8941.
A synthetic comparison at Age 300
Assume a public static response, no request-side directives, no local rules that override origin headers, and a downstream Age: 300. This example shows policy selection only; these headers were not sent to a cache.
Cache-Control: public, max-age=60, s-maxage=120
CDN-Cache-Control: public, max-age=600
Cloudflare-CDN-Cache-Control: public, max-age=900
| Cache | Policy used in this example | At Age 300 | Qualification |
|---|---|---|---|
| Browser/private cache | max-age=60 | Stale | It does not use s-maxage or the CDN-targeted fields in this example. |
| Ordinary shared proxy | s-maxage=120 | Stale | An ordinary shared cache not targeting the added fields uses normal HTTP freshness selection. |
| Another RFC 9213 CDN | CDN-Cache-Control: max-age=600 | Fresh | Assumes its target list selects CDN-Cache-Control. |
| Cloudflare, per current documentation | Cloudflare-CDN-Cache-Control: max-age=900 | Fresh | Assumes documented precedence applies and no higher-priority product rule overrides it. |
The age remains end-to-end. A longer targeted lifetime can leave a CDN’s copy fresh while a downstream browser or shared proxy considers the response stale; targeted policy does not reset Age. RFC 9213 §2.3 gives the same distinction with a synthetic example. Do not assume a product removes Age or rewrites Date unless its documentation or an authorized capture establishes that behavior.
Cloudflare’s documented boundary
Cloudflare documents this order for cache response controls: Cloudflare-CDN-Cache-Control, then CDN-Cache-Control, then ordinary Cache-Control. It says the standard CDN field is forwarded downstream, the Cloudflare-specific field is not, and ordinary Cache-Control is proxied as received. These are Cloudflare product statements, not RFC 9213 rules for other providers. CDN-Cache-Control; Cache responses.
- A Cache Response Rule that sets cache control can take precedence over origin-set targeted headers. A Cache Rule’s Edge Cache TTL can also override the targeted field’s edge lifetime.
- Browser Cache TTL changes the ordinary browser-facing
Cache-Controlfield; Cloudflare says it does not modify either targeted field. - Cloudflare’s CDN-Cache-Control documentation says
Surrogate-Controlsuppresses originCache-Controlfor surrogates even if empty, but it does not fully specify an ordering against both targeted fields. That combination remains a configuration question. - Cloudflare’s Origin Cache Control documentation says setting
Cloudflare-CDN-Cache-Controlenables OCC regardless of the usual OCC toggle. For a request carryingAuthorization, its documented cache-permission conditions are product-specific; do not generalize them to other caches or treat them as proof that user-specific content is safe to share.
For the separate Cloudflare Cache Rules, Browser TTL, cache-key, and purge overview, see the Cloudflare Cache Rules guide and its dated report.
Freshness is not privacy or key isolation
A valid targeted field can intentionally direct one cache to store a response even when ordinary Cache-Control: no-store tells other caches not to store it. A selected targeted policy is not merged with ordinary controls. If a CDN must not store a response, put the restrictive directive in the targeted field that CDN selects or omit that targeted field; do not rely on an unselected ordinary header to veto it. RFC 9213 warns that multiple policies can lead to unintended reuse.
private and no-store have the RFC meaning for the policy selected by a cache, but no-store is not a guarantee against a malicious or compromised cache. A correct TTL also does not make a shared key safe: RFC 9111’s minimum key includes method and target URI, while Vary and implementation-specific inputs may further distinguish representations. A targeted lifetime does not add cookies, authorization, tenant, locale, or other dimensions to a cache key.
For user-specific or credentialed content, review storage eligibility, every cache’s selected policy, response variants, and key before permitting shared storage. See the cache-key and privacy report.
What remains unknown
- RFC 9213 defines semantics for conforming caches; it does not establish that a named browser, CDN, proxy, or cache enables targeted fields or what its target list contains.
- Cloudflare’s documentation does not establish a particular zone’s matching rules, Edge/Browser TTL settings, key, response headers, POP/tier path, or resulting
Age. - Malformed or empty field handling, date/age rewriting, additional Cloudflare products, and a concrete downstream topology were not tested here.
- All response fields and age values in the comparison are synthetic. No endpoint, cache, browser, Cloudflare zone, or third-party system was tested.
Primary sources
- RFC 9213 — Targeted HTTP Cache Control: §§2.1–2.4 for syntax, target-list selection, fallback, pass-through, end-to-end freshness, and field conventions; §§3–3.1 for CDN targeting and forwarding; §5 for security limits.
- RFC 9111 — HTTP Caching: §§2, 3.5, 4.2–4.2.3, 5.1, 5.2.2.1, and 5.2.2.10 for keys, Authorization, freshness/age,
Age,max-age, ands-maxage. - RFC 8941 — Structured Field Values for HTTP: dictionary syntax referenced by RFC 9213.
- Cloudflare: CDN-Cache-Control: documented header precedence, forwarding, and TTL interactions; page notes last update 16 Apr 2026.
- Cloudflare: Cache responses: documented response-header precedence, bypass/revalidation behavior, and Edge TTL exception.
- Cloudflare: Origin Cache Control: documented OCC and Authorization interaction.
- Cloudflare: Cache Response Rules: documented precedence of response rules over origin-set cache control and Cache Rules.
RFC 9213 and RFC 9111 are IETF Standards Track documents. Cloudflare statements above are current product documentation checked 25 Oct 2026; they are not live measurements.