Please note, this is a STATIC archive of website developer.mozilla.org from 03 Nov 2016, cach3.com does not collect or store any user information, there is no "phishing" involved.

Revision 1107617 of HTTP caching

  • Revision slug: Web/HTTP/Caching
  • Revision title: HTTP caching
  • Revision id: 1107617
  • Created:
  • Creator: teoli
  • Is current revision? No
  • Comment
Tags: 

Revision Content

{{HTTPSidebar}}

The performance of web sites and applications can be signifcantly improved by reusing previously fetched resources. Web caches reduce latency and network traffic and thus lessen the time needed to display a representation of a resource. By making use of HTTP caching, Web sites become more responsive.

Different kinds of caches

A cache is a tool that stores versions of a given document and serve it back when requested. When a cache have a requested resource, it intercepts the requests and achieve several goals: it eases the load of the server that doesn't need to serve all clients itself, and it improves performances by being closer to the client: it takes less time to transmit the resource back. For a Web site, it is a major component in achieving high performance. On the other side, it has to be configured properly as not all resources stay identical forever: it is important to cache a resource only until it changes, not longer.

There several kinds of caches that can be grouped in two main categories: private or shared caches. A shared cache is a cache that stores responses to be reused by more than one user and a private cache is only dedicated to a single user. This page will mostly talk about browser and proxy caches, but there are also gateway caches, CDN, reverse proxy caches and load balancers that are deployed on web servers for better reliability, performance and scaling of web sites and web applications.

What a cache provide, advantages/disadvantages of shared/private caches.

Private browser caches

A private cache is dedicated to a single user. You might have seen "caching" in your browser's settings already. A browser cache holds all documents downloaded via HTTP by the user. This cache is used to make visited documents available for back/forward, saving, viewing-as-source, etc. without requiring an additional trip to the server. It likewise improves offline browsing of cached content.

Shared proxy caches

A shared cache is a cache that stores responses to be reused by more than one user. For example, an ISP or your company might have set up a proxy to serve thousands of users and popular resources are reused a number of times to reduce network traffic and latency.

Targets of caching operations

HTTP caching is an optional operation, but reusing a cached response is desirable often. However, common HTTP caches are typically limited to caching responses to {{HTTPMethod("GET")}} and may decline other methods. The primary cache key consists of the request method and target URI (oftentimes only the URI is used as only GET requests are caching targets). Common forms of caching entries are:

  • Successful results of a retrieval request: a {{HTTPStatus(200)}} (OK) response to a {{HTTPMethod("GET")}} request containing a resource like HTML documents, images or files.
  • Permanent redirects: a {{HTTPStatus(301)}} (Moved Permanently) response.
  • Error responses: a {{HTTPStatus(404)}} (Not Found) result page.
  • Incomplete results: a {{HTTPStatus(206)}} (Partial Content) response.
  • Responses other than {{HTTPMethod("GET")}} if something suitable for use as a cache key is defined.

A cache entry might also consist of multiple stored responses differentiated by a secondary key, if the request is target of content negotiation. For more details see the information about the {{HTTPHeader("Vary")}} header below.

Controlling caching

The Cache-control header

The {{HTTPHeader("Cache-Control")}} HTTP/1.1 general-header field is used to specify directives for caching mechanisms in both, requests and responses. Use this header to define your caching policies with the variety of directives it provides.

No cache storage at all

The cache should not store anything about the client request or server response. A request is sent to the server and a full response is downloaded each and every time.

Cache-Control: no-store
Cache-Control: no-cache, no-store, must-revalidate

No caching

A cache will send the request to the origin server for validation before releasing a cached copy.

Cache-Control: no-cache

Private and public caches

The "public" directive indicates that the response may be cached by any cache. This can be useful, if pages with HTTP authentication or response status codes that aren't normally cacheable, should now be cached. On the other hand, "private" indicates that the response is intended for a single user only and must not be stored by a shared cache. A private browser cache may store the response in this case.

