# Cache-Control: no-cache vs no-store

> Compare the no-cache and no-store Cache-Control response directives and choose the correct policy for sensitive or frequently changing responses.

Source: https://howhttpworks.com/compare/no-cache-vs-no-store
Last reviewed: 2026-10-04

> **TL;DR:** `no-cache` means a cache may store the response but must revalidate it with the origin before every reuse. `no-store` means do not store it at all. Neither is a security boundary on its own: for secrets use `no-store`, and for per-user pages add `private` so shared caches never keep them.

## 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`.

```http
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](https://howhttpworks.com/status-codes/304). 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
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 an instruction to compliant caches, not a 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-cache` when the content may be stored but must be revalidated before reuse.
- Use `no-store` when storing the response itself is unacceptable.
- Use `private, no-cache` for 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](https://howhttpworks.com/tools/cache-builder), then inspect a deployed response with the [Header Inspector](https://howhttpworks.com/tools/inspect).

## 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` plus `Pragma: no-cache` is common cargo-cult configuration. `no-store` already prohibits storage, so the revalidation directives add nothing for compliant caches. `Pragma: no-cache` is only defined for requests (RFC 9111 section 5.4) and is not a reliable response header.

### 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.

## Browser and CDN behavior

- A normal reload revalidates; a hard reload bypasses the cache. Back/forward navigation may show a stored page without any request, because history entries are not subject to normal freshness rules.
- Chrome's back/forward cache (bfcache) has historically skipped pages whose main resource is `Cache-Control: no-store`, so `no-store` can make back navigation slower. Chrome has been enabling bfcache for some such pages; check current Chrome documentation before relying on either behavior.
- A CDN given `no-cache` stores the object and revalidates against your origin each time. Use `private` for per-user responses, and `CDN-Cache-Control` (RFC 9213) when the CDN needs a different policy from browsers.

## Reproduce

```bash
curl -sI https://example.com/account | grep -iE '^(cache-control|etag|age|pragma|vary)'
curl -si https://example.com/app.js -H 'If-None-Match: "abc123"' | head -1   # 304 when the validator matches
```

An `Age:` header on a response marked `no-store` means some cache stored it anyway, typically a CDN rule that overrides origin headers.

## FAQ

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

`no-cache` allows storage but requires validation (an `If-None-Match` or `If-Modified-Since` request) before reuse. `no-store` forbids storing the response, so there is nothing to revalidate and every request returns a full body.

### Does no-cache mean the browser does not cache?

No. The browser keeps a copy and asks the origin whether it is still valid. If the origin answers 304 Not Modified the stored body is reused. Use `no-store` when you mean "do not keep a copy".

### Should I use no-store for authenticated pages?

Only where a stored copy is a real risk, such as account numbers, recovery codes or one-time tokens. For ordinary per-user pages `private, no-cache` keeps them out of shared caches while still allowing cheap conditional requests.

### Do I need both no-cache and no-store?

No. With `no-store` present a compliant cache stores nothing, so `no-cache` is redundant. The common `no-store, no-cache, must-revalidate` line is legacy belt-and-braces.

### What Cache-Control should HTML pages use?

For HTML that changes often and is not sensitive, `Cache-Control: no-cache` with a strong `ETag` gives fresh content and cheap 304 responses. Reserve long `max-age` with `immutable` for fingerprinted assets.

## References

- [RFC 9111: Cache-Control response directives](https://www.rfc-editor.org/rfc/rfc9111#section-5.2.2)
- [RFC 9111: Pragma (section 5.4)](https://www.rfc-editor.org/rfc/rfc9111#section-5.4)
- [RFC 9213: Targeted HTTP Cache Control](https://www.rfc-editor.org/rfc/rfc9213)
- [MDN: Cache-Control](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control)
