How to set cache headers for static files
Cache-Control tells browsers how long to keep a file. Long lifetimes with versioned filenames make repeat visits instant.
Step by step, with screenshots: Browser caching: what to cache, for how long, and how to set Cache-Control →
Check your own site
Runs this check and the other 192, free, in about 45 seconds.
Or run only this check with the free HTTP/2 & HTTP/3 test.
What it is
The Cache-Control header is an HTTP response header that tells browsers and CDNs whether they may store a file and for how long, for example Cache-Control: public, max-age=31536000, immutable. It is how a server says "keep this logo for a year" or "always ask me again for this page".
The directives do different jobs: max-age sets the lifetime in seconds, no-cache allows storing but requires a check with the server before each use, no-store forbids storing at all, private keeps a response out of shared caches, and immutable says the file will never change at this URL. A static file with no Cache-Control is re-downloaded on every visit or kept for a lifetime the browser guesses.
OK looks like this: versioned images, CSS, JavaScript and fonts send a long max-age with immutable, and HTML sends no-cache or a short lifetime so updates show up at once. getReport lists static files that send no cache lifetime.
What a passing site looks like
- Static files have a cache lifetimewarning · −1.5 ptseffort S
Cache lifetime for static files
Why it matters. Without a cache lifetime, every visit downloads the same logo, CSS and scripts again. Returning visitors should get them from their browser in 0 ms.
- Send Cache-Control: public, max-age=31536000, immutable for versioned images, CSS, JS and fonts.
- Most caching plugins and CDNs set this for you; check the "browser cache" or "edge TTL" setting.
Questions people ask
What is the Cache-Control header?
Cache-Control is the HTTP header that sets caching rules for a response, for browsers and for shared caches such as CDNs. It holds one or more directives, such as max-age=3600, no-cache or private, separated by commas. It replaced the older Expires and Pragma headers.
What is the difference between no-cache and no-store?
no-cache lets the browser keep a copy but makes it ask the server whether the copy is still current before using it, which is quick when nothing changed. no-store forbids keeping a copy at all, so everything is downloaded again. Use no-cache for HTML and no-store only for sensitive data.
What does Cache-Control immutable mean?
immutable tells the browser that the file at this URL will never change during its max-age, so it should not even check with the server when the visitor reloads. Use it only for versioned files whose name changes when the content changes, such as app.3f9c2.js.
What is max-age in Cache-Control?
max-age is the number of seconds a response stays fresh, counted from when it was fetched. max-age=31536000 is one year, the usual value for versioned static files; max-age=0 means the copy must be revalidated before every use. s-maxage sets a separate lifetime for CDNs.
What is the difference between Cache-Control and ETag?
Cache-Control decides how long a stored copy can be used without asking the server. ETag is a version tag the server sends with a file, so that when the copy expires the browser can ask "has it changed?" and get a tiny 304 Not Modified answer instead of the full file. They work together.