Cache-Control: private
Cache-Control: public

Expiration

The most important directive here is "max-age=<seconds>" which the maximum amount of time a resource will be considered fresh. Contrary to {{HTTPHeader("Expires")}}, this directive is relative to the time of the request. For the files in the application that will not change, you can usually add aggressive caching. This includes static files such as images, CSS files and JavaScript files, for example.

For more details, see also the Freshness section below.

Cache-Control: max-age=31536000

Validation

When using the "must-revalidate" directive, the cache must verify the status of the stale resources before using it and expired ones should not be used. For more details, see the Validation section below.

Cache-Control: must-revalidate

The Pragma header

{{HTTPHeader("Pragma")}} is a HTTP/1.0 header, is not specified for HTTP responses and is therefore not a reliable replacement for the general HTTP/1.1 Cache-Control header, although it does behave the same as Cache-Control: no-cache, if the Cache-Control header field is omitted in a request. Use Pragma only for backwards compatibility with HTTP/1.0 clients.

Freshness

Once a resource is stored in a cache, it can theoretically be served by the cache forever. Caches have finite storage though periodically remove items they stored. This process is called cache eviction. On the other side, some resources may changes in the server, and the cache should be updated. As HTTP is a client-server protocol, servers can't contact caches and clients when a resource change; they have to communicate an expiration time for the resource. Before this expiration time, the resource is fresh, after its expiration time, the resource if stale. Eviction algorithm often privileges fresh resources over stale resources. Note that a stale resource is not evicted or ignored; when the cache receives a request for a stale resource, it forwards this requests with a {{HTTPHeader("If-None-Match")}} to check if it isn't in fact still fresh. If so, the server returns a {{HTTPStatus("304")}} (Not Modified) message and don't send the resource back, saving some bandwidth.

Here is an example of this process with a shared cache proxy:

Show how a proxy cache acts when a doc is not cache, in the cache and fresh, in the cache and stale.

The freshness lifetime is calculated based on several headers. If a "Cache-control: max-age=N" header is specified, then the freshness lifetime is equal to N. If this header is not present, which is very often the case, it is checked if an {{HTTPHeader("Expires")}} header is present. If an Expires header exists, then its value minus the value of the {{HTTPHeader("Date")}} header determines the freshness lifetime. Finally, if neither header is present, look for a {{HTTPHeader("Last-Modified")}} header. If this header is present, then the cache's freshness lifetime is equal to the value of the Date header minus the value of the Last-modified header divided by 10.
The expiration time is computed as follows:

expirationTime = responseTime + freshnessLifetime - currentAge

where responseTime is the time at which the response was received according to the browser.

Revved resources

The more we use cached resources, the better the responsiveness and the performance of a Web site will be. To optimize this, good practices recommend to set expiration times as far in the future as possible. This is possible on resources that are regularly updated, or often, but is problematic for resources that are rarely and infrequently updated. They are the resources that would benefit the most from caching resources, yet this make them very difficult to update. This is typical of the technical resources included and linked from each Web pages: JavaScript and CSS files change infrequently, but when they change you want them to be updated quickly.

Web developers invented a technique that Steve Sounders called revving[1]. Infrequently updated files are named in specific way: in their URL, usually in the filename, a revision number is added. That way each new revision of this resource is considered as a resource on its own that never changes and that can have an expiration time very far in the future, usually one year or even more. In order to have the new versions, all the links to them must be changed, that is the drawback of this method: additional complexity that is usually taken care by the tool chain used by Web developers. When the infrequently variable resources change they induce an additional change to often variable resources. When these are read, the new versions of the others are also read.

This technique has an additional benefits: it allows to guarantee that two resources can be updated at the same time and that caches will not lead to the situation where the old version of one of this resource is used with the new version of this other ones. This is very important when Web sites have CSS stylesheets or JS scripts that have dependencies and must be read coherently.

