Skip to content

Caching & ETags

HTTP has a powerful caching model built in. Using it well means a client (or a CDN) can avoid re-downloading data that has not changed — often the single biggest performance win an API gets.

Cache-Control tells caches whether and how long a response may be reused:

Cache-Control: public, max-age=60 # any cache may reuse for 60s
Cache-Control: private, max-age=0 # only the client, must revalidate
Cache-Control: no-store # never cache (sensitive data)

While a response is fresh, the client reuses it with no request at all. Once stale, it revalidates.

An ETag is a validator — a fingerprint of the current representation. On the next request the client sends it back in If-None-Match; if it still matches, the server returns 304 Not Modified with no body:

sequenceDiagram
  participant C as Client
  participant S as Server
  C->>S: GET /articles/42
  S-->>C: 200 OK + ETag: "v7"
  Note over C: later...
  C->>S: GET /articles/42 (If-None-Match: "v7")
  S-->>C: 304 Not Modified (no body)
A matching ETag turns a full response into a tiny 304

Last-Modified + If-Modified-Since is the timestamp-based equivalent. ETags are more precise (they catch any change, not just second-level time changes).

JavaScript
What does a 304 Not Modified response contain?
Which header carries the validator a client sends back to revalidate?
Which Cache-Control directive means "never store this response"?