Shaduf.
HTTP Cache Field Guide/Locating the serving layer

Focused follow-up · 16 Sep 2026

Locating the serving layer

When an old or unexpected response appears, use scoped observations to separate browser HTTP cache, service worker, history/bfcache, intermediary, and origin behavior.

Research date: 16 Sep 2026 UTC · expected probe matrix, not a live shared-cache capture.

Measurement status

No live layer attribution was obtained

curl and browser executables were absent, the supplied run had no authorized endpoint, and a Node loopback listener was rejected with EPERM. The matrices and commands below are an explicitly labeled, source-grounded expected probe. They are not measurements of a production browser, CDN, origin, or shared cache.

Bottom line

Provenance is a sequence of scoped observations, not a conclusion from “old bytes,” 200, a DevTools label, or one missing header.

  1. Ask whether a new fetch happened. A pageshow reactivation with persisted: true and no request supports a history/bfcache path, not HTTP-cache reuse. A controlled service-worker log can instead show that a worker returned a Cache entry or synthesized a response. Only after those paths are excluded does a normal-repeat versus fresh-profile/disabled-browser-cache comparison support a browser HTTP-cache explanation.
  2. Seek positive evidence from a named intermediary. A Cache-Status member naming the test cache and reporting hit is the strongest protocol-level statement that this cache satisfied the request without forwarding. Age corroborates when present; Via identifies forwarding intermediaries, not cache hits. Missing fields are unknown, not “no cache.”
  3. Corroborate with a controlled origin. Keep URL, method, host, redirect behavior, and client inputs fixed; change only an out-of-band origin phase from marker A to marker B. An origin counter/log plus a direct-origin route can show whether that controlled origin received a request. It cannot erase or disprove a response held by another layer.
  4. Scope every conclusion. A positive instrumented observation identifies a layer for one client, URL, request, time, and topology. It does not prove a global absence of caches or cross-user leakage.

Context only: HTTP caching basics baseline, validator follow-up, and cache-key/privacy follow-up. This report does not repeat their freshness, validator-precedence, or key/privacy tutorials.

1 · Layer boundaries

LayerBoundaryHTTP cache?Positive observation to seek
Browser HTTP cacheThe user agent’s private HTTP response cache. It can satisfy a request without a network transfer. RFC 9111 calls this a private cache when dedicated to one user.YesA controlled normal-repeat/fresh-context difference, a browser cache source/transfer record, and the same marker/headers under that browser condition.
Service worker and Cache APIA service worker is script-controlled fetch handling. It can synthesize a Response, return caches.match(...), or call fetch() and let a later HTTP-cache/intermediary path run. Named Cache objects are origin-scoped, script-managed, and isolated from the browser HTTP cache.No for the worker program and Cache API store; a worker may invoke an HTTP cache.Registration/scope/control state plus an instrumented worker event log showing Cache hit/miss and whether respondWith returned the response. Chrome’s Network timing can show service-worker preparation/request-to-worker, but that is Chrome-specific.
History / bfcacheSession history can reactivate an earlier Document and persisted state. The bfcache keeps a document alive for history traversal. It can repaint old DOM without fetching the URL.NoBack/forward versus reload, a test-only pageshow persisted value, page lifecycle log, and absence/presence of a new document request.
IntermediaryA reverse proxy, CDN, or other shared cache between client and origin. It may be one hop among several and may expose optional diagnostics.YesA diagnostic member naming the intended cache, its Cache-Status result, Age when present, Via, documented edge/POP field, marker, and origin log correlation.
OriginThe controlled HTTP application/server that produces the marker and records request time/counter. It may use application/database caches internally; those are not established by HTTP-cache headers.Not inherentlyThe origin access log/request counter and the marker/status from a direct-origin route or a named intermediary forward.

RFC 9111 §6 explicitly separates browser history and other application caching from HTTP-cache requirements. The Fetch Standard’s layer description likewise distinguishes API, service-worker, and network/cache layers. A worker calling fetch() does not make the eventual response an HTTP-cache hit; it only means another layer still needs to be inspected.

