Caching headers: Cache-Control and ETag
Caching is the reason a second visit to a site is fast. Three headers do most of the work.
Cache-Control
Cache-Control tells browsers and shared caches (a CDN, a proxy) what they may keep. Settings that matter most:
| Setting | Meaning |
|---|---|
max-age=3600 | A stored copy may be reused for 3,600 seconds without asking the server |
no-cache | A copy may be stored but must be checked with the server before each reuse |
no-store | Do not keep any copy |
public / private | A shared cache may keep it / only the user's own browser may |
immutable | The file will never change at this address, so do not check it again during max-age |
The names are confusing: no-cache does not mean "do not cache".
A file that never changes
Files with a version or hash in their name can be cached for a year. This is the response of our test server for a stylesheet:
GET /cache HTTP/1.1
Host: example.com
HTTP/1.1 200 OK
Date: Sat, 14 Nov 2026 10:00:00 GMT
Content-Type: text/css
Cache-Control: public, max-age=31536000, immutable
Content-Length: 6
body{}A private page
GET /nocache HTTP/1.1
Host: example.com
HTTP/1.1 200 OK
Date: Sat, 14 Nov 2026 10:00:00 GMT
Content-Type: text/html; charset=utf-8
Cache-Control: no-store
Content-Length: 14
<p>private</p>no-store is right for pages with private data, such as a bank balance. It means no reuse at all, so every visit downloads the page again.
Validation with ETag
An ETag is a label for one version of a file. The browser sends it back and the server can answer with a short 304 if nothing changed. First request:
GET /etag HTTP/1.1
Host: example.com
HTTP/1.1 200 OK
Date: Sat, 14 Nov 2026 10:00:00 GMT
ETag: "v7"
Cache-Control: max-age=60
Content-Type: text/plain; charset=utf-8
Content-Length: 13
version sevenSecond request, after the cached copy expired:
GET /etag HTTP/1.1
Host: example.com
If-None-Match: "v7"
HTTP/1.1 304 Not Modified
Date: Sat, 14 Nov 2026 10:00:00 GMT
ETag: "v7"
Cache-Control: max-age=60The 304 response has no body. The browser reuses its stored copy and updates its freshness. Read more on the 304 page.
A simple plan
- HTML pages:
no-cachewith anETag, or a shortmax-age. - Files with hashed names (CSS, JS, images):
max-age=31536000, immutable. - Private pages:
no-store.
Why does my change not show on the site?
A cache still has the old copy. Check the Cache-Control and Age headers in your browser's developer tools (Network tab), and change the file's address when you change its content.
Sources
- RFC 9111 HTTP Caching (rfc-editor.org/rfc/rfc9111)
- RFC 9110 section 15.4.5 (304 Not Modified)
Read on 14 November 2026.
This is an independent guide. It is not connected with the IETF, IANA, any browser maker or any company named here. Meanings were checked against the RFC texts on 14 November 2026. Responses shown were recorded on 14 November 2026 from a small test server on the author's own computer.