max-age=0 implies that the content is considered stale (and must be re-fetched) immediately, which is in effect the same thing as no-cache.
Google has failed to solve this mystery for me :(
max-age=0 implies that the content is considered stale (and must be re-fetched) immediately, which is in effect the same thing as no-cache.
Google has failed to solve this mystery for me :(
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 :)
I'm hardly a caching expert, but Mark Nottingham is. Here are his caching docs. He also has excellent links in the References section.
Based on my reading of those docs, it looks like max-age=0
could allow the cache to send a cached response to requests that came in at the "same time" where "same time" means close enough together they look simultaneous to the cache, but no-cache
would not.
The difference is that no-cache (no-store on Firefox) prevents any kind of caching. That can be useful to prevent pages with secure content being written to disk and for pages that should always be updated even if they are re-visited with the back button.
max-age=0 indicates that a cache entry is stale and requires re-validation, but does not prevent caching. Often browsers only validate resources once per browser session, so the content may not get updated until the site is visited in a new session.
Usually, browsers will not delete expired cache entries, unless they are reclaiming the space for newer content when the browser cache is full. Using no-store, no-cache allows a cache entry to be explicitly deleted.
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").
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 http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.1:
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.
IOW, 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)?
I believe shahkalpesh's answer applies to the user agent side. You can also look at http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.2.6.
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.
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.