Every performance conversation eventually lands on the same truth: the fastest network request is the one that never happens, and the second-fastest is the one answered with 'you already have it'. HTTP caching is the machinery for both — old, universally deployed, and so widely misunderstood that half the web disables it by accident and the other half breaks deploys with it.
The whole system runs on a few headers deciding two questions: how long may a stored copy be reused without asking (freshness), and how do we ask cheaply when it expires (validation)?
Freshness: max-age and friends
Cache-Control is the contract. max-age says how many seconds the response may be reused without any network contact at all — the zero-round-trip case that makes repeat visits feel instant. public lets shared caches like CDNs store it; private restricts it to the one browser; no-store forbids storage entirely, which is the right call for personal or sensitive responses and wildly wasteful for everything else.
The trap is that a cached copy cannot be recalled. Serve your homepage HTML with a day of max-age and users will see Tuesday's page on Wednesday, whatever you deploy. Freshness is a promise about the future, so long freshness belongs only on content whose future you control — which leads directly to the one pattern that solves it.
The immutable-assets pattern
The modern playbook has two halves. Fingerprinted assets — files whose name contains a hash of their content, app.4f3a9c.js — get max-age of a year plus immutable, because a changed file gets a new name and is, by construction, a different URL. HTML gets little or no freshness but permits revalidation. Deploys then work like this: new assets upload under new names, the HTML that references them updates, and every browser picks up exactly the changed files with zero stale risk and zero unnecessary downloads.
Validation covers the HTML half. An ETag (a content hash) or Last-Modified date travels with the response; when freshness expires the browser sends it back — 'I have version 4f3a9c' — and the server answers either with new content or with 304 Not Modified, a headers-only reply that costs one round trip and no body bytes. Revalidation is not as fast as freshness, but it converts full downloads into tiny confirmations, and for HTML that is the right trade: always current, nearly free.
CDNs, and a checklist
A CDN is simply a shared cache you rent by the edge, obeying the same headers — with one superpower browsers lack: purging. That enables the advanced pattern — long shared freshness (s-maxage) for the CDN plus instant purge on deploy — and the gentler stale-while-revalidate, which serves the stored copy immediately while refreshing behind the scenes, hiding revalidation latency entirely. Together they give dynamic sites CDN speed with same-minute updates.
The checklist that prevents ninety percent of caching grief: fingerprint every static asset and cache it for a year as immutable; give HTML no-cache-style revalidation rather than long freshness; mark personal responses private or no-store so a shared cache never leaks one user's page to another; and confirm behaviour in the network panel — a served-from-cache asset and a 304 look very different from a silent re-download. Get those four right and your site ships fewer bytes than your competitors' by default, forever.