1. HTTP (Hypertext Transfer Protocol)

  1. Caching
    1. HTTP Features
    2. Stages
      1. Public/Shared Cache
      2. Private Cache
      3. Freshing a Cached Response
    3. Common Caching Directives
      1. Static, Unchanging Document
      2. Requiring revalidation
      3. Disabling storage
      4. Personalized document behind Cookie authorization
    4. Implementations
      1. Local Private Caches
      2. Public/Gateway/Server Cache
      3. CDN Cache services
    5. Configuring Caching Headers
      1. AWS S3
      2. Apache httpd
    6. Configuring Cache Storage
      1. Nginx
      2. Apache httpd
    7. History
    8. See also


HTTP caching allows a client or server to re-use a previous response, with the benefit of improving performance.

The process for setting if a response may be stored, when to re-use a stored response, and when to freshen a stored response with the origin server, is defined in RFC 9111: HTTP Caching.

HTTP Features


There's several components to caching a response and determining if a previous, cached response may be reused:

Public/Shared Cache

A public cache (typically synonymous with a shared cache) stores responses that may be made anonymously, or are otherwise available to the public, and can be re-used for other users. It is typically implemented by CDNs (content delivery networks), caching proxies, caching gateways, and origin servers (for requests to dynamic pages, to avoid re-computing a response).

Private Cache

A private cache additionally allows user-agents to cache responses available only to a certain users, or that are not accessible by the general public. For example, a list of private messages for a single user that may be cached—but only by that user.

Freshing a Cached Response

Sometimes a client wants to check with the origin server to verify if a previous response may be re-used, and possibly to update metadata associated with it (especially the cache entry expiration date). This is called freshing a response and is implemented with conditional requests.

Common Caching Directives

This documents different suggested ways to configure caching-related headers. See the Implementations section for specifying this header in your particular environment.

Static, Unchanging Document

Use this if the resource is content-addressable (the filename is based on the contents of the file), or the contents of the file are not expected to change (e.g. changes are tracked by uploading a new document with a unique version number).

Cache-Control: max-age=31104000

This response allows a cache to store the response for about one year (31104000 seconds is 360 days).

Requiring revalidation

Use this if the resource has a modest possibility of changing, and you always want the user-agent to check if there's a newer version available. For example, a currently playing song, task being worked on, or other thing. "Infrequent" is relative to how often the resource is accessed—if a user checks the resource every few seconds, infrequent could mean every few minutes.

ETag: {etag}
Last-Modified: {mtime}
Cache-Control: max-age=0

max-age=0 forces a stored response to always be considered "stale". This will cause the cache to send a conditional request to the origin server to check if the resource has changed; if it has not, the server will respond with 304 (Not Modified), and the stored response will be re-used.

The {etag} and {mtime} placeholders must be filled with a unique value that changes whenever the document does. Most HTTP servers automatically do this when serving files off the filesystem. See conditional requests for more information.

Disabling storage

If the response contains private information that must not be stored, use the no-store directive:

Cache-Control: no-store

If it's OK for clients to store the response, consider using the "requiring revalidation" technique above instead.

Personalized document behind Cookie authorization

Use this if the resource is a personalized document that doesn't change very often, you may want to allow clients to cache the response. Use the private directive to ensure that it is not stored by a shared cache; and use Vary: Cookie to ensure that the response is no longer served if the user logs out.

Cache-Control: private
Vary: Cookie


Local Private Caches

  • Firefox
  • Chrome
  • Safari

Public/Gateway/Server Cache

  • Apache httpd
  • nginx
  • Squid
  • ATS (Apache Traffic Server)
  • Varnish

CDN Cache services

  • Fastly
  • Akamai
  • AWS CloudFront
  • Cloudflare

Configuring Caching Headers


With aws-cli/2 accepts several arguments for setting cache-related headers on S3 objects, namely --cache-control and --expires. For example:

aws s3 sync <src> <dst> --cache-control "max-age=31104000"
aws s3 cp <src> <dst> --cache-control "max-age=31104000"

Apache httpd

Apache has extensive configuration options available for configuring caching options based on the type of document being served. See:

An example directive with mod_headers and mod_expires:

Header merge Cache-Control "max-age=31104000"

Configuring Cache Storage


Caches are configured separately in each module, for example, the fastcgi_cache and proxy_cache directives. (Note that what Nginx calls a "proxy" is actually a "gateway".)

Apache httpd

Apache has a single mechanism to cache responses from any inbound source, like requests forwarded to an origin server, a CGI script, or even resources from a slower filesystem (like spinning media or a network filesystem) when cached on a faster filesystem (like solid state media). See:


  1. 1999-06: Published in RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1
  2. 2014-06: HTTP Caching is published as a separate document during the rewrite, RFC 7234
  3. 2020-06: HTTP Caching is updated as part of a new cluster in RFC 9111

See also