Crux Read real Cache-Control headers, response trace headers, and a layered hit/miss path, then pick the behaviour and the highest-leverage fix.
Your altitude — climbing toward senior
ZeroJuniorMiddleSenior
You are at senior altitude — in orbit
◷ 14 min
Cache bugs are diagnosed in the response headers and the per-layer trace, not in a diagram. Read the header, predict what each layer does, and choose the fix a senior makes first.
Goal
Practise the loop you run on every cache incident: read the Cache-Control directives and the trace headers, follow the request down the layer stack, and find which layer is lying before you touch a TTL.
An engineer adds this header to a personalized /me endpoint, then asks why the CDN hit ratio is 0% and origin load did not drop. What is correct?
Heads-up no-store wins — it forbids storage entirely, so max-age is dead weight. And caching a personalized response at a shared CDN would leak one user's data to another; the 0% ratio is correct, not a bug to fix here.
Heads-up private means only a user-private cache (the browser) may store it; shared caches like the CDN must not. It is the opposite of 'origin only' — and no-store forbids even the browser.
Heads-up The directives explicitly opt out of shared caching. A personalized endpoint should not be cached at the CDN; the 0% ratio is the header doing its job.
Snippet 2 — the trace headers
HTTP/1.1 200 OKAge: 240Cache-Control: public, max-age=300CF-Cache-Status: HITX-Cache: MISS from reverse-proxy
Quiz
Completed
A user reports stale data 4 minutes after a write. Reading these headers from the same response, what do you conclude?
Heads-up A proxy MISS means the proxy went upstream — but the CDN HIT in front of it short-circuited the request first, so the origin response was never used. The stale copy is the CDN's, not the origin's.
Heads-up Being within max-age is exactly why the CDN still serves it — that is the problem. The entry is 'fresh' by TTL but stale by data because the write did not purge it. TTL freshness is not data freshness.
Heads-up They describe two different layers — the CDN HIT and the reverse-proxy MISS — and are consistent: the request hit the CDN and never reached the proxy's upstream. Reading them per-layer is exactly how you locate the lying copy.
Snippet 3 — the layered hit/miss path
client → CDN edge → reverse proxy → app (Redis) → Postgres miss miss HIT (Redis) —
Quiz
Completed
A request misses the CDN and the reverse proxy but hits Redis at the app layer. For an in-region setup, what is the rough latency story, and what does it tell you?
Heads-up The trace shows the opposite: CDN and proxy both missed and forwarded. A hit deep in the stack means every layer above it added a miss hop. Layers do not share state — each is checked and forwards on a miss.
Heads-up A miss is normal cache behaviour, not breakage — it just means those upper layers do not hold this key. The signal is whether the hit ratio at each layer justifies keeping it for this traffic, not that caching failed.
Heads-up The trace ends at the Redis HIT — Postgres (—) was not queried. Redis saved the DB round trip on this request; the question is whether the CDN and proxy above it are pulling their weight.
A high-traffic, slightly-stale-tolerant feed switches to this directive and p99 drops sharply with no rise in origin load spikes. Why does it work?
Heads-up The opposite — stale-while-revalidate extends usability for 600s past max-age by serving the stale copy while refreshing in the background. Nothing is forced to wait on a fresh fetch within that window.
Heads-up It does not revalidate on every request — it serves the stale copy immediately and revalidates asynchronously. The data is intentionally slightly stale; that staleness tolerance is what buys the latency win.
Heads-up max-age=60 alone would cause a synchronous origin fetch (and a possible herd) at every expiry. The win is the stale-while-revalidate window decoupling user latency from revalidation — not the max-age value.
Recap
Cache behaviour is read in headers and traces. Cache-Control directives decide which layers may store a response — no-store forbids all, private forbids shared caches like the CDN — so a personalized endpoint correctly shows a 0% CDN hit ratio. Per-layer trace headers (CF-Cache-Status, X-Cache, Age) let you walk the stack and find which copy is stale: a CDN HIT within max-age that survived a write means the CDN was not purged. A hit deep in the stack means every layer above it added a miss hop, so confirm each layer earns its place. And stale-while-revalidate serves a stale copy instantly while refreshing in the background, cutting p99 and smoothing origin load for staleness-tolerant reads.