Cache-Control header
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
The HTTPCache-Control
header holdsdirectives (instructions) in both requests and responses that controlcaching in browsers and shared caches (e.g., Proxies, CDNs).
In this article
Syntax
Cache-Control: <directive>, <directive>, ...
Cache directives follow these rules:
- Caching directives are case-insensitive. However, lowercase is recommended because some implementations do not recognize uppercase directives.
- Multiple directives are permitted and must be comma-separated (e.g.,
Cache-control: max-age=180, public
). - Some directives have an optional argument. When an argument is provided, it is separated from the directive name by an equals symbol (
=
). Typically, arguments for the directives are integers and are therefore not enclosed in quote characters (e.g.,Cache-control: max-age=12
).
Cache directives
The following table lists the standardCache-Control
directives:
Request | Response |
---|---|
max-age | max-age |
max-stale | - |
min-fresh | - |
- | s-maxage |
no-cache | no-cache |
no-store | no-store |
no-transform | no-transform |
only-if-cached | - |
- | must-revalidate |
- | proxy-revalidate |
- | must-understand |
- | private |
- | public |
- | immutable |
- | stale-while-revalidate |
stale-if-error | stale-if-error |
Note: Check thecompatibility table for their support; user agents that don't recognize them should ignore them.
Vocabulary
This section defines the terms used in this document, some of which are from the specification.
- (HTTP) cache
Implementation that holds requests and responses for reusing in subsequent requests. It can be either a shared cache or a private cache.
- Shared cache
Cache that exists between the origin server and clients (e.g., Proxy, CDN). It stores a single response and reuses it with multiple users — so developers should avoid storing personalized contents to be cached in the shared cache.
- Private cache
Cache that exists in the client. It is also calledlocal cache orbrowser cache. It can store and reuse personalized content for a single user.
- Store response
Store a response in caches when the response is cacheable. However, the cached response is not always reused as-is. (Usually, "cache" means storing a response.)
- Reuse response
Reuse cached responses for subsequent requests.
- Revalidate response
Ask the origin server whether or not the stored response is stillfresh. Usually, the revalidation is done through a conditional request.
- Fresh response
Indicates that the response isfresh. This usually means the response can be reused for subsequent requests, depending on request directives.
- Stale response
Indicates that the response is astale response. This usually means the response can't be reused as-is. Cache storage isn't required to remove stale responses immediately because revalidation could change the response from being stale to beingfresh again.
- Age
The time since a response was generated. It is a criterion for whether a response isfresh or stale.
Directives
This section lists directives that affect caching — both response directives and request directives.
Response Directives
max-age
Themax-age=N
response directive indicates that the response remainsfresh untilN seconds after the response is generated.
Cache-Control: max-age=604800
Indicates that caches can store this response and reuse it for subsequent requests while it'sfresh.
Note thatmax-age
is not the elapsed time since the response was received; it is the elapsed time since the response was generated on the origin server.So if the other cache(s) — on the network route taken by the response — store the response for 100 seconds (indicated using theAge
response header field), the browser cache would deduct 100 seconds from itsfreshness lifetime.
If themax-age
value is negative (for example,-1
) or isn't an integer (for example,3599.99
), then the caching behavior is unspecified. Caches are encouraged to treat the value as if it were0
(this is noted in theCalculating Freshness Lifetime section of the HTTP specification).
Cache-Control: max-age=604800Age: 100
s-maxage
Thes-maxage
response directive indicates how long the response remainsfresh in a shared cache.Thes-maxage
directive is ignored by private caches, and overrides the value specified by themax-age
directive or theExpires
header for shared caches, if they are present.
Cache-Control: s-maxage=604800
no-cache
Theno-cache
response directive indicates that the response can be stored in caches, but the response must be validated with the origin server before each reuse, even when the cache is disconnected from the origin server.
Cache-Control: no-cache
If you want caches to always check for content updates while reusing stored content,no-cache
is the directive to use. It does this by requiring caches to revalidate each request with the origin server.
Note thatno-cache
does not mean "don't cache".no-cache
allows caches to store a response but requires them to revalidate it before reuse. If the sense of "don't cache" that you want is actually "don't store", thenno-store
is the directive to use.
must-revalidate
Themust-revalidate
response directive indicates that the response can be stored in caches and can be reused whilefresh. If the response becomesstale, it must be validated with the origin server before reuse.
Typically,must-revalidate
is used withmax-age
.
Cache-Control: max-age=604800, must-revalidate
HTTP allows caches to reusestale responses when they are disconnected from the origin server.must-revalidate
is a way to prevent this from happening - either the stored response is revalidated with the origin server or a 504 (Gateway Timeout) response is generated.
proxy-revalidate
Theproxy-revalidate
response directive is the equivalent ofmust-revalidate
, but specifically for shared caches only.
no-store
Theno-store
response directive indicates that any caches of any kind (private or shared) should not store this response.
Cache-Control: no-store
private
Theprivate
response directive indicates that the response can be stored only in a private cache (e.g., local caches in browsers).
Cache-Control: private
You should add theprivate
directive for user-personalized content, especially for responses received after login and for sessions managed via cookies.
If you forget to addprivate
to a response with personalized content, then that response can be stored in a shared cache and end up being reused for multiple users, which can cause personal information to leak.
public
Thepublic
response directive indicates that the response can be stored in a shared cache. Responses for requests withAuthorization
header fields must not be stored in a shared cache; however, thepublic
directive will cause such responses to be stored in a shared cache.
Cache-Control: public
In general, when pages are under Basic Auth or Digest Auth, the browser sends requests with theAuthorization
header. This means that the response is access-controlled for restricted users (who have accounts), and it's fundamentally not shared-cacheable, even if it hasmax-age
.
You can use thepublic
directive to unlock that restriction.
Cache-Control: public, max-age=604800
Note thats-maxage
ormust-revalidate
also unlock that restriction.
If a request doesn't have anAuthorization
header, or you are already usings-maxage
ormust-revalidate
in the response, then you don't need to usepublic
.
must-understand
Themust-understand
response directive indicates that a cache should store the response only if it understands the requirements for caching based on status code.
must-understand
should be coupled withno-store
for fallback behavior.
Cache-Control: must-understand, no-store
If a cache doesn't supportmust-understand
, it will be ignored. Ifno-store
is also present, the response isn't stored.
If a cache supportsmust-understand
, it stores the response with an understanding of cache requirements based on its status code.
no-transform
Some intermediaries transform content for various reasons. For example, some convert images to reduce transfer size. In some cases, this is undesirable for the content provider.
no-transform
indicates that any intermediary (regardless of whether it implements a cache) shouldn't transform the response contents.
immutable
Theimmutable
response directive indicates that the response will not be updated while it'sfresh.
Cache-Control: public, max-age=604800, immutable
A modern best practice for static resources is to include version/hashes in their URLs, while never modifying the resources — but instead, when necessary,updating the resources with newer versions that have new version-numbers/hashes, so that their URLs are different. That's called thecache-busting pattern.
<script src="https://example.com/react.0.0.0.js"></script>
When a user reloads the browser, the browser will send conditional requests for validating to the origin server. But it's not necessary to revalidate those kinds of static resources even when a user reloads the browser, because they're never modified.immutable
tells a cache that the response is immutable while it'sfresh and avoids those kinds of unnecessary conditional requests to the server.
When you use a cache-busting pattern for resources and apply them to a longmax-age
, you can also addimmutable
to avoid revalidation.
stale-while-revalidate
Thestale-while-revalidate
response directive indicates that the cache could reuse a stale response while it revalidates it to a cache.
Cache-Control: max-age=604800, stale-while-revalidate=86400
In the example above, the response isfresh for 7 days (604800s).After 7 days it becomesstale, but the cache is allowed to reuse it for any requests that are made in the following day (86400s), provided that they revalidate the response in the background.
Revalidation will make the cache befresh again, so it appears to clients that it was alwaysfresh during that period — effectively hiding the latency penalty of revalidation from them.
If no request happened during that period, the cache becamestale and the next request will revalidate normally.
stale-if-error
Thestale-if-error
response directive indicates that the cache can reuse astale response when an upstream server generates an error, or when the error is generated locally. Here, an error is considered any response with a status code of 500, 502, 503, or 504.
Cache-Control: max-age=604800, stale-if-error=86400
In the example above, the response isfresh for 7 days (604800s). Afterwards, it becomesstale, but can be used for an extra 1 day (86400s) when an error is encountered.
After the stale-if-error period passes, the client will receive any error generated.
Request Directives
no-cache
Theno-cache
request directive asks caches to validate the response with the origin server before reuse.
Cache-Control: no-cache
no-cache
allows clients to request the most up-to-date response even if the cache has afresh response.
Browsers usually addno-cache
to requests when users areforce reloading a page.
no-store
Theno-store
request directive allows a client to request that caches refrain from storing the request and corresponding response — even if the origin server's response could be stored.
Cache-Control: no-store
max-age
Themax-age=N
request directive indicates that the client allows a stored response that is generated on the origin server withinN seconds — whereN may be any non-negative integer (including0
).
Cache-Control: max-age=10800
In the case above, if the response withCache-Control: max-age=10800
was generated more than 3 hours ago (calculated frommax-age
and theAge
header), the cache couldn't reuse that response.
Many browsers use this directive forreloading, as explained below.
Cache-Control: max-age=0
max-age=0
is a workaround forno-cache
, because many old (HTTP/1.0) cache implementations don't supportno-cache
. Recently browsers are still usingmax-age=0
in "reloading" — for backward compatibility — and alternatively usingno-cache
to cause a "force reloading".
If themax-age
value is negative (for example,-1
) or isn't an integer (for example,3599.99
), then the caching behavior is unspecified. Caches are encouraged to treat the value as if it were0
.
max-stale
Themax-stale=N
request directive indicates that the client allows a stored response that isstale withinN seconds.If noN value is specified, the client will accept a stale response of any age.
Cache-Control: max-stale=3600
For example, a request with the header above indicates that the browser will accept a stale response from the cache that has expired within the last hour.
Clients can use this header when the origin server is down or too slow and can accept cached responses from caches even if they are a bit old.
Note that the major browsers do not support requests withmax-stale
.
min-fresh
Themin-fresh=N
request directive indicates that the client allows a stored response that isfresh for at leastN seconds.
Cache-Control: min-fresh=600
In the case above, if the response withCache-Control: max-age=3600
was stored in caches 51 minutes ago, the cache couldn't reuse that response.
Clients can use this header when the user requires the response to not only befresh, but also requires that it won't be updated for a period of time.
Note that the major browsers do not support requests withmin-fresh
.
no-transform
Same meaning thatno-transform
has for a response, but for a request instead.
only-if-cached
The client indicates that an already-cached response should be returned. If a cache has a stored response, even a stale one, it will be returned. If no cached response is available, a504 Gateway Timeout response will be returned.
stale-if-error
Thestale-if-error
request directive indicates that the browser is interested in receiving stale content on error from any intermediate server for a particular origin.This is not supported by any browser (seeBrowser compatibility).
Use Cases
>Preventing storing
If you don't want a response stored in caches, use theno-store
directive.
Cache-Control: no-store
Note thatno-cache
means "it can be stored but don't reuse before validating" — so it's not for preventing a response from being stored.
Cache-Control: no-cache
In theory, if directives are conflicted, the most restrictive directive should be honored. So the example below is basically meaningless becauseprivate
,no-cache
,max-age=0
andmust-revalidate
conflict withno-store
.
# conflictedCache-Control: private, no-cache, no-store, max-age=0, must-revalidate# equivalent toCache-Control: no-store
Caching static assets with "cache busting"
When you build static assets with versioning/hashing mechanisms, adding a version/hash to the filename or query string is a good way to manage caching.
For example:
<!-- index.html --><script src="/assets/react.min.js"></script><img src="/assets/hero.png" width="900" height="400" />
The React library version will change when you update the library, andhero.png
will also change when you edit the picture. So those are hard to store in a cache withmax-age
.
In such a case, you could address the caching needs by using a specific, numbered version of the library, and including the hash of the picture in its URL.
<!-- index.html --><script src="/assets/react.0.0.0min.js"></script><img src="/assets/hero.png?hash=deadbeef" width="900" height="400" />
You can add a longmax-age
value andimmutable
because the content will never change.
# /assets/*Cache-Control: max-age=31536000, immutable
When you update the library or edit the picture, new content should have a new URL, and caches aren't reused. That is called the "cache busting" pattern.
Use ano-cache
to make sure that the HTML response itself is not cached.no-cache
could cause revalidation, and the client will correctly receive a new version of the HTML response and static assets.
# /index.htmlCache-Control: no-cache
Note: Ifindex.html
is controlled under Basic Authentication or Digest Authentication, files under/assets
are not stored in the shared cache. If/assets/
files are suitable for storing in a shared cache, you also need one ofpublic
,s-maxage
ormust-revalidate
.
Up-to-date contents always
For content that's generated dynamically, or that's static but updated often, you want a user to always receive the most up-to-date version.
If you don't add aCache-Control
header because the response is not intended to be cached, that could cause an unexpected result. Cache storage is allowed to cache it heuristically — so if you have any requirements on caching, you should always indicate them explicitly, in theCache-Control
header.
Addingno-cache
to the response causes revalidation to the server, so you can serve afresh response every time — or if the client already has a new one, just respond304 Not Modified
.
Cache-Control: no-cache
Most HTTP/1.0 caches don't supportno-cache
directives, so historicallymax-age=0
was used as a workaround. But onlymax-age=0
could cause astale response to be reused when caches disconnected from the origin server.must-revalidate
addresses that. That's why the example below is equivalent tono-cache
.
Cache-Control: max-age=0, must-revalidate
But for now, you can simply useno-cache
instead.
Clearing an already-stored cache
There are no cache directives for clearing already-stored responses from caches onintermediate servers.
Imagine that clients/caches store afresh response for a path, with no request flight to the server. There is nothing a server could do to that path.
Clear-Site-Data: cache
can be used to clear every stored response for a site in the browser cache, so use this with care.Note that this will not affected shared or intermediate caches.
Specifications
Specification |
---|
HTTP Caching> # field.cache-control> |
HTTP Immutable Responses> # the-immutable-cache-control-extension> |
Browser compatibility
Loading…