Web & performance

Cache-Control: no-cache vs no-store vs max-age

Understand cache storage, revalidation and freshness, with concrete examples for HTML, private responses and versioned assets.

Photorealistic editorial photo for Cache Control No Cache No Store
Web & performance · Practical ideas for your next build

Cache-Control describes how a response may be stored and reused. Confusion usually starts with the name no-cache: it does not simply mean that a response must never be stored. Separate two questions before changing a policy. May a cache retain the representation, and under what conditions may it reuse that representation? The distinction makes deployment troubleshooting much easier than adding every directive that appears to mention freshness.

Separate storage permission from reuse

A response with no-store instructs caches not to store it. A response with no-cache may be retained, but reuse requires successful validation with the origin. When validators such as an ETag are available, that validation can result in a small 304 response instead of transferring the representation again. These directives serve different purposes. Review the sensitivity of the response and the desired reuse behavior rather than assuming their names are interchangeable. Also remember that a newly delivered directive does not magically delete every previously stored copy.

Use freshness for resources with a clear lifetime

A max-age value specifies a freshness lifetime in seconds. It does not mean the browser must download the resource after precisely that wall-clock interval; it controls whether a stored response is considered fresh for reuse. Versioned static assets can often tolerate a long freshness lifetime because a content change produces a different URL. Frequently changing HTML may instead require revalidation. Shared-cache rules such as s-maxage and private require additional attention when a CDN sits between the browser and origin.

Verify the actual response path

Inspect the response received by the browser, including Age and Vary when present. A CDN, reverse proxy or framework can add or replace the origin header, so editing one configuration file may not change the final policy. Avoid contradictory duplicate directives and test both a fresh navigation and a subsequent request. Our parser separates directives and flags malformed age values, but cannot determine the complete effective policy from one header string. Request context, status, validators and the behavior of the caches in the path still matter.

Worked example

EXAMPLE
HTML requiring validation:
Cache-Control: no-cache

Response that must not be stored:
Cache-Control: no-store

Versioned asset freshness:
Cache-Control: public, max-age=31536000

Does max-age=0 mean the same thing as no-store?

No. A zero freshness lifetime makes a stored response immediately stale; it does not itself prohibit storage.

Reference and further reading

Read the official documentation ↗