Shaduf.
HTTP Cache Field Guide/Cache deployment and incident runbook

Dated report · provider-neutral · 23 Sep 2026

Cache deployment and incident runbook

A short, standards-grounded path for keeping private responses private, shipping public content predictably, and finding the layer that served old bytes.

Documentation-only / no live provider capture. The source review had no authorized CloudFront distribution, Cloudflare zone, endpoint, controlled origin, browser or HTTP-client capture, vendor log, purge/invalidation operation, or analytics. Provider behavior below is documented expectation or inference, never a measured result.

The decision order

  1. Classify the representation. Is the body identical for every intended audience, or can cookies, authorization, query, language, device, geography, feature flags, time, or server state change it?
  2. Choose the storage audience. Decide between no HTTP-cache retention, private/browser retention, and shared retention. Do not infer the answer from a provider status field.
  3. Set browser and shared freshness separately. max-age is the browser-facing lifetime; s-maxage is for shared caches and takes precedence there over max-age and Expires.
  4. Add validation when retention is acceptable. Use ETag and/or Last-Modified. If both conditions are sent, If-None-Match is evaluated first; a 304 does not identify the hop that produced it.
  5. Review identity before TTL. Check method, URI, query, Vary, cookies, authorization, host, compression, redirects, device/geo signals, and the effective provider key.
  6. Name the hop and its limits. Capture Age, Cache-Status when exposed, provider fields, validators, a redacted origin marker, and downstream state. A purge or hit at one named layer is not global proof.
Two deployment paths for private and public responses Both paths begin by classifying the representation. The private path prevents shared storage and checks downstream copies. The public path confirms equivalent content, sets separate lifetimes, versions changed URLs, and verifies the named hop. Classify same body?same audience? Private / sensitive no shared storeno-store orprivate, no-cache Validate if kept ETag / dateaudit workerand provider Check downstream browser · workerproxy · app cachecontain before close Public / equivalent safe to sharekey variantsreviewed Set freshness max-ages-maxagevalidators Version and verify new URL for new bytesnamed hop evidencedownstream test
Two lanes, one rule: safety comes from representation and storage decisions before a provider TTL or purge choice.

Three evidence labels

LabelUse it forDo not overclaim
Standards-stableHTTP storage audience, freshness precedence, validators, conditional requests, minimum cache-key model, Vary, Age, Via, and optional RFC 9211 Cache-Status.Standards do not force a cache to store/reuse, identify hidden layers, or control service workers and application caches.
Vendor-specificCloudFront behavior/TTL bounds, response-header policies, invalidation scope, Cloudflare OCC, Cache Rules, Browser TTL, custom keys, status fields, and purge methods.Do not merge CloudFront and Cloudflare into a generic “CDN,” or turn documentation into a deployment result.
Live-topology-requiredThe matching rule and key, actual stored object, POP/tier, provider status, origin counter, browser state, downstream proxy, or purge follow-up.No live topology was supplied here. Treat unknown as unknown until a named path is captured.

Pre-deploy checklist

A · Personalized or sensitive

  1. List every input that can change the body or sensitive headers: session cookie, Authorization, tenant, role, query, language, device, geography, experiment, time, and server state. If the list is incomplete, do not make the response public.
  2. Use Cache-Control: no-store when intentional HTTP-cache retention is unacceptable. If browser retention with validation is acceptable, use Cache-Control: private, no-cache with a validator.
  3. Keep the route out of shared caching rules. Review the effective provider rule, edge minimum/override, cache key, Workers or functions, framework caches, service-worker Cache API, and response-header rewrites.
  4. Do not use Vary: Cookie as a general privacy fix. A custom key does not make personalized bytes safe; a Set-Cookie header alone is not a complete cache barrier.
  5. Use a harmless redacted marker and origin counter in an authorized synthetic fixture. Never put credentials, account data, or tokens in the fixture or saved evidence.
  6. Make a release blocker explicit: a public rule, positive shared-cache minimum, unreviewed key dimension, or one identity receiving another identity's marker stops the rollout.

Containment: correct policy and key first. Purge known provider objects only as a secondary action; it cannot prove that a browser, service worker, corporate proxy, or log has no copy.

B · Public HTML or versioned assets

  1. Confirm that body and relevant headers are intentionally identical for the audiences that will share them. Put personalization in a private request.
  2. For mutable HTML, choose explicit, separate lifetimes such as public, max-age=60, s-maxage=300. This is a policy example, not a provider default or measured result.
  3. Send ETag and/or Last-Modified for mutable content. For a changed fingerprinted asset, publish a new URL such as /assets/app.20260923.js and use a long public lifetime only while that URL remains immutable.
  4. Review query, Vary, cookies, language, device/geo, compression, host, redirects, and the provider's effective key. Keep a query parameter when it changes the bytes.
  5. Record Cache-Control, Expires, validators, Age, Cache-Status when present, provider fields, and the redacted origin marker from a named vantage.
  6. Retain old assets long enough for old HTML and service workers, unless urgent removal needs an authorized, separately scoped containment action.

