The Core Difference
This comparison covers the directives as they apply to responses; similarly named request directives have related but distinct semantics.
The names are misleading. no-cache does not prevent storage. It allows a browser or shared cache to store the response, but requires the cache to validate that stored response with the origin before reuse. That validation normally requires a network request.
no-store is the directive that tells caches not to store the response. It is the appropriate default for highly sensitive, personalized responses when retaining a copy would create an unacceptable privacy or security risk.
| Behavior | no-cache | no-store |
|---|---|---|
| Cache may save the response | Yes | No |
| Reuse without contacting origin | No | No |
| Conditional validation with ETag or Last-Modified | Yes | Not applicable |
| Suitable for frequently changing public content | Yes | Usually wasteful |
| Suitable for highly sensitive responses | Not by itself | Yes |
What no-cache Does
With Cache-Control: no-cache, a cache can retain the response. Before reuse, it sends a conditional request using a validator such as If-None-Match or If-Modified-Since.
GET /account/preferences HTTP/1.1
Host: example.com
If-None-Match: "preferences-v8"
If the representation has not changed, the origin can return 304 Not Modified. The cache then reuses its stored body. This still requires a round trip, but avoids transferring the full representation.
Use no-cache when freshness must be checked on every use but retaining and conditionally reusing the body is acceptable. It works well for HTML documents, configuration responses, and other content that changes unpredictably.
What no-store Does
Cache-Control: no-store tells private and shared caches not to store the request or response. A later request needs a new response body from the origin because there should be no retained representation to validate.
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
{"recoveryCodes":["..."]}
Use no-store for responses containing secrets or unusually sensitive personal data, such as recovery codes, one-time credentials, or financial account details. Do not apply it to every authenticated response automatically: preventing storage also removes useful HTTP caching.
no-store is not a privacy or security guarantee. A malicious or compromised cache can ignore it, and the directive does not remove copies that were stored before the response changed to no-store. Continue to use HTTPS, access control, data minimization, and application-specific protections.
Which Directive Should You Choose?
Choose based on the consequence of retaining the response, not merely whether the content changes:
- Use
no-cachewhen the content may be stored but must be revalidated before reuse. - Use
no-storewhen storing the response itself is unacceptable. - Use
private, no-cachefor personalized content that a browser may retain and validate but a shared cache must not store. - Use
public, max-age=...for intentionally reusable public content with a known freshness period.
Try combinations in the Cache-Control Builder, then inspect a deployed response with the Header Inspector.
Common Mistakes
Treating no-cache as “do not cache”
The directive requires validation; it does not prohibit storage. Use no-store when retaining a copy is the actual risk.
Combining every restrictive directive
no-store, no-cache, max-age=0, must-revalidate is common cargo-cult configuration. no-store already prohibits storage, so revalidation directives add no useful behavior for compliant caches.
Using no-store to fix stale static assets
Hashed JavaScript, CSS, fonts, and images should normally use long-lived caching. Fix asset versioning instead of disabling storage globally.
Forgetting shared caches
For personalized responses that may be browser-cached, add private. It prevents a compliant shared cache from storing the response while still allowing private-cache behavior.