awesome-everything RU
↑ Back to the climb

Networking & Protocols

Tiered cache and Cache-Control

Crux How edge cache, origin shield, and Cache-Control directives cooperate so 90%+ of requests never touch origin — and what to set per content type.
Your altitude — climbing toward senior
ZeroJuniorMiddleSenior
You are at middle altitude — in the sky
◷ 12 min

Your CDN is in front of the origin, but the origin alarm is still firing on every deploy. New users miss the cache, every edge POP fetches from origin simultaneously, and suddenly 200 edge servers generate 200 parallel origin requests for the same uncached URL. This is not a bug — it is a missing architecture layer: the origin shield.

The four-layer cache hierarchy

When a browser makes a request, four caches may answer before origin:

  1. Browser memory cache (~sub-ms, in-tab lifetime)
  2. Browser disk cache (~10 ms, persists across tabs)
  3. CDN edge POP cache (~20–50 ms over the network from user)
  4. CDN origin shield / regional cache (~50–100 ms)

Only if all four miss does the origin server answer (~100–300 ms depending on geography). Each layer obeys the same Cache-Control directives but applies them independently.

Cache-Control directives

The Cache-Control response header tells every caching layer what to do with the response:

DirectiveMeaning
max-age=3600Fresh for 1 hour at both browser and CDN
s-maxage=86400Fresh for 1 day at CDN only (browser ignores s-maxage)
publicAny cache (browser, CDN, proxy) may store this
privateOnly the browser cache; CDN must not store
no-storeNo cache anywhere may store this response
no-cacheMust revalidate with origin before serving stored copy
stale-while-revalidate=604800Serve stale for up to 7 days while refreshing in background
immutableDo not revalidate — content will never change at this URL

Most important rule: without Cache-Control: public (or s-maxage) the CDN passes through — no caching happens. Origin response headers govern cacheability; the CDN cannot cache what the origin does not permit.

Cache-Control by content type
Static assets (content-hashed JS/CSS)
public, max-age=31536000, immutable
Images (with hash in URL)
public, max-age=31536000, immutable
HTML pages (frequently updated)
public, max-age=300, stale-while-revalidate=3600
API responses (public, read-only)
public, s-maxage=60, stale-while-revalidate=600
User-specific API (auth required)
private, no-store
Checkout / transactional pages
no-store

Origin shield architecture

Every CDN region may have dozens of edge POPs. Without a shield, a cache miss at all 200 POPs for a popular URL generates 200 simultaneous origin requests — a thundering herd.

Origin shield (called “Tiered Cache” at Cloudflare, “Origin Shield” at Fastly, same feature at CloudFront) is a regional intermediate cache between edge POPs and origin. All edge POPs in a region funnel their misses through one shield node. The shield maintains a larger cache; it typically absorbs 90%+ of misses without contacting origin.

Workflow for a cold URL:

  1. 200 edge POPs all miss simultaneously.
  2. All 200 forward to the regional shield.
  3. Shield has one outstanding origin request; the other 199 queue.
  4. Origin responds once; shield propagates to all 199 waiting edges.
  5. Origin saw 1 request instead of 200.

Static-asset versioning: making invalidation unnecessary

The cleverest cache trick: include the content hash in the filename (e.g. app.f3a2b8c.js). Set max-age=31536000, immutable (1 year). When the file changes, the hash changes, the URL changes — the cache has no entry for the new URL and fetches fresh automatically. No purge needed. Tools that do this automatically: Webpack, Vite, esbuild, Astro.

Cache invalidation patterns (when you need them)

  1. TTL expiry — wait for max-age to expire. Cheap, no API calls, but slow for urgent fixes.
  2. Explicit purge — CDN API call: POST /purge {"url": "/api/products"}. Fast, but slow when purging thousands of URLs per deploy.
  3. Cache tags — tag responses at origin (Cache-Tag: article-1001), purge by tag (POST /purge {"tag": "article-1001"}). Most flexible; requires CDN enterprise tier (Fastly, Cloudflare Enterprise).

Conditional requests and 304 Not Modified

After a browser’s local cache expires, it revalidates with If-None-Match: <etag>. If the response has not changed, the CDN (or origin) returns 304 Not Modified — empty body, saves bandwidth. CDNs handle ETags transparently for cacheable responses, forwarding to origin only when the ETag actually changed.

Quiz

What does the s-maxage directive do that max-age alone does not?

Quiz

Why are static-asset URLs typically content-hashed (e.g. app.f3a2b8c.js)?

Trace it
1/5

Trace a cold load of an article page through the full CDN cache hierarchy.

1
Step 1 of 5
Browser DNS-resolves the hostname. What does it get?
2
Locked
Browser opens TCP + TLS to the edge. Edge checks its local cache — cache miss. Where does the edge forward?
3
Locked
Origin responds. What does the response carry to be cacheable?
4
Locked
Shield caches the response and forwards to edge. Edge caches and returns to browser. Next user requests the same URL within 3600 seconds?
5
Locked
You deploy a new version of the article. Max-age is 3600 s and only 10 minutes have passed. How do users get the new version?
Order the steps

Order Cache-Control directives from most-cacheable to least-cacheable:

  1. 1 public, max-age=31536000, immutable — 1 year, never re-fetched
  2. 2 public, max-age=3600 — 1 hour at any cache
  3. 3 public, max-age=60, stale-while-revalidate=600 — 60s fresh, then stale-serve for 10 min
  4. 4 private, max-age=300 — browser only, 5 min
  5. 5 no-cache — caches must revalidate every request
  6. 6 no-store — no cache may store this at all
Recall before you leave
  1. 01
    Why is content-hashed URL versioning preferred over manual cache purges for static assets?
  2. 02
    An origin shield is between edges and origin. 200 edges all miss the same URL simultaneously. How many origin requests does the shield generate?
  3. 03
    Your HTML page has Cache-Control: public, max-age=3600. You push a hotfix deploy. Users continue seeing the old page for up to 1 hour. What is the fastest way to make all CDN edges serve the new version within seconds?
Recap

The CDN cache hierarchy has four layers — browser memory, browser disk, edge POP, and origin shield — each obeying the same Cache-Control directives. The key directives: max-age sets the freshness window for all caches; s-maxage overrides it for shared caches (CDN) only; private excludes CDN caching; no-store forbids all caching. The origin shield prevents thundering herds by collapsing all edge misses in a region into a single origin request. Content-hashed URLs with immutable, max-age=31536000 eliminate the cache invalidation problem for static assets entirely. For mutable content, choose between TTL expiry (simple), URL purge (fast but URL-specific), or cache-tag purge (flexible, requires enterprise tier).

Connected lessons
appears again in162
Continue the climb ↑Vary header and cache keys
shortcuts expand
search
K
prev piece
k
next piece
j
cycle tier
t
this menu
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.