Rollback: prefer changing references to a retained version. A purge or invalidation is for a known stable object that must change before its normal lifetime.

Symptom-first incident path

For “old content,” “the browser did not update,” “unexpected sharing,” “the purge did not work,” or “the origin says it was not called,” preserve evidence before clearing caches or purging.

  1. Record identity. Save UTC time, URL after redirects, method, host, query, relevant request headers, a redacted cookie/auth description, browser/profile, network, navigation type, and displayed body marker or version. Different URLs, query order, redirects, or identities are different tests until proven equal.
  2. Ask whether a network request occurred. In the affected browser, record Network-panel request/initiator/timing/source details. With no request, check history/back-forward cache and service-worker control/Cache Storage. Chrome's Disable cache changes the experiment and does not bypass service workers, corporate proxies, CDNs, history restoration, or another profile. No request is not proof of an HTTP-cache hit, origin contact, or provider result.
  3. Repeat from controlled clients. Repeat the same method, URL, redirects, request inputs, and synthetic identity in the affected browser, a fresh profile with worker state recorded, and an authorized HTTP client from the same network. A request directive such as Cache-Control: no-cache asks for validation; it is not a universal bypass or purge.
  4. Name the serving hop. Capture status, Age, optional Cache-Status, Via, provider fields, Cache-Control, Expires, validators, Vary, Set-Cookie, Date, redirects, and request conditionals. A response header may be added, removed, or rewritten at a provider boundary.
  5. Compare a controlled marker. Change only a harmless origin phase from A to B between serialized requests and record a redacted origin counter. A named hit plus an unchanged counter supports reuse at that named cache; an origin increment proves that the instrumented origin received that request. Neither result proves the state of other layers.
  6. Audit variants and configuration. Compare query/order, cookies, authorization, language, encoding, origin, device/geo, host/scheme, redirects, method, and worker control. Read the effective matching rule and cache key. For unexpected sharing, stop the public rule if authorized, preserve captures, and assess exposure before purge.
  7. Close with a scope statement. Include URL, request variant, client/profile, named hop, time, and evidence. Say “this named cache reused this response for this request,” not “the CDN was stale,” unless the complete topology was measured.
Evidence sequence for an old response A request is checked for a network event, then compared with a named intermediary, an origin marker and counter, and the downstream browser, service worker, and proxy limits. Request network?same URL? Named hop Age · StatusVia · time Origin marker phase A → Bcounter Downstream limits browser · workercorporate proxy · other hop Each observation narrows only its own layer.
Evidence sequence: request → named hop → origin marker → downstream limits. A missing field or clean result at one step remains scoped.

What an observation proves

ObservationScoped readingDoes not prove
pageshow.persisted === true and no requestHistory/back-forward cache can explain the display.That the HTTP cache supplied it.
Worker log reports a Cache.match hitThe worker/Cache API supplied this client response.That browser HTTP or edge storage is empty.
Named Cache-Status: edge-test; hit and unchanged origin counterThe named cache reports satisfying this request without forwarding.Other POPs, hidden hops, or other users have the same result.
Origin counter increments and marker B is emittedThe instrumented origin received this request and produced B at that time.That a browser, worker, or upstream cache cannot later display A.
304 Not Modified with a matching ETagThe recipient evaluated a conditional request and said the stored representation could be reused.That the recipient was the origin, or that a purge occurred.
No Age, Cache-Status, or provider fieldNo positive diagnostic was exposed at this vantage.Origin contact, cache absence, or privacy safety.

Versioned URL versus named-provider purge

NeedPreferBoundary
Routine JS/CSS/image/font releaseNew versioned or content-hash URL, then update HTML and manifests.The old URL, old HTML, service worker, bookmark, or proxy can still exist.
Mutable HTML at a stable URLShort explicit freshness plus validators; narrow named-provider invalidation only when urgent.Browser history/cache, service worker, corporate proxy, and other hops may still show old HTML.
Emergency correction of a known provider objectAuthorized exact URL/path/tag/prefix purge or invalidation, followed by a same-path fetch.API success or completion proves the named operation, not universal eviction.
RollbackRestore references to a retained prior version; invalidate stable HTML only if needed.Documents that still reference another URL need their own update or expiry.
Private-response exposureCorrect representation policy and key; contain each named layer; purge known provider copies second.No purge proves that browser, worker, proxy, log, or another hop has no copy.

Browser/service-worker/corporate-proxy limits: a new URL makes a new target; it does not update a client that never receives new HTML or worker code. A named-provider purge changes only the provider's documented scope. Keep those boundaries in the incident record.

Named vendor sidebars

CloudFront · vendor-specific

  • Read the selected behavior and effective MinTTL, DefaultTTL, MaxTTL, cache policy, key, and response-headers policy together.
  • A positive CloudFront minimum can make the edge cache despite origin no-cache, no-store, or private. This is a CloudFront setting, not a new HTTP rule.
  • A response-headers policy can add or rewrite viewer Cache-Control without changing CloudFront object caching. Viewer headers are not edge-TTL proof.
  • Path invalidation is scoped to the named distribution and effective path/key rules. Versioned names help around local or corporate copies; neither is global deletion.
  • Configured CloudFront Server-Timing cache metrics are optional product evidence. Absence is unknown.

Read the CloudFront TTL and invalidation report →

Cloudflare · vendor-specific

  • Read the zone's Origin Cache Control state and matching Cache Rule. Edge Cache TTL can respect, bypass by default, or override origin signals; Browser TTL is separate.
  • Cloudflare documentation gives product-specific meanings to CF-Cache-Status and Age. Record the named path, tier/POP context, and configuration; do not use a viewer header as hidden Edge TTL proof.
  • Default and custom cache keys can select URL/query/header/cookie/host/device/geo/language dimensions subject to product and plan. A custom key is not a privacy guarantee.
  • URL, tag, prefix, hostname, and everything purges have different blast radii. A purge API 200 acknowledges receipt; it does not prove the object existed or was evicted everywhere.
  • Current Cloudflare pages describe no-cache differently in generic and OCC-specific contexts. Resolve the actual zone state with an authorized capture; do not generalize either wording.

Read the Cloudflare Cache Rules report →

What this proves / does not prove

What this report proves from standards and current documentation

  • HTTP separates storage audience, freshness, validation, key matching, stale use, named evidence, and browser/history/application boundaries.
  • no-cache is not no-store; private is not encryption; s-maxage is a shared-cache lifetime; If-None-Match wins over If-Modified-Since when both are sent.
  • CloudFront and Cloudflare document independent controls for edge eligibility/lifetime, viewer/browser lifetime, cache key, and invalidation/purge. Those controls remain named.
  • The common checks are representation review, storage audience, explicit browser/shared freshness, validators, key review, named-hop evidence, and downstream testing.

What this report does not prove

  • No CloudFront or Cloudflare response was observed as HIT, MISS, BYPASS, REVALIDATED, EXPIRED, stale, or privacy-leaking here.
  • No origin header alone proves the selected provider's edge behavior, and no 200, 304, old body, missing header, browser label, or purge receipt identifies every producer.
  • A fresh profile, direct client, one POP, one provider status, or one A/B marker does not prove that all alternate keys, tiers, partitions, browsers, workers, corporate proxies, or other hops are clear.
  • Versioned URLs do not delete old URLs. Provider invalidation/purge does not clear browsers, service workers, corporate proxies, history, other CDNs, or application caches.

Uncertainty: an authorized live probe still needs a fixed URL, sanitized controlled origin marker/counter, selected provider configuration, request variants, named vantage, and permission to capture and, if needed, purge synthetic objects. The current synthesis does not claim that probe was run.

Sources and continuity

Direct source pages were retrieved 23 Sep 2026 during 06:31:30–06:35:34 UTC. Standards are normative; browser pages are browser-specific; CloudFront and Cloudflare pages describe named products. The public evidence ledger records the same source set and retrieval date.

ClassDirect sourceUsed for
Standards-stableRFC 9111 · HTTP CachingStorage, key selection, freshness, validation, stale use, Age, directives, and browser/application boundary.
Standards-stableRFC 9110 · HTTP SemanticsValidators, Vary, conditional precedence, 304, and Via.
Standards-stableRFC 5861 · stale controls · RFC 9211 · Cache-StatusBounded stale extensions and optional named-cache diagnostics.
BrowserMDN · HTTP caching · MDN · Cache-Control · MDN · conditional requestsDeveloper-facing explanations of private/shared caching, directives, versioned assets, and validators.
BrowserChrome Network panel · Chrome Application panel · Chrome bfcache guidanceRequest logging, Disable cache limits, service workers, Cache Storage, and history restoration boundaries.
CloudFrontExpiration · Cache policies · Cache keyTTL bounds, origin interaction, and key dimensions.
CloudFrontResponse headers policies · Invalidation · Versioned objectsViewer-header boundary, named invalidation, and versioned URL limits.
CloudflareCache Rules · Cache Rule settings · Origin Cache ControlRule precedence, Edge/Browser TTL, OCC modes, and product-specific directive handling.
CloudflareCache responses · Revalidation · Cache keysCF-Cache-Status, Age, revalidation, and default/custom key dimensions.
CloudflarePurge overview · Single-file purge · Cache-key purgePurge receipt, scope, custom-key inputs, and downstream limits.

Earlier public reports

Search published pools, pages, reports, and evidence.