The revision version added to revved resources doesn't need to be a classical revision string like 1.1.3, or even a monotonously growing suite of number. It can be anything that prevent collisions, like a hash or a date.

Cache validation

Revalidation is triggered when the user presses the reload button. It is also triggered under normal browsing if the cached response includes the "Cache-control: must-revalidate" header. Another factor is the cache validation preferences in the Advanced->Cache preferences panel. There is an option to force a validation each time a document is loaded.

When a cached documents expiration time has been reached, it is either validated or fetched again. Validation can only occur if the server provided either a strong validator or a weak validator.

ETags

The {{HTTPHeader("ETag")}} response header is an opaque-to-the-useragent value that can be used as a strong validator. That means that the client, like the browser, has don't know what this string represents and can't predict it, even if it is not generated randomly on the server side. If the ETag header is present in a response, then the client can issue an {{HTTPHeader("If-None-Match")}} request header to validate the cached document.

The {{HTTPHeader("Last-Modified")}} response header can be used as a weak validator. It is considered weak because it only has 1-second resolution. If the Last-Modified header is present in a response, then the client can issue an {{HTTPHeader("If-Modified-Since")}} request header to validate the cached document.

When a validation request is made, the server can either ignore the validation request and response with a normal {{HTTPStatus(200)}} OK, or it can return {{HTTPStatus(304)}} Not Modified to instruct the browser to use its cached copy. The latter response can also include headers that update the expiration time of the cached document.

Varying responses

The {{HTTPHeader("Vary")}} HTTP response header determines how to match future request headers to decide whether a cached response can be used rather than requesting a fresh one from the origin server.

When a cache receives a request that can be satisfied by a cached response that has a Vary header field, it must not use that cached response unless all header fields as nominated by the Vary header match in both the original (cached) request and the new request.

The Vary header leads cache to use more HTTP headers as key for the cache.

This can be useful for serving content dynamically, for example. When using the Vary: User-Agent header, caching servers should consider the user agent when deciding whether to serve the page from cache. If you are serving different content to mobile users, it can help you to avoid that a cache may mistakenly serve a desktop version of your site to your mobile users. In addition, it can help Google and other search engines to discover the mobile version of a page, and might also tell them that no Cloaking is intended.

Vary: User-Agent

Because the {{HTTPHeader("User-Agent")}} header value is different ("varies") for mobile and desktop clients, caches will not be used to serve mobile content mistakenly to desktop users or vice versa.

See also

Revision Source

<div>{{HTTPSidebar}}</div>

<p class="summary">The performance of web sites and applications can be signifcantly improved by reusing previously fetched resources. Web caches reduce latency and network traffic and thus lessen the time needed to display a representation of a resource. By making use of HTTP caching, Web sites become more responsive.</p>

<h2 id="Different_kinds_of_caches">Different kinds of caches</h2>

<p>A cache is a tool that stores versions of a given document and serve it back when requested. When a cache have a requested resource, it intercepts the requests and achieve several goals: it eases the load of the server that doesn't need to serve all clients itself, and it improves performances by being closer to the client: it takes less time to transmit the resource back. For a Web site, it is a major component in achieving high performance. On the other side, it has to be configured properly as not all resources stay identical forever: it is important to cache a resource only until it changes, not longer.</p>

<p>There several kinds of caches that can be grouped in two main categories: private or shared caches. A shared cache is a cache that stores responses to be reused by more than one user and a private cache is only dedicated to a single user. This page will mostly talk about browser and proxy caches, but there are also gateway caches, CDN, reverse proxy caches and load balancers that are deployed on web servers for better reliability, performance and scaling of web sites and web applications.</p>

<p><img alt="What a cache provide, advantages/disadvantages of shared/private caches." src="https://mdn.mozillademos.org/files/13777/HTTPCachtType.png" style="height:573px; width:910px" /></p>

<h3 id="Private_browser_caches">Private browser caches</h3>

<p>A private cache is dedicated to a single user. You might have seen "caching" in your browser's settings already. A browser cache holds all documents downloaded via <a href="/en-US/docs/Web/HTTP" title="en/HTTP">HTTP</a> by the user. This cache is used to make visited documents available for back/forward, saving, viewing-as-source, etc. without requiring an additional trip to the server. It likewise improves offline browsing of cached content.</p>

<h3 id="Shared_proxy_caches">Shared proxy caches</h3>

<p>A shared cache is a cache that stores responses to be reused by more than one user. For example, an ISP or your company might have set up a proxy to serve thousands of users and popular resources are reused a number of times to reduce network traffic and latency.</p>

<h2 id="Targets_of_caching_operations">Targets of caching operations</h2>

<p>HTTP caching is an optional operation, but reusing a cached response is desirable often. However, common HTTP caches are typically limited to caching responses to {{HTTPMethod("GET")}} and may decline other methods. The primary cache key consists of the request method and target URI (oftentimes only the URI is used as only GET requests are caching targets). Common forms of caching entries are:</p>

<ul>
 <li>Successful results of a retrieval request: a {{HTTPStatus(200)}} (OK) response to a {{HTTPMethod("GET")}} request containing a resource like HTML documents, images or files.</li>
 <li>Permanent redirects: a {{HTTPStatus(301)}} (Moved Permanently) response.</li>
 <li>Error responses: a {{HTTPStatus(404)}} (Not Found) result page.</li>
 <li>Incomplete results: a {{HTTPStatus(206)}} (Partial Content) response.</li>
 <li>Responses other than {{HTTPMethod("GET")}} if something suitable for use as a cache key is defined.</li>
</ul>

<p>A cache entry might also consist of multiple stored responses differentiated by a secondary key, if the request is target of content negotiation. For more details see the information about the {{HTTPHeader("Vary")}} header <a href="#Varying_responses">below</a>.</p>

<h2 id="Controlling_caching">Controlling caching</h2>

<h3 id="The_Cache-control_header">The <code>Cache-control</code> header</h3>

<p>The {{HTTPHeader("Cache-Control")}} HTTP/1.1 general-header field is used to specify directives for caching mechanisms in both, requests and responses. Use this header to define your caching policies with the variety of directives it provides.</p>

<h4 id="No_cache_storage_at_all">No cache storage at all</h4>

<p>The cache should not store anything about the client request or server response. A request is sent to the server and a full response is downloaded each and every time.</p>

<pre>
Cache-Control: no-store
Cache-Control: no-cache, no-store, must-revalidate
</pre>

<h4 id="No_caching">No caching</h4>

<p>A cache will send the request to the origin server for validation before releasing a cached copy.</p>

<pre>
Cache-Control: no-cache</pre>

<h4 id="Private_and_public_caches">Private and public caches</h4>

<p>The "public" directive indicates that the response may be cached by any cache. This can be useful, if pages with HTTP authentication or response status codes that aren't normally cacheable, should now be cached. On the other hand, "private" indicates that the response is intended for a single user only and must not be stored by a shared cache. A private browser cache may store the response in this case.</p>

<pre>
Cache-Control: private
Cache-Control: public
</pre>

<h4 id="Expiration">Expiration</h4>

<p>The most important directive here is "<code>max-age=&lt;seconds&gt;</code>" which the maximum amount of time a resource will be considered fresh. Contrary to {{HTTPHeader("Expires")}}, this directive is relative to the time of the request. For the files in the application that will not change, you can usually add aggressive caching. This includes static files such as images, CSS files and JavaScript files, for example.</p>

<p>For more details, see also the <a href="#Freshness">Freshness</a> section below.</p>

<pre>
Cache-Control: max-age=31536000</pre>

<h4 id="Validation">Validation</h4>

<p>When using the "<code>must-revalidate</code>" directive, the cache must verify the status of the stale resources before using it and expired ones should not be used. For more details, see the <a href="#Cache_validation">Validation</a> section below.</p>

<pre>
Cache-Control: must-revalidate</pre>

<h3 id="The_Pragma_header">The <code>Pragma</code> header</h3>

<p>{{HTTPHeader("Pragma")}} is a HTTP/1.0 header, is not specified for HTTP responses and is therefore not a reliable replacement for the general HTTP/1.1 <code>Cache-Control</code> header, although it does behave the same as <code>Cache-Control: no-cache</code>, if the <code>Cache-Control</code> header field is omitted in a request. Use <code>Pragma</code> only for backwards compatibility with HTTP/1.0 clients.</p>

<h2 id="Freshness">Freshness</h2>

<p>Once a resource is stored in a cache, it can theoretically be served by the cache forever. Caches have finite storage though periodically remove items they stored. This process is called <em>cache eviction</em>. On the other side, some resources may changes in the server, and the cache should be updated. As HTTP is a client-server protocol, servers can't contact caches and clients when a resource change; they have to communicate an expiration time for the resource. Before this expiration time, the resource is <em>fresh</em>, after its expiration time, the resource if <em>stale</em>. Eviction algorithm often privileges fresh resources over stale resources. Note that a stale resource is not evicted or ignored; when the cache receives a request for a stale resource, it forwards this requests with a {{HTTPHeader("If-None-Match")}} to check if it isn't in fact still fresh. If so, the server returns a {{HTTPStatus("304")}} (Not Modified) message and don't send the resource back, saving some bandwidth.</p>

<p>Here is an example of this process with a shared cache proxy:</p>

<p><img alt="Show how a proxy cache acts when a doc is not cache, in the cache and fresh, in the cache and stale." src="https://mdn.mozillademos.org/files/13771/HTTPStaleness.png" style="height:910px; width:822px" /></p>

<p>The freshness lifetime is calculated based on several headers. If a "<code>Cache-control: max-age=N</code>" header is specified, then the freshness lifetime is equal to N. If this header is not present, which is very often the case, it is checked if an {{HTTPHeader("Expires")}} header is present. If an <code>Expires</code> header exists, then its value minus the value of the {{HTTPHeader("Date")}} header determines the freshness lifetime. Finally, if neither header is present, look for a {{HTTPHeader("Last-Modified")}} header. If this header is present, then the cache's freshness lifetime is equal to the value of the <code>Date</code> header minus the value of the <code>Last-modified</code> header divided by 10.<br />
 The expiration time is computed as follows:</p>

<pre>
expirationTime = responseTime + freshnessLifetime - currentAge
</pre>

<p>where <code>responseTime</code> is the time at which the response was received according to the browser.</p>

<h3 id="Revved_resources">Revved resources</h3>

<p>The more we use cached resources, the better the responsiveness and the performance of a Web site will be. To optimize this, good practices recommend to set expiration times as far in the future as possible. This is possible on resources that are regularly updated, or often, but is problematic for resources that are rarely and infrequently updated. They are the resources that would benefit the most from caching resources, yet this make them very difficult to update. This is typical of the technical resources included and linked from each Web pages: JavaScript and CSS files change infrequently, but when they change you want them to be updated quickly.</p>

<p>Web developers invented a technique that Steve Sounders called <em>revving</em><sup><a href="https://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/">[1]</a></sup>. Infrequently updated files are named in specific way: in their URL, usually in the filename, a revision number is added. That way each new revision of this resource is considered as a resource on its own that <em>never</em> changes and that can have an expiration time very far in the future, usually one year or even more. In order to have the new versions, all the links to them must be changed, that is the drawback of this method: additional complexity that is usually taken care by the tool chain used by Web developers. When the infrequently variable resources change they induce an additional change to often variable resources. When these are read, the new versions of the others are also read.</p>

<p>This technique has an additional benefits: it allows to guarantee that two resources can be updated at the same time and that caches will not lead to the situation where the old version of one of this resource is used with the new version of this other ones. This is very important when Web sites have CSS stylesheets or JS scripts that have dependencies and must be read coherently.</p>

<p><img alt="" src="https://mdn.mozillademos.org/files/13779/HTTPRevved.png" /></p>

<p>The revision version added to revved resources doesn't need to be a classical revision string like 1.1.3, or even a monotonously growing suite of number. It can be anything that prevent collisions, like a hash or a date.</p>

<h2 id="Cache_validation">Cache validation</h2>

<p>Revalidation is triggered when the user presses the reload button. It is also triggered under normal browsing if the cached response includes the "<code>Cache-control: must-revalidate</code>" header. Another factor is the cache validation preferences in the <code>Advanced-&gt;Cache</code> preferences panel. There is an option to force a validation each time a document is loaded.</p>

<p>When a cached documents expiration time has been reached, it is either validated or fetched again. Validation can only occur if the server provided either a <em>strong validator</em> or a <em>weak validator</em>.</p>

<h3 id="ETags">ETags</h3>

<p>The {{HTTPHeader("ETag")}} response header is an <em>opaque-to-the-useragent</em> value that can be used as a strong validator. That means that the client, like the browser, has don't know what this string represents and can't predict it, even if it is not generated randomly on the server side. If the <code>ETag</code> header is present in a response, then the client can issue an {{HTTPHeader("If-None-Match")}} request header to validate the cached document.</p>

<p>The {{HTTPHeader("Last-Modified")}} response header can be used as a weak validator. It is considered weak because it only has 1-second resolution. If the <code>Last-Modified</code> header is present in a response, then the client can issue an {{HTTPHeader("If-Modified-Since")}} request header to validate the cached document.</p>

<p>When a validation request is made, the server can either ignore the validation request and response with a normal {{HTTPStatus(200)}} <code>OK</code>, or it can return {{HTTPStatus(304)}} <code>Not Modified</code> to instruct the browser to use its cached copy. The latter response can also include headers that update the expiration time of the cached document.</p>

<h2 id="Varying_responses">Varying responses</h2>

<p>The {{HTTPHeader("Vary")}} HTTP response header determines how to match future request headers to decide whether a cached response can be used rather than requesting a fresh one from the origin server.</p>

<p>When a cache receives a request that can be satisfied by a cached response that has a <code>Vary</code> header field, it must not use that cached response unless all header fields as nominated by the <code>Vary</code> header match in both the original (cached) request and the new request.</p>

<p><img alt="The Vary header leads cache to use more HTTP headers as key for the cache." src="https://mdn.mozillademos.org/files/13769/HTTPVary.png" style="height:817px; width:752px" /></p>

<p>This can be useful for serving content dynamically, for example. When using the <code>Vary: User-Agent</code> header, caching servers should consider the user agent when deciding whether to serve the page from cache. If you are serving different content to mobile users, it can help you to avoid that a cache may mistakenly serve a desktop version of your site to your mobile users. In addition, it can help Google and other search engines to discover the mobile version of a page, and might also tell them that no <a href="https://en.wikipedia.org/wiki/Cloaking">Cloaking</a> is intended.</p>

<pre>
Vary: User-Agent</pre>

<p>Because the {{HTTPHeader("User-Agent")}} header value is different ("varies") for mobile and desktop clients, caches will not be used to serve mobile content mistakenly to desktop users or vice versa.</p>

<h2 id="See_also">See also</h2>

<ul>
 <li><a href="https://tools.ietf.org/html/rfc7234">RFC 7234: Hypertext Transfer Protocol (HTTP/1.1): Caching</a></li>
 <li><a href="https://www.mnot.net/cache_docs">Caching Tutorial – Mark Nottingham</a></li>
 <li><a href="https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching">HTTP caching – Ilya Grigorik</a></li>
</ul>
Revert to this revision