Caching makes sites faster and cheaper, but it can also show people stale data. Learn the layers of a cache, how Cache-Control works, and how to avoid the classic mistakes.

A cache is a saved copy of something that is expensive to produce, kept somewhere closer or quicker to reach. Done well, caching makes pages load instantly and cuts your server costs. Done badly, it shows visitors yesterday’s prices.

The trick is knowing which layer to use for which kind of content.

The layers of a cache

A single request can pass through several caches. Each one can answer without bothering the next.

Every hit at an earlier layer saves all the work after it.

Controlling the browser and CDN with headers

Your server tells browsers and CDNs how to cache a response using the Cache-Control header.

response header
Cache-Control: public, max-age=31536000, immutable
DirectiveWhat it means
max-age=NTreat the response as fresh for N seconds
publicAny cache, including a CDN, may store it
privateOnly the visitor’s own browser may store it. Use for personal data
no-cacheMay be stored, but must be checked with the server before each use
no-storeDo not store it at all. Use for sensitive responses
immutableThe file will never change at this URL, so do not even recheck
stale-while-revalidate=NServe the old copy for a while, and refresh it in the background

A strategy that works for most sites

Different content deserves different rules:

ContentSuggested approach
CSS, JavaScript and images with a hash in the file nameCache for a year with immutable. A new build gets a new file name
HTML pagesShort cache or no-cache with validation, so updates appear quickly
Public API data that changes slowlyCache for seconds or minutes, or use stale-while-revalidate
User specific or sensitive dataprivate or no-store

The “hash in the file name” trick, such as app.3f9a1c.js, solves the hardest part. Because the name changes whenever the content changes, you can cache the old name forever and never serve stale files.

Validation: checking without downloading

When a cached copy expires, the browser does not have to download everything again. It can ask, “has this changed?” using an ETag, a fingerprint of the content. If nothing changed, the server replies 304 Not Modified with no body, which is tiny and quick.

A cheap question replaces a full download.

The hard part: invalidation

Knowing when to throw a cached copy away is famously difficult. Some practical guidance:

  • Prefer expiry over manual purging. A short time to live (TTL) fixes itself.
  • Version your URLs for files that change, instead of purging.
  • Be careful with personal data. Never let a shared cache store one user’s private response.
  • Test with the network tab. Check headers and the “from cache” labels in your browser’s developer tools.