Web · 30 min read
Caching and CDNs
How copies of content near users cut latency and origin load, and how cache validators and CDNs keep those copies just fresh enough.
Why this exists
Every byte from a distant origin costs latency and money. Popular content is requested far more often than it changes.
Caching stores reusable responses closer to clients: in browsers, at organizational proxies, and on CDN edge nodes worldwide.
The hard part is not storing bytes. The hard part is correctness: serving fresh enough data without stampeding the origin on every click.
Axioms & primitives
- 01A cache trades freshness for latency and origin offload.
- 02HTTP caching metadata (Cache-Control, ETag, Last-Modified, Vary) is the shared language for that tradeoff.
- 03CDNs are geographically distributed caches (and more) in front of origins.
- 04Cache keys must include everything that changes the response meaningfully (see Vary).
- 05Private personalized responses must not be stored in shared caches.
- 06Invalidation is deliberately hard; design for explicit TTLs and purge paths.
Learning objectives
After this lesson you should be able to:
- Explain browser cache versus CDN edge cache versus origin in a request path story.
- Choose Cache-Control directives for a fingerprinted JS file versus an HTML document that changes often.
- Describe what an ETag revalidation request saves compared to a full download.
- Predict a cache fragmentation problem from a mismanaged Vary header.
- Outline why purging and TTLs are both needed operationally.
Progressive depth
Read the layers in order for a full explanation. Or open the layer you need.
Intuition
If a million users want the same logo, the origin should not draw it a million times across oceans. Store it near users.
Caching is that storage. A CDN industrializes it: many edges, anycast DNS, purge APIs, and TLS at the edge.
The price is staleness risk. Perfect freshness and perfect performance fight each other; headers declare the compromise.
Formal shape
Browser HTTP cache respects Cache-Control/Expires and validators. Shared caches (CDNs, proxies) additionally honor directives like private/public/s-maxage.
Validators: If-None-Match (ETag) and If-Modified-Since enable 304 responses. Vary lists request headers that must be part of the cache key (e.g. Accept-Encoding, Cookie carefully).
CDNs map hostnames to edges via DNS. Origin shield layers reduce thundering herds. Soft purge and stale-while-revalidate patterns keep UX smooth during refresh.
Fingerprinted filenames (app.abc123.js) allow immutable caching. HTML stays short-TTL and points at new fingerprints on deploy.
Worked examples
Static asset: Cache-Control: public, max-age=31536000, immutable with hashed name.
Personalized homepage: Cache-Control: private, no-store or short private max-age; never cache with Set-Cookie carelessly on shared edges.
API GET of public config: CDN caches 60s; clients still happy; origin load collapses.
Incident: wrong Vary: User-Agent shards cache into useless fragments. Hit ratio tanks.
Edge cases
Authenticated content at the edge needs signed URLs or token schemes; naive cookie caching is a data leak.
Normalization of query strings and trailing slashes affects hit ratio.
Stale-if-error can serve old content during origin outages; product must accept that tradeoff.
Browser BFCache and service workers add caches outside classical HTTP heuristics; debug with the right panel.
Mental models
Neighborhood bodega vs warehouse
CDN edges are bodegas. The origin is the warehouse. Most trips should end at the bodega.
Milk expiry dates
TTLs are expiry dates. Revalidation is sniffing the milk before pouring when the date is near.
Library reserve desk
ETags are edition marks. 'Do you still have edition 7?' can be answered with 304 Not Modified.
Common misconceptions
Myth
CDNs only make static images faster.
Reality
They also terminate TLS, absorb traffic spikes, protect origins, and cache many API GETs when headers allow.
Myth
Cache-Control: no-cache means do not store.
Reality
no-cache usually means revalidate before use. no-store means do not keep a copy.
Myth
Longer TTLs are always better.
Reality
They improve hit ratio and worsen staleness. Fingerprinting assets lets you cache forever safely.
Myth
If I deployed, users instantly see new content.
Reality
Caches keep old copies until TTL, revalidation, or purge. Design deploys accordingly.
Exercises
Work these without looking up answers first. Check yourself against the intent notes.
Exercise 01
Pick Cache-Control values for (a) index.html of an SPA, (b) /static/app.<hash>.js, (c) /api/me.
What good looks like
a short TTL/no-cache revalidate; b long immutable; c private no-store or equivalent.
Exercise 02
A deploy changed CSS but users still see old styles for an hour. Give two concrete causes and fixes.
What good looks like
Long TTL without fingerprint; CDN not purged. Fix: fingerprint+immutable; purge; shorten HTML TTL.
Exercise 03
Why is caching GET /users/me on a shared CDN dangerous if responses differ per Authorization header and Vary is unset?
What good looks like
One user may receive another's private representation; must Vary on Authorization or avoid shared cache.
Sources & further reading
External references. Prefer primary documents and clear explainers.
- MDN: HTTP caching
high
- RFC 9111 - HTTP Caching
high
- MDN: CDN
medium
Go deeper on your own
These picks go past the foundation in this lesson. Use them when you want a primary spec, official docs, or a longer walkthrough.
Normative cache freshness and validation rules. Use it when Cache-Control behavior surprises you.
Worked examples of validators and cache directives. Good before you tune CDN or browser caches.