Cache-Control no-cache vs no-store, what Chrome actually does (tested)

no-cache means 'cache it, but ask first'; no-store means 'don't keep it'. We measured what Chrome sent to the server for each common value when the page was opened again.

1. What reached the server on the second visit

Cache-Control on the fileRevisit / reload
no-cacheRequest with If-None-Match → 304, no body
max-age=0Same as no-cache: 304
max-age=0, must-revalidateSame: 304
no-storeFull 200 download again, no conditional request
no-cache, no-store, must-revalidateFull 200 again (no-store wins)
max-age=60 / private, max-age=60No request at all (served from cache, even on reload)
(no Cache-Control, only ETag + Last-Modified)No request at all

2. What that means

3. A sensible setup

# HTML: always current, cheap 304s
location / {
    add_header Cache-Control "no-cache" always;
}
# fingerprinted assets: cache for a year
location /assets/ {
    add_header Cache-Control "public, max-age=31536000, immutable" always;
}
# private pages
location /account/ {
    add_header Cache-Control "no-store" always;
}

private only tells shared caches (CDNs, proxies) not to store it; the browser still cached it in our test. ETags make the no-cache 304s work: see how nginx builds them. Inspect a URL's headers with curl -sI or the free HTTP headers tool.

Frequently asked questions

What is the difference between no-cache and no-store?

no-cache stores the response but checks with the server before each use; in our Chrome test that was a 304 with no body. no-store keeps nothing, so every visit was a full 200 download.

Is max-age=0 the same as no-cache?

In our Chrome test, yes: both (with or without must-revalidate) revalidated and got a 304 on every revisit.

Does no-cache, no-store, must-revalidate make sense?

It works, but in our test it behaved exactly like no-store alone. Use no-store for private data, no-cache for content that must be fresh.

Is a response without Cache-Control cached?

Yes. A script with only ETag and a two-hour-old Last-Modified was reused by Chrome without any request.

Written with AI assistance. Measured on 2026-10-01 in Chromium 153 (full build, new headless, fresh profile per row): a page loaded a script whose response carried each Cache-Control value plus ETag "v1" and a Last-Modified two hours old; the page was then opened again (revisit) or reloaded, and the server logged every request for the script and whether it answered 304. CDN behaviour for 'private' and the nginx lines are from the HTTP spec and nginx docs, not this test. PlainHeaders is our extension; curl and the HTTP headers tool are free.