AlgoPlusAlgoPlus
Learn/Web
Lesson

HTTP Caching

Don't fetch what you already have — freshness lets the browser reuse a copy with no network, and revalidation reuses it with just a 304.

9 min read Watch it move Build it

HTTP caching lets the browser skip downloads it doesn't need. A cache sits between the browser and the server and keeps past responses. While a stored copy is still fresh, the browser reuses it with *zero network*; once it goes stale, the browser asks 'has this changed?' instead of blindly re-downloading — and usually hears back 'no'.

Freshness — Cache-Control

When the server sends a file it tags the response with a Cache-Control header. The key directive is max-age, a freshness lifetime in seconds: for that long the browser may reuse its copy without asking the server at all.

  1. 1max-age=3600 — reuse this copy freely for one hour; it's fresh.
  2. 2no-cache — you may store it, but always revalidate before reuse (it doesn't mean 'don't cache').
  3. 3no-store — never write this to the cache at all (for private or sensitive responses).
  4. 4private — only the browser may cache it, not shared caches (CDNs, proxies).
  5. 5public — any cache along the path may store it.
no-cache vs no-store
The names mislead. no-store is the strict one — nothing is written to disk. no-cache *does* store the copy; it just forces a revalidation check every time before reusing it.

Revalidation — ETag and If-None-Match

Once a copy is stale, the browser doesn't re-download blindly. On the first response the server attached an ETag — a short fingerprint of the content (it changes whenever the content does) — and often a Last-Modified date. To revalidate, the browser sends a conditional request: If-None-Match: <etag> (or If-Modified-Since: <date>). If nothing changed, the server replies 304 Not Modified with *no body*, so only a few header bytes cross the wire instead of the whole file. The cached copy is reused as-is.

# First request — cache MISS
GET /style.css HTTP/1.1
Host: example.com

HTTP/1.1 200 OK
Cache-Control: max-age=3600, public
ETag: "a1b2c3"
Last-Modified: Wed, 01 Jul 2026 10:00:00 GMT
Content-Length: 18240
... 18 KB of CSS ...

# Later, copy is STALE — browser revalidates
GET /style.css HTTP/1.1
Host: example.com
If-None-Match: "a1b2c3"
If-Modified-Since: Wed, 01 Jul 2026 10:00:00 GMT

HTTP/1.1 304 Not Modified
ETag: "a1b2c3"
# no body — reuse the cached 18 KB
Two savings, one system
A fresh hit costs *no request at all*. A revalidated stale hit costs one tiny round trip and a header-only 304. Only a real change (or an empty cache) pays for the full download.
Check yourself
The browser has a stale copy with ETag "a1b2c3". It sends If-None-Match: "a1b2c3" and the content hasn't changed. What comes back?