What's the difference between Cache-Control: max-age=0 and no-cache?

475,201

Solution 1

I had this same question, and found some info in my searches (your question came up as one of the results). Here's what I determined...

There are two sides to the Cache-Control header. One side is where it can be sent by the web server (aka. "origin server"). The other side is where it can be sent by the browser (aka. "user agent").


When sent by the origin server

I believe max-age=0 simply tells caches (and user agents) the response is stale from the get-go and so they SHOULD revalidate the response (eg. with the If-Not-Modified header) before using a cached copy, whereas, no-cache tells them they MUST revalidate before using a cached copy. From 14.9.1 What is Cacheable:

no-cache

...a cache MUST NOT use the response to satisfy a subsequent request without successful revalidation with the origin server. This allows an origin server to prevent caching even by caches that have been configured to return stale responses to client requests.

In other words, caches may sometimes choose to use a stale response (although I believe they have to then add a Warning header), but no-cache says they're not allowed to use a stale response no matter what. Maybe you'd want the SHOULD-revalidate behavior when baseball stats are generated in a page, but you'd want the MUST-revalidate behavior when you've generated the response to an e-commerce purchase.

Although you're correct in your comment when you say no-cache is not supposed to prevent storage, it might actually be another difference when using no-cache. I came across a page, Cache Control Directives Demystified, that says (I can't vouch for its correctness):

In practice, IE and Firefox have started treating the no-cache directive as if it instructs the browser not to even cache the page. We started observing this behavior about a year ago. We suspect that this change was prompted by the widespread (and incorrect) use of this directive to prevent caching.

...

Notice that of late, "cache-control: no-cache" has also started behaving like the "no-store" directive.

As an aside, it appears to me that Cache-Control: max-age=0, must-revalidate should basically mean the same thing as Cache-Control: no-cache. So maybe that's a way to get the MUST-revalidate behavior of no-cache, while avoiding the apparent migration of no-cache to doing the same thing as no-store (ie. no caching whatsoever)?


When sent by the user agent

I believe shahkalpesh's answer applies to the user agent side. You can also look at 13.2.6 Disambiguating Multiple Responses.

If a user agent sends a request with Cache-Control: max-age=0 (aka. "end-to-end revalidation"), then each cache along the way will revalidate its cache entry (eg. with the If-Not-Modified header) all the way to the origin server. If the reply is then 304 (Not Modified), the cached entity can be used.

On the other hand, sending a request with Cache-Control: no-cache (aka. "end-to-end reload") doesn't revalidate and the server MUST NOT use a cached copy when responding.

Solution 2

max-age=0

This is equivalent to clicking Refresh, which means, give me the latest copy unless I already have the latest copy.

no-cache

This is holding Shift while clicking Refresh, which means, just redo everything no matter what.

Solution 3

Old question now, but if anyone else comes across this through a search as I did, it appears that IE9 will be making use of this to configure the behaviour of resources when using the back and forward buttons. When max-age=0 is used, the browser will use the last version when viewing a resource on a back/forward press. If no-cache is used, the resource will be refetched.

Further details about IE9 caching can be seen on this msdn caching blog post.

Solution 4

In my recent tests with IE8 and Firefox 3.5, it seems that both are RFC-compliant. However, they differ in their "friendliness" to the origin server. IE8 treats no-cache responses with the same semantics as max-age=0,must-revalidate. Firefox 3.5, however, seems to treat no-cache as equivalent to no-store, which sucks for performance and bandwidth usage.

Squid Cache, by default, seems to never store anything with a no-cache header, just like Firefox.

My advice would be to set public,max-age=0 for non-sensitive resources you want to have checked for freshness on every request, but still allow the performance and bandwidth benefits of caching. For per-user items with the same consideration, use private,max-age=0.

I would avoid the use of no-cache entirely, as it seems it has been bastardized by some browsers and popular caches to the functional equivalent of no-store.

Additionally, do not emulate Akamai and Limelight. While they essentially run massive caching arrays as their primary business, and should be experts, they actually have a vested interest in causing more data to be downloaded from their networks. Google might not be a good choice for emulation, either. They seem to use max-age=0 or no-cache randomly depending on the resource.

Solution 5

max-age
    When an intermediate cache is forced, by means of a max-age=0 directive, to revalidate 
its own cache entry, and the client has supplied its own validator in the request, the 
supplied validator might differ from the validator currently stored with the cache entry. 
In this case, the cache MAY use either validator in making its own request without 
affecting semantic transparency. 

    However, the choice of validator might affect performance. The best approach is for the 
intermediate cache to use its own validator when making its request. If the server replies 
with 304 (Not Modified), then the cache can return its now validated copy to the client 
with a 200 (OK) response. If the server replies with a new entity and cache validator, 
however, the intermediate cache can compare the returned validator with the one provided in 
the client's request, using the strong comparison function. If the client's validator is 
equal to the origin server's, then the intermediate cache simply returns 304 (Not 
Modified). Otherwise, it returns the new entity with a 200 (OK) response. 

    If a request includes the no-cache directive, it SHOULD NOT include min-fresh, 
max-stale, or max-age. 

courtesy: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.4

Don't accept this as answer - I will have to read it to understand the true usage of it :)

Share:
475,201
rubyruy
Author by

rubyruy

Currently working on a private Python/Angular project. Previously back at working for isoHunt, this time in python. Previous to that as a python web/web-services programmer for Activision-Blizzard at Demonware. Previous to that worked as a ruby/rails developer at isoHunt. Previous to that that did CAN YOU MAKE US A PHP WEBSITE for everyone and their grandma.

