Cache-Control Headers Explained: Faster Repeat Visits, No Stale Pages
3 min read4 October 2026By Muhammad Abdullah
Caching lets a browser or CDN keep a copy of a file and reuse it instead of downloading it again. Done well, repeat visits load almost instantly. Done badly, visitors keep seeing an old version of your site after you have deployed a fix. The Cache-Control header decides which of those you get.
The directives, in plain words
max-age=3600: the copy is fresh for 3600 seconds. Until then it is reused without asking the server.no-cache: you may store it, but check with the server before every use. Despite the name, it does cache.no-store: do not keep a copy at all. For sensitive responses such as account pages.public: shared caches like CDNs may store it.private: only the visitor's own browser may.s-maxage: a separate freshness time for shared caches, so a CDN can hold a file longer than browsers do.immutable: this file will never change, so do not even check while it is fresh.stale-while-revalidate=60: after expiry, keep serving the old copy for up to 60 seconds while fetching a new one in the background.
Checking is cheap: revalidation
When a cached copy needs checking, the browser sends a small request with the copy's ETag or Last-Modified date. If nothing changed, the server replies 304 Not Modified with no body, and the browser uses what it has. That saves the download but still costs a round trip, which is why truly unchanging files skip the check with immutable.
The two-rule setup that suits most sites
Modern build tools give static files names that include a hash of their content, such as app.3f9a1c.js. When the file changes, its name changes. That makes caching simple:
# files with a content hash in the name: JS, CSS, fonts, images
Cache-Control: public, max-age=31536000, immutable
# HTML pages
Cache-Control: no-cacheHashed files are cached for a year and never checked, because a new version always arrives under a new name. HTML is always checked, so visitors get the latest page right after a deploy, and that page points at the new file names.
Why visitors see the old site after a deploy
- The HTML was given a long max-age, so browsers keep the old page and never ask for the new one.
- A file without a hash in its name, like
style.css, was cached for a long time, so the new HTML loads the old stylesheet. - A CDN is holding the old copy. Purge the CDN on deploy, or keep HTML short-lived at the CDN with s-maxage.
Long caching is only safe for files whose name changes when their content does. Everything else should be short-lived or revalidated.
Common questions
What is the difference between no-cache and no-store?
no-cache stores the response but revalidates it with the server before each use. no-store forbids keeping a copy at all.
What Cache-Control should HTML pages use?
Usually no-cache, so browsers check for a new version every time and visitors get updates as soon as you deploy.
When should I use immutable?
For files with a content hash in their filename, together with a long max-age, since a changed file always gets a new name.