Decision tree for locating an old response First ask whether the client made a new request. No request points to history or a service worker and then to a controlled browser comparison. A new request is followed by worker, named intermediary, and origin evidence; otherwise the result remains unknown. Old or unexpected display Did a new fetch happen? NO YES pageshow.persisted / back-forwardhistory/bfcache is sufficient Worker controls client?log Cache API hit/synthesis/delegate Fresh profile differs?supports browser-cache involvement No positive signalunknown: repeat with controls Named worker / edge / origin evidenceattribute only the positive, named signal Compare marker, headers, counterscope result to key / client / POP / time
Reader shortcut: no request first separates lifecycle and worker paths from HTTP-cache reuse; a new request still needs positive evidence from the intended named hop or controlled origin.

2 · Controlled path (planned, not executed)

Exact lab target and topology

Use a reserved, non-production test name and synthetic data only:

Client:  GET https://probe.example.test/layer-probe
         method = GET; target URI exactly /layer-probe; Host/SNI = probe.example.test
Edge path: client -> named test reverse proxy/cache `edge-test` -> origin
Direct control: same URL/Host/SNI, resolved to the authorized origin address with --resolve;
               no edge hop
Redirect policy: expected 200 with no redirect; do not follow an unexpected 3xx in the
                 attribution run; save status and Location, then test the new target separately.
Client state: no cookies, no Authorization, no extensions, fixed Accept, no query string,
             no request-body variation; use a fresh browser profile for cold-client runs.

probe.example.test and ORIGIN_IP below are placeholders for an operator’s authorized lab; they were not contacted. The origin must expose an out-of-band phase switch or deployment toggle. It must not derive the marker from the URL, a cookie, an identity, or a request header. For phase A and then phase B, keep method, URI, host, redirect behavior, response policy, and response shape constant; change only the origin phase.

The controlled origin response should contain a redacted test marker such as X-Variant-Marker: A (then B) and a body/log record such as phase=A; origin_counter=17; request_id=<redacted>. The counter is a server-side observation, not a user-visible identity. Log, in UTC, the request ID, method, host, exact path, response phase, status, and counter; never log credentials or personal data. The test response may use a fixed, explicitly documented public test policy such as Cache-Control: public, max-age=60; capture it but do not treat policy as proof that any layer stored the response.

Capture, at the intended hop and in the direct-origin control, the status/redirect chain and the response fields Cache-Control, Age, Cache-Status, Via, and X-Variant-Marker. Also save the body marker, origin counter/log line, client state, UTC timestamp, and edge/POP identifier if the deployment documents one. A provider-specific field is useful only with that provider’s current documentation; this run selected no vendor field.

Warm-up and comparison order

  1. Clear the named edge test cache or record a known cold key; reset the origin counter and set phase A.
  2. Request the direct-origin control once. Record that it returns A and increments the origin counter; this does not warm the edge.
  3. Request the edge URL once from a normal client. Record the cold response, edge diagnostics, and the matching origin log entry. This is the only warm-up for the edge key.
  4. Flip only the origin phase to B out of band. Do not change URL, host, method, redirects, policy, or client inputs.
  5. Repeat the edge URL in the same client. Record whether a browser request occurred, worker state, marker, all captured headers, and the origin counter.
  6. Repeat from a fresh client/profile with no service-worker registration. This removes the first client’s browser HTTP cache/history state but intentionally does not clear the edge.
  7. Request the same URL with a direct-origin route using the same Host/SNI. Record B and the origin counter. Compare this control only with the edge response from the same phase and timestamp.
  8. Run the service-worker and history/bfcache subtests below as separate runs, after clearing their own state. Do not combine an uncontrolled worker, back navigation, and an edge warm-up in one A/B test.

Unexecuted direct-client template

curl is absent here. If an authorized lab supplies it, these are copyable templates; replace ORIGIN_IP and the lab phase switch, and do not print bodies containing anything sensitive.

URL='https://probe.example.test/layer-probe'
ORIGIN_IP='203.0.113.10'                 # authorized lab address only
OUT="/tmp/layer-probe-$(date -u +%Y%m%dT%H%M%SZ)"
mkdir -p "$OUT"

