76

I have a couple of queries related to Cache-Control.

If I specify Cache-Control max-age=3600, must-revalidate for a static html/js/images/css file, with Last Modified Header defined in HTTP header:

  1. Does browser/proxy cache(like Squid/Akamai) go all the way to origin server to validate before max-age expires? Or will it serve content from cache till max-age expires?
  2. After max-age expiry (that is expiry from cache), is there a If-Modified-Since check or is content re-downloaded from origin server w/o If-Modified-Since check?
Intrications
  • 16,782
  • 9
  • 50
  • 50
nyb
  • 761
  • 1
  • 5
  • 3

3 Answers3

59

a) If the server includes this header:

Cache-Control "max-age=3600, must-revalidate"

it is telling both client caches and proxy caches that once the content is stale (older than 3600 seconds) they must revalidate at the origin server before they can serve the content. This should be the default behavior of caching systems, but the must-revalidate directive makes this requirement unambiguous.

b) The client should revalidate. It might revalidate using the If-Match or If-None-Match headers with an ETag, or it might use the If-Modified-Since or If-Unmodified-Since headers with a date.

james.garriss
  • 12,959
  • 7
  • 83
  • 96
  • 9
    To me the protocol is a bit ambiguous here, but in practice I have found that must-revalidate means it must revalidate regardless of max-age. – ColinM Mar 15 '12 at 00:44
  • 3
    @ColinM, What do you mean? must-revalidate means it must revalidate only when max-age is reached no? – Pacerier Aug 25 '13 at 07:20
  • Behavior seems to vary across browsers. I believe Firefox uses ColinM's interpretation, but in some recent work I'm finding that others (e.g. Chrome) apparently do not. – Joe Mabel Oct 21 '13 at 19:09
  • 7
    I'm calling "citation needed" on this answer. There seems to be some debate on whether it's accurate. – andrewrk Nov 24 '13 at 02:31
  • 23
    According to RFC2616[1], "When the must-revalidate directive is present in a response received by a cache, that cache MUST NOT use the entry *after it becomes stale* to respond to a subsequent request without first revalidating it with the origin server" This means that the official spec agrees with the answer, and not with @ColinM. http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.4 – andrewrk Nov 24 '13 at 02:40
  • 4
    @superjoe30 I agree that the answer is correct according to the RFC. My comment was just noting that *in practice*, some caches essentially ignore "max-age" when "must-revalidate" is present. Unfortunately I performed these tests a long time ago and do not remember which ones specifically.. Overall I'm pretty disappointed in the adherence to RFC of most caching reverse proxies (nginx, Apache, Cloudfront, etc..), and especially in the lack of support for things like true server-side content negotiation. – ColinM Dec 11 '13 at 17:20
  • @ColinM, I completely agree that not all caches adhere to the spec. That's true for so many things HTTP-related. – james.garriss Dec 11 '13 at 17:51
  • 1
    @ColinM thanks for the clarification. I hope it was clear that I was not attempting to bash your comment. It seems the "in practice" answer is often more useful than the "official spec" answer. – andrewrk Dec 12 '13 at 17:06
  • Correct me if I'm wrong but "MUST NOT use the entry after it becomes stale" in RFC does not say that it can't be revalidated before that time. So the answer to the first question should be "Yes, it may very well do that. You can't presume it to serve content from cache till max-age expires". So, in that sense @ColinM is partly right. – savehansson May 22 '15 at 19:08
  • Cache-Control Header: public, must-revalidate, proxy-revalidate,max-age=2592000 ETAG Header: "dcdff9f59bd1cf1:0" Last-Modified Header: Tue, 16 Sep 2014 10:49:59 GMT With these headers on a jpg response Chrome revalidates every time. I don't know if it's the "must-revalidate" or the presence of ETag and/or "Last-Modified" that triggers the behaviour. – savehansson May 22 '15 at 19:22
  • 1
    if we don't have the `must-revalidate` then what sort of ambiguity could we possibly have?! Using the `max-age` it didn't need to check before. After it should. – mfaani Jul 16 '17 at 12:32
  • I can prove @ColinM is right. My original understanding is the same as james.garriss's answer. But iOS's NSURLCache, will reach remote server every time a request is made in case of 'Cache-Control: must-revalidate, max-age=86400, private' and some etag. See my question here https://stackoverflow.com/questions/51778155/nsurlcache-together-with-nsurlsession-does-not-respect-cache-control-max-age – foresightyj Aug 20 '18 at 02:44
6

a. Look at the ‘Stats’ tab on this page and see what happens.

b. After expiration the browser will check at the server if the file is updated. If not, the server will respond with a 304 Not Modified header and nothing is downloaded.

You can check this behaviour yourself by looking at the ‘Net’ panel in Firebug or similar tools. Just re-enter the URL in the address bar and compare the number of HTTP requests with the number of requests when your cache is empty.

Marcel Korpel
  • 21,536
  • 6
  • 60
  • 80
1

The given answers are incorrect, at least for web browsers in 2019.

"After expiration the browser will check at the server if the file is updated" <- not true

I have a static file served with "Cache-Control: public,must-revalidate,max-age=864000" and both Chrome and Firefox do a request every time (and get a 304 Not Modified back every time).

mhenry1384
  • 7,538
  • 5
  • 55
  • 74
  • Are you sure? My chrome get "from memory cache" when setting "Cache-Control: public,must-revalidate,max-age=864000" in nginx – John Xiao Aug 18 '21 at 02:46
  • I believe this is an incorrect statement. [MDN says a 304 implicitly happens](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/304) for cached files. Further down it also notes that extra 304s could pop up just to display cached results in the dev tools. MDN still says that a `must-revalidate` "Indicates that once a resource becomes stale, caches must not use their stale copy without successful validation on the origin server." – JM_24 Aug 24 '21 at 04:59
  • I ran into a situation like this after adding `must-revalidate` to the caching policy of a specific file that previously only had `max-age` set. The problem was that the browser had retained the old `If-Modified-Since` value from a previous request so was always checking the resource and getting a 304 response. After clearing my cache the new policy was applied and now the file is served directly from memory/disk cache as expected. – Besworks Jun 10 '22 at 15:09