The cache-control header is the main mechanism for the HTTP server, which tells the caching proxy the "freshness" of the response, (i.e. how / if the response is stored in the cache for a long time)
In some situations, cache-control directives are insufficient. A discussion of the HTTP working group is archived here , describing a page that only changes in the language. This is not a valid use case for a variable header, but this context is valuable for our discussion. (Although I believe that the Vary header will solve the problem in this case, there is a better way.) From this page:
Vary strictly for those cases where it is hopelessly or overly complicated for a proxy server to replicate what the server will do.
A contrived example:
Your HTTP server has a large landing page. You have two slightly different pages with the same URL, depending on whether the user has been before. You distinguish between requests and the user "visits the account" based on cookies. But, since your server landing page is so large, you want mediation proxies to cache the response, if possible.
The URL, Last-Modified, and Cache-Control headers are not enough to give this view to the caching proxy, but if you add Vary: Cookie , the caching mechanism will add a Cookie header to its caching solutions.
Finally, for small traffic, dynamic websites - I always considered simple Cache-Control: no-cache, no-store and Pragma: no-cache sufficient.
Edit - to more accurately answer your question: the header of the Accept HTTP request defines the types of content that the client can process. If you have two copies of the same content at the same URL that differ only in the content type, then using Vary: Accept may be appropriate.
Update September 11th:
I include a couple of links that appeared in the comments, as this comment was originally posted. They are both excellent resources for real-world examples (and problems) using Vary: Accept; If you are reading this answer, you also need to read these links.
The first, from the outstanding EricLaw, from the behavior of Internet Explorer with the Vary header and some of the problems it presents to developers: Vary Header prevents caching in IE . In short, IE (pre IE9) does not cache any content that uses the Vary header because the request cache does not include HTTP request headers. EricLaw (Eric Lawrence in the real world) is a program manager on the IE team.
The second is from Eran Medan, and this is a constant discussion of the unexpected behavior related to Vary in Chrome: Backup does not handle the Vary header correctly . This is due to the behavior of IE, except that the Chrome developers took a different approach, although it did not seem to be a deliberate choice.