Browser Caching and Cache-Control Explained

Browser caching lets a visitor’s browser keep a local copy of your files — images, stylesheets, scripts — so repeat visits load them from disk instead of downloading them again. Done well, it makes second and subsequent page views feel instant. The whole system is controlled by a few HTTP headers, chiefly Cache-Control.

The short version

Use Cache-Control to tell browsers how long they may reuse a file. Cache static assets aggressively with a long max-age and immutable, and version their filenames so a change forces a fresh download. Keep HTML on a short cache or revalidate it. ETag handles efficient revalidation. Run a scan to see your current caching headers.

How the browser decides

When a browser needs a file it already has cached, it checks whether the cached copy is still “fresh.” If it is, the browser uses the local copy with no network request at all — the fastest possible outcome. If it might be stale, the browser asks the server whether anything changed. The Cache-Control header sets the rules for that decision.

Cache-Control directives

Cache-Control is a single header carrying one or more directives:

DirectiveWhat it does
max-age=SECONDSHow long the file stays fresh before revalidation
publicAny cache, including CDNs, may store it
privateOnly the user’s browser may cache it, not shared caches
no-cacheMay store, but must revalidate before each reuse
no-storeNever cache — for sensitive or personalized responses
immutableContent will never change, so skip revalidation entirely

A practical strategy

The trick is to treat two kinds of content differently.

Static assets: cache hard, version filenames

Stylesheets, scripts and images rarely change, so cache them for a year and mark them immutable:

Cache-Control: public, max-age=31536000, immutable

To push an update, change the filename — for example app.4f2a1c.css — so the new page references a new URL the browser has never cached. This “cache busting” through versioning is what lets you cache aggressively without ever serving a stale asset. Most build tools add the hash automatically.

HTML: keep it short-lived

HTML changes whenever content does, and it references your versioned assets, so it should not be cached for long. A short max-age or no-cache with revalidation keeps pages current:

Cache-Control: no-cache

ETag and revalidation

An ETag is a fingerprint the server attaches to a file. When a cached copy needs revalidating, the browser sends the ETag back with If-None-Match. If the file is unchanged, the server replies 304 Not Modified with no body — a tiny response that saves re-downloading the whole file. Last-Modified with If-Modified-Since works the same way using timestamps. ETags are most useful for HTML and other content you revalidate rather than cache immutably.

Tip: A CDN adds a second caching layer between your server and visitors. Use public so the edge can cache shared assets, and combine long asset caching with filename versioning for the best results. See our CDN guide and speed test.

Frequently asked questions

Won’t long caching stop users seeing my updates?

Not if you version filenames. The HTML points at a new asset URL after each change, so browsers fetch the update immediately while still caching unchanged files for a long time.

Should I use Cache-Control or Expires?

Prefer Cache-Control. It is newer, more expressive, and takes precedence over the older Expires header when both are present.

What should never be cached?

Anything personalized or sensitive — account pages, cart contents, authenticated API responses. Use Cache-Control: no-store so no cache retains a copy.

Related guides

Check your site against this guide

Run a free ScanOpsPro scan and see how your site handles the fundamentals.

Run a free scan