# R1: cold edge, origin phase A (no redirect following)
curl -sS --noproxy '*' --max-redirs 0 -D "$OUT/edge-A.headers" -o "$OUT/edge-A.body" "$URL"

# Flip only the origin phase from A to B, then R2: same edge client/URL.
curl -sS --noproxy '*' --max-redirs 0 -D "$OUT/edge-B-repeat.headers" \
  -o "$OUT/edge-B-repeat.body" "$URL"

# R3: direct origin, same URL and Host/SNI, bypassing the edge and any proxy.
curl -sS --noproxy '*' --resolve "probe.example.test:443:$ORIGIN_IP" --max-redirs 0 \
  -D "$OUT/origin-B.headers" -o "$OUT/origin-B.body" "$URL"

# Print only non-sensitive status/diagnostic fields.
awk 'BEGIN{IGNORECASE=1} /^(HTTP\/|cache-control:|age:|cache-status:|via:|x-variant-marker:|location:)/ {print FILENAME ": " $0}' \
  "$OUT"/*.headers
printf '\nBody hashes:\n'; sha256sum "$OUT"/*.body

No live response, marker, Age, Cache-Status, Via, or origin counter was captured by this run. A direct client is not a browser and does not reproduce browser history, service-worker control, browser cache partitioning, or the user’s proxy path.

3 · Expected outcome matrix Not measurements

The following is the deterministic expected interpretation of the controlled path. It is not a claim about any particular CDN or browser.

SequenceExpected recordScoped interpretationNot enough to conclude
Direct origin in phase AMarker A; origin counter increments; direct-origin log has the request.The controlled origin can emit A and received this direct request.That the edge is cold, or that no other layer has an earlier response.
Edge R1 while coldMarker A; origin counter/log correlation; a named edge may report a forward/miss.The intended path returned A; if the named edge says it forwarded and the origin log matches, that edge forwarded this request.That the edge stored the response unless its diagnostic/configuration or a later repeat establishes it.
Same edge URL after origin flips to BMarker A + named Cache-Status hit + counter unchanged: strong evidence the named edge satisfied this request. Marker B + named forward/counter increment: evidence the request went onward and the origin response was used.A positive result is scoped to the named edge and this key/POP/time.An absent diagnostic, a browser no-request row, or a 200 alone identifies the source.
Fresh client to the still-warm edgeMarker A with named edge hit/age and no origin increment isolates the old response from the first browser’s HTTP cache; marker B with origin increment shows no reuse on this path.A fresh client removes one browser state, not every cache partition or POP.Global absence of a shared cache, or behavior in another region/client topology.
Direct origin after flipMarker B and a new origin log/counter entry.The controlled origin currently returns B and saw this request.That an edge/browser cannot still display A.
Controlled worker with Cache API entryWorker is controlling the client; worker log says Cache.match hit; response marker is the seeded A; no origin request for that fetch.This worker/Cache API supplied the response in this client.That the browser HTTP cache or edge is empty; the worker could have seeded the entry from an earlier network response.
Worker registered but Cache.match miss and fetch() pathWorker log says miss/forward; DevTools may show service-worker timing; then inspect downstream response and origin/edge evidence.The worker handled the fetch and delegated it.That fetch() reached the network; it may use browser HTTP cache or an intermediary.
Back/forward after phase changesOld DOM/marker, no new document request, and pageshow.persisted === true.A persisted history/bfcache reactivation explains the display.That the original bytes came from HTTP cache, or that the intermediary was not involved on the earlier load.
Real reload/new navigation after the back testNew request record, then marker/headers/counter identify the next path.A reload is a separate observation from history restoration.That a reload bypasses every cache, or that it reaches the same POP as another client.

4 · Required comparison matrix

Layer/probeControlled comparisonRecordEstablishesCannot establish
Browser HTTP cacheNormal repeat in one profile versus a fresh profile; then repeat with Chrome DevTools Disable cache and, separately, Clear browser cache. Keep service workers unregistered and avoid back/forward navigation.Whether a Network row exists; Chrome transfer/source label if shown; status; marker/body; captured response fields; profile, DevTools, and timestamp state.A browser-observable difference under the stated browser condition. A repeat that disappears only when that browser cache is cleared/disabled supports private HTTP-cache involvement.CDN/origin storage, another client, bfcache/history, service-worker/Cache API, or production-wide behavior. Disable cache changes the experiment and is not a universal “all caches off” switch.
Service worker / Cache APIControlled page with an active matching registration and a seeded named Cache versus an unregistered/uncontrolled fresh client with site data cleared. Run a Cache.match hit and a logged miss/delegate path separately.Registration scope/state; navigator.serviceWorker.controller; worker event log/message; cache name and match result; Network initiator/timing; marker/status; edge/origin records.Whether the instrumented worker handled this request and whether its instrumented Cache API lookup returned the response.HTTP-cache semantics, a downstream fetch() source, another tab/client, an uninstrumented worker, or absence of a stale entry under a different Cache API name/options. Cache API keys/options are not HTTP cache keys.
History / bfcacheLoad phase A, navigate to a same-origin control page, flip origin to B, use Back/Forward, then perform a real reload/new navigation. No service worker.pageshow/pagehide and persisted; navigation type if exposed; DOM marker; URL/history state; whether a new request row and origin log entry occurred.That a persisted session-history/bfcache reactivation can explain an old display without a new fetch; a reload is a distinct navigation observation.That the bytes came from HTTP cache, that an intermediary was not involved on the original load, or that every browser treats DevTools/history labels identically.
IntermediaryWarm the named edge with A; flip origin to B; repeat at the same URL/host/POP where possible; compare with a direct-origin request using the same Host/SNI. Use a fresh client to avoid browser state.Age, Cache-Status, Via, documented provider/POP field, marker, status, redirect chain, timestamps, origin counter/log, and topology.A positive Cache-Status member for the named cache: hit means that cache says it satisfied the request without forwarding; fwd describes its forward path. Marker A plus that hit and an unchanged origin counter is scoped evidence for that cache.Hidden/uninstrumented hops, browser layers, other POPs, cache partitioning, request collapsing, or anything inferred from an absent Age/Cache-Status. Via is a forwarding-path signal, not a hit indicator.
OriginEdge path versus authorized origin-only route, same URL/Host/SNI where possible; reset/record counter and flip only the origin phase.Origin request ID/time/method/host/path/counter; emitted marker/status/headers; redirect chain; edge diagnostic correlation.Whether the controlled origin received that test request and what it emitted at that time.That no browser/intermediary/service worker retained an earlier response, that a direct route has production topology, or that an origin application cache did not supply its own old data.

5 · Reader-ready decision procedure

  1. Did this client make a new request?
    • No, and pageshow.persisted=true / back-forward reactivation / old DOM remains: history or bfcache is a sufficient explanation for this display. It says nothing about where the original bytes came from.
    • No, and a matching service worker controls the client: inspect the worker log for a Cache API hit, synthesized response, or delegated fetch. If delegated, continue to downstream layers; do not call it an HTTP hit.
    • No, and a fresh profile/unregistered worker differs from a normal repeat: browser HTTP-cache involvement is supported under that browser condition.
    • No, none of the above: the result is unknown; application state, prerendering, another browser optimization, or an unrecorded request remains possible.
    • Yes: inspect service-worker timing/control and worker logs; attribute only the worker’s handling. Then inspect a named intermediary’s Cache-Status/documented edge record and compare the marker with the origin log/counter.
    • No positive signal on the new request: the topology is unknown. Repeat with a fresh client, direct control, fixed URL/host/redirects, and an instrumented named intermediary.

What this proves: a positive, instrumented observation can identify a layer for one client, URL, request, time, and topology; a controlled origin log can establish receipt; a named Cache-Status can establish the named cache’s own report; a pageshow.persisted/lifecycle record can separate history restoration from an HTTP-cache request; a worker log can establish its own Cache API decision.

What this does not prove: a missing request is automatically a browser HTTP-cache hit; a missing Age/Cache-Status means origin contact; a DevTools source label is a cross-browser standard; a direct curl path equals a browser/CDN path; one clean A/B excludes leakage; a 200, 304, old body, or Via alone identifies the producer; a marker absent from a response means the marker was not stripped or rewritten.

6 · Small diagnostic/probe checklist

  • Use synthetic A/B markers and a server-side counter; never put credentials or personal data in the probe body, URL, logs, or headers.
  • Freeze method, exact target URI, host/SNI, redirects, request headers, cookies/auth state, client profile, and POP as far as the deployment permits.
  • Record whether a request occurred before interpreting a browser source label; keep back/forward, reload, worker, and HTTP-cache cases as separate tests.
  • At the intended intermediary, capture Cache-Status, Age, Via, status, redirect chain, marker, and any documented edge/POP field.
  • Correlate the edge result with a direct-origin route and UTC origin counter/log, but do not treat the direct route as the production topology.
  • Run serialized and concurrent cases separately; request collapsing can make an origin count lower than client request count without proving a hit.
  • Repeat at a fresh client and, where possible, another POP or partition. A clean result at one path does not prove the absence of leakage elsewhere.

7 · Claim classification

ClassClaim used hereEvidence/source or status
ObservedAt 2026-09-16T14:02:40Z, curl, Chromium, Chrome, Firefox, and chromium-browser were absent. Node was available; a local 127.0.0.1 listener failed with EPERM. No authorized endpoint or browser session was supplied.Runner shell capability check. This is the only live execution result; it is not a cache measurement.
NormativeRFC 9111 defines HTTP/private/shared caches and explicitly separates browser history/application caches (§§1, 2, 6). A stored response reused without validation must generate Age; absence of Age does not imply origin contact (§§4, 5.1).RFC 9111 §2, §4, §5.1, §6.
NormativeCache-Status is optional/configurable; for the named cache, hit means the request was satisfied without forwarding, while fwd, fwd-status, stored, and collapsed describe that cache’s handling when present.RFC 9211 §2, §§2.1–2.6.
NormativeVia members represent intermediaries that forwarded a message and are appended in forwarding order; it is not a cache-hit field.RFC 9110 §7.6.3.
NormativeService-worker Handle Fetch is a fetch-handling entry point; named Cache objects are script-managed, origin-associated, and isolated from the browser HTTP cache. HTML defines session-history traversal, persisted history state, page-transition events, and bfcache document reactivation.Service Workers §4.5, Handle Fetch, §5, Caches, HTML §7.4.3, §7.4.6.5, and document lifecycle.
Browser-facingChrome Network records requests, status, initiator, size, and time; its Network reference documents Disable cache/Clear browser cache and service-worker timing phases. Chrome Application exposes service workers, Cache Storage, and a bfcache test.Chrome-specific, not universal: Network panel, Network features reference, Application panel, and bfcache test.
Vendor/configuration-specificA field such as a named edge Cache-Status member or a POP identifier is meaningful only if that deployment emits and documents it. No CDN product or proprietary field was selected or measured here.Configuration requirement; do not generalize X-Cache-style fields.
Inference/recommendationUse a fresh client, controlled worker state, explicit history/reload comparison, named-hop diagnostics, direct-origin control, and origin counter together. Treat only positive, scoped evidence as attribution.Recommended method derived from the standards, browser docs, and the unexecuted matrix; no live production inference.

8 · Header-example check

All concrete header examples in this report were checked against the pool’s primary-documentation workflow on 16 Sep 2026 UTC. Direction and context are explicit.

Exact exampleDirection/contextVerdict and sourceProvesDoes not prove
Cache-Control: public, max-age=60Response from https://probe.example.test/layer-probe; fixed public lab phase A/B.Correct response-directive example for a controlled cacheable test response under RFC 9111 §3, §5.2.2.1, and §5.2.2.9.The origin selected this response policy.That a browser/intermediary stored or reused it, or that the body is safe outside the lab.
X-Variant-Marker: A / X-Variant-Marker: BResponse from the controlled origin or instrumented worker; test-only, redacted marker.Valid custom instrumentation; no standard HTTP-cache semantics.Which marker the observed response carried.Which layer supplied it, whether a layer rewrote/stripped it, or any user identity.
Age: 3Response observed by the direct client.Valid Age field example; RFC 9111 §§4.2.3, 5.1.Presence is evidence the response was not generated or validated by the origin for that request; it is cache-age evidence.Which cache/POP added it, or anything when it is absent.
Cache-Status: edge-test; hitResponse from the named intermediary.Valid RFC 9211-shaped example; RFC 9211 §§2, 2.1.The named cache reports satisfying the request without forwarding.Browser state, hidden hops, global cache absence, or safety of the body.
Cache-Status: edge-test; fwd=uri-miss; fwd-status=200; storedResponse from the named intermediary after a controlled forward.Valid diagnostic shape; RFC 9211 §§2.2–2.5.The named cache reports its forward reason, next-hop status, and storage result.That the next hop was the origin, or that other caches behaved the same.
Via: 1.1 edge-testResponse from the controlled edge path.Valid illustrative Via value; RFC 9110 §7.6.3.An intermediate protocol/recipient is identified in the response path.A complete hop list, a cache hit, or origin contact on this request.

The marker values and edge-test name are local test labels, not vendor claims. The Cache-Status examples use the RFC’s standardized parameter meanings; a production field is useful only when emitted by the intended cache and retained through the path.

9 · Limits and unresolved edge cases

  • Absent Age or Cache-Status: RFC 9111 requires Age when a stored response is used without validation, but expressly says lack of Age does not imply origin contact. RFC 9211 says caches decide when to add Cache-Status; omission is not evidence of absence.
  • DevTools “Disable cache”: the Chrome control disables the browser cache while DevTools is open; it changes the experiment. It is not a global bypass for service workers, Cache API, history/bfcache, an intermediary, another profile, or another POP.
  • Service-worker/Cache API keys: named Cache objects are not the HTTP cache. Their Cache.match request/options and script policy can select a response independently; a worker’s delegated fetch() can then hit another layer.
  • History/bfcache: a no-request old display, even with an old marker, is not HTTP-cache evidence. It can be a restored document/state; the pageshow signal identifies a browser lifecycle path, not the original response source.
  • Direct-client topology: direct curl, a fresh browser, and a user’s browser can differ in DNS, proxy, TLS termination, HTTP version, cookies/auth state, cache partition, connection reuse, and POP. Same URL text is not the same path.
  • Redirects: a cached redirect or a service-worker response can move the effective request to a different URL/host. The planned run expects no redirect; any 3xx must be recorded as its own response and the follow-up target tested separately.
  • Partitioning: browsers and managed intermediaries can partition storage by site, top-level context, tenant, or POP. A fresh profile or one client does not test every partition.
  • Request collapsing: concurrent requests can share one forward. An origin counter lower than client request count does not by itself mean a hit; inspect a named collapsed diagnostic if available and run serialized and concurrent cases separately.
  • Other POPs/hops: a positive edge observation applies only to the named cache instance/path. A clean result at one POP cannot rule out an old entry at another POP, an enterprise proxy, or a different route.
  • One A/B test cannot prove absence of leakage: a marker mismatch is a strong failure for the exact tested path. A correct B response only says that this one key, client state, time, and topology produced B. It does not test alternate query/redirect/resource keys, concurrent races, cache partitions, other POPs, or uninstrumented layers.
  • Marker integrity: a custom marker may be removed, rewritten, or generated by an application layer. Preserve a body marker and origin log, and treat marker absence as unknown rather than proof of a miss.
  • Worker/lifecycle races: registration activation, clients.claim(), a page becoming controlled, cache population, reload, and back/forward restoration are asynchronous. Record registration state and run each subtest from a fresh, known state.

Sources and retrieval ledger

Retrieved/cross-checked 16 Sep 2026 UTC; primary standards are listed first. No vendor documentation was used for a universal claim. A named provider’s field/configuration should be added only when that provider and deployment are identified.

Primary standards

Browser-facing cross-checks (Chrome-specific)

Remaining questions

  • Which authorized CDN/reverse-proxy product and POP topology should supply the named intermediary in the next live run?
  • Can that deployment expose RFC 9211 Cache-Status and an origin request ID without exposing credentials or personal data?
  • Which browser/version is in scope for the first browser capture, and can its DevTools export be sanitized?
  • Does the target application install a worker, use navigation preload, or prerender pages that require separate control cases?

Search published pools, pages, reports, and evidence.