Updated on April 27, 2021

Comments

  • rubyruy
    rubyruy about 3 years

    The header Cache-Control: max-age=0 implies that the content is considered stale (and must be re-fetched) immediately, which is in effect the same thing as Cache-Control: no-cache.

  • Pacerier
    Pacerier almost 12 years
    Good point, but in practice does any browsers actually do that?
  • Hank Gay
    Hank Gay almost 12 years
    @Pacerier I think this is more for caching proxy servers like Varnish, Squid, Traffic, etc.
  • Didier A.
    Didier A. over 11 years
    Wouldn't Cache-Control: max-age=0, must-revalidate, proxy-revalidate would be the exact equivalence of no-cache ?
  • Robert Christ
    Robert Christ over 10 years
    Similarly, IE 8 runs into all sorts of "could not download" issues when no-cache is used over https. suggested resolutions sometimes include changing headers to max-age=0
  • dana
    dana about 10 years
    Best answer for password protected content. private,max-age=0.
  • Craig London
    Craig London about 9 years
    Great answer, I went to read the article you site but the page is no longer valid. palisade.plynt.com/issues/2008Jul/cache-control-attributes
  • Michael Krebs
    Michael Krebs about 9 years
    Thanks, @CraigLondon. I redirected it to a cached version.
  • Michael
    Michael about 8 years
    This is incorrect. shift-refresh is a hard refresh which is more similar to no-store
  • Cees Timmerman
    Cees Timmerman about 8 years
    Verified in Firefox 45.0 which, like Chrome 49.0.2623.87 m, also sends a "Pragma: no-cache" when Shift+Refreshing.
  • user2067021
    user2067021 almost 8 years
    Section 14.9.4 Cache Revalidation and Reload Controls, HTTP 1.1 spec describes max-age=0 and no-cache quite well.
  • Cris Rockwell
    Cris Rockwell over 7 years
    There is a reference about the differences here... developers.google.com/web/fundamentals/performance/…
  • Patanjali
    Patanjali about 7 years
    must-revalidate is NOT meant to be the same as no-cache or no-store. The latter bypass caches altogether, but the former just says that a cache must always be checked for freshness, but if it is still current, it can be used, so saving bandwidth. The latter forces full end-to-end downloads all the time, taking up unnecessary bandwidth and delaying responses.
  • Xenos
    Xenos almost 7 years
    @DidierA. I would say max-age=0 makes only 1 real request if you trigger two HTTP requests at the exact same time while must-revalidate should always trigger 2 requests. But the showcase will be very hard to set up!
  • Franklin Yu
    Franklin Yu over 5 years
    @Patanjali no-cache doesn't "bypass caches altogether" or "force full end-to-end downloads all the time", at least not in all browsers. The specification only says that browser must validate the cache.
  • Patanjali
    Patanjali over 5 years
    @FranklinYu. Yes, specifically no-cache does only ask for revalidation, rather than full re-download, so it does involve a round-trip latency, but not a bandwidth hit. Because it allows a field-name list, it does seem to be designed as a mechanism for partial caching. The no-store only talks about preventing non-volatile memory storage, so in-memory caching is still OK. Pays to read the spec, because the terms don't really convey what their words really mean.
  • Patanjali
    Patanjali over 5 years
    css and js are suitable candidates for caching, as in production systems, they shouldn't really change often. However, having caching for them while developing is a pain, as that activity can require frequent forced cache-flushes. But, if one cannot use different settings for the different environments, production requirements should take precedent, as it has the most effect because the far larger numbers of accesses will save bandwidth, compared to the few Ctrl-F5 refreshes that a few developers will have to do. However, querying real-time data requires that cache-control work properly.
  • Franklin Yu
    Franklin Yu over 5 years
    @Patanjali I know, so how is that helping this question? must-revalidate with max-age=0 still looks the same as no-cache. I was targeting your claim "must-revalidate is NOT meant to be the same as no-cache or no-store", and the no-cache part (because I know about no-store).
  • Jackyef
    Jackyef about 5 years
    What would happen if no Cache-Control header is found? Will the browser just not cache the response? Does different browser has different behavior in this case?
  • Arcin B
    Arcin B almost 5 years
    max-age=0 and no-cache would result in different behaviour when max-stale request directive is used. with a max-stale request directive user would be able to get a stale response from the cache if the server ONLY sent max-age=0. But with no-cache, cache MUST revalidate before returning the cached response, no matter how fresh/stale the item is.
  • Arcin B
    Arcin B almost 5 years
    The language for must-revalidate is also similar in the sense that cache waits for the item to expire (become stale). After that it has to re-validate. Until then, it can be served and max-stale from the user can extend the time it can be served without validation
  • Rick Luo
    Rick Luo over 3 years
    But something is strange, Cache-Control: max-age=0, private, must-revalidate can return 304 in Firefox with ETag/If-None-Match, but always return 200 in Chrome, do you know the reason?
  • Florian F
    Florian F over 3 years
    People who understand what "must revalidate the cache" means probably already know what no-cache, no-store, max-age do. I don't. I am here because I want to know which option in a request header will force to go all the way to the server and request the resource regardless of any cache state or header or what.
  • Florian F
    Florian F over 3 years
    I actually tried to read that very page and didn't understand it. I came to stackoverflow in hope for a simple, clear answer.
  • jKlaus
    jKlaus over 2 years
    Your description is inaccurate. This is misinforming people.