Card 02/ 11

ConceptDifficulty: Beginner2 min

Cache-Control: max-age, no-cache, no-store, private and public

Five directives cover most API responses, and each answers who may store it and for how long.

The Cache-Control response header tells every cache what it may do with a response, through directives separated by commas. Five cover most API responses: max-age sets how long a copy stays fresh, no-cache allows storing but requires checking with the server before each use, no-store forbids storing at all, private allows only the user's own cache, and public allows shared caches too.

Common Cache-Control directives, who may store the response, for how long, and a typical endpoint
DirectiveWho may store itHow long it is used without askingTypical endpoint
max-age=3600Any cache, unless private is also setOne hourGET /products
s-maxage=600Applies to shared caches onlyTen minutes, overriding max-age thereA list a CDN may hold more briefly than browsers
no-cacheAny cacheNever; it revalidates before every useGET /orders/42, which must always be current
no-storeNobodyNot stored at allA password reset token, a payment card
privateOnly the user's own browserAs max-age saysGET /me
publicShared caches too, even for authenticated requestsAs max-age saysPublic data behind a login

Combining them. Directives combine: Cache-Control: private, max-age=60 lets the browser reuse a profile for a minute and keeps it out of the CDN. public, max-age=86400, immutable says a versioned file such as /assets/app.3f9a.js will never change, so caches need not even revalidate.

Defaults by kind of data.

  • Public data that changes slowly, such as a product list: public, max-age with a lifetime the business can accept stale data for.
  • Personal data, such as an account page: private, with no-cache or a short max-age.
  • Secrets and one-time values, such as tokens and card details: no-store.

public is rarely needed. Shared caches already store most GET responses that have a max-age. public matters mainly for responses to requests that carried an Authorization header, which shared caches otherwise refuse to store.

Lifetimes are a business decision. A one-hour max-age means a price change may take an hour to reach every user. Choose the longest lifetime the data can be stale for, not the one that sounds efficient.

So set Cache-Control on every response, from three questions: may a shared cache keep it, how long may it be stale, and must it never be stored?