A look at Internet Explorer from the inside out. @EricLaw left Microsoft in 2012, but was named an IE MVP in '13 & an IE userAgent ( in '14

Vary with Care

Vary with Care

  • Comments 19

About the Vary Response Header 

As described in the HTTP/1.1 specification (RFC2616), the Vary response header allows a cache to determine if a cached (still fresh) response may be returned for a subsequent request, based on whether or not the new request's headers match those that were sent when the the previously response was originally cached.

  The Vary field value indicates the set of request-header fields that
  fully determines, while the response is fresh, whether a cache is
  permitted to use the response to reply to a subsequent request
  without revalidation. For uncacheable or stale responses, the Vary
  field value advises the user agent about the criteria that were used
  to select the representation.

The Problem

Unfortunately, the WinINET caching engine (below Internet Explorer and other applications) does not cache outbound request headers.  This limitation makes it impossible for WinINET to perform the request-header matching algorithm. 

Hence, Internet Explorer is conservative and generally will refuse to return a cached Vary response for a new request, except under special circumstances, as detailed below.

Internet Explorer 6

Internet Explorer 6 will treat an uncompressed response with a Vary header as completely uncacheable, unless the Vary header contains only the token User-Agent.  Hence, a subsequent request will be made unconditionally, resulting in a full re-delivery of the unchanged response. This results in a significant performance problem when Internet Explorer 6 encounters Vary headers.

Note: IE6 will ignore the Vary header entirely if the response was delivered with HTTP Compression; the header is dropped when URLMon decompresses the cache file on WinINET's behalf.

Internet Explorer 7

For Internet Explorer 7, the problem was not eliminated, but its impact was mitigated in some common cases. 

When evaluating a cached response that has a Vary, IE7 can make a conditional request (e.g. If-Modified-Since) rather than an unconditional request.

In order to take advantage of this improvement, the original response must contain an ETag.

Even though revalidation of cache response will require one round trip to server, it is still a significant improvement if server responds with a HTTP/304, because the response body is not transmitted.

Note, WinINET will remove the Vary: Accept-Encoding header if it decompressed the response.  Therefore, you should only send a Vary: Accept-Encoding header when you have compressed the content (e.g. Content-Encoding: gzip). 7.21.2009: see the comments below for a caveat on this.

Best Practices

  • Never send Vary: Host.  All responses implicitly vary by hostname, because the hostname is a part of the URI, and all requests vary by URI.
  • Only send a Vary: Accept-Encoding header when you have compressed the content (e.g. Content-Encoding: gzip).

7/14/2010 Update: Improved in IE9; IE9 will ignore Vary: Accept-Encoding, Vary: Host, and Vary: User-Agent, or any combination of these. You should still send an ETAG if you cannot avoid using VARY responses.

  • Eric, Is it fair to presume that in most cases... a web server that is serving up content with Expires and Cache-Control headers to explicitly cache static resources (CSS/JS/GIF/JPG/PNG) and not cache HTML pages should not need to send a Vary header... ever?

    e.g. if the server passes the correct headers for caching... can we ditch the Vary header completely?

    EricLaw: @Steve: The idea behind Vary is that the same URL may yield a different resource based on some factor in the headers. For instance, if I had a "Buy" PNG file, I could use VARY: Accept-Language and return a localized PNG file for a localized page. In practice, of course, sites will typically use a different URL for this purpose, because support for Vary is sporadic and causes cache bloat problems for shared caches.

  • Just a note - your "best practice":


    Only send a Vary: Accept-Encoding header when you have compressed the content (e.g. Content-Encoding: gzip).


    Will make pretty much every intermediary cache thrash, and violates HTTP. Anybody left at MSFT who can fix this? ;)

  • @Mark: No one at Microsoft updates IE6-9's functionality, if that's what you're asking; only security patches are issued. I'm afraid I don't understand your claim of "intermediary cache thrash"-- it would be interesting to have a fuller explanation of the problem you think would arise. It would also be interesting for you to be more explicit about where, exactly in RFC2616 requires "Vary" as real-world practice suggests that it's insufficiently plain.

  • In particular, it should be noted that, in virtually all cases I can think of, it would be preferable for the client to retrieve a locally cached albeit decompressed response in preference to a remote retrieval of a compressed version of the resource.

Page 2 of 2 (19 items) 12
Leave a Comment
  • Please add 2 and 6 and type the answer here:
  • Post