HTTP Caching
HTTP - Caching
Section titled “HTTP - Caching”HTTP caching is a crucial technique for improving website performance and reducing server load. By storing copies of frequently accessed resources closer to the client (e.g., in browser cache, proxy caches), subsequent requests for those resources can be served faster and without needing to contact the origin server.
The goals of HTTP caching are:
- Reduce latency: Serving content from a local cache is much faster than fetching it over the network.
- Reduce network traffic: Avoids redundant data transfers, saving bandwidth for both client and server.
- Reduce server load: Fewer requests reach the origin server, decreasing its workload.
HTTP/1.1 provides several mechanisms for controlling cache behavior, primarily through response headers set by the server. Key concepts include resource freshness and validation.
Cache-Control Header
Section titled “Cache-Control Header”The Cache-Control HTTP/1.1 general-header field is the primary way to specify caching policies for both requests and responses. It consists of a comma-separated list of directives.
Common Cache-Control Response Directives:
Section titled “Common Cache-Control Response Directives:”| Directive | Description |
|---|---|
| public | Indicates that the response may be cached by any cache (browser, proxy, CDN). |
| private | Indicates that the response is intended for a single user and MUST NOT be cached by a shared cache (e.g., a proxy). Browser caches can still store it. |
| no-cache | Forces caches to submit the request to the origin server for validation before releasing a cached copy. It does not mean “don’t cache”; it means “revalidate before use”. |
| no-store | The cache SHOULD NOT store anything about the client request or server response. This is for sensitive information. |
| max-age=<seconds> | Specifies the maximum amount of time in seconds that a resource is considered fresh. Relative to the time of the request. |
| s-maxage=<seconds> | Similar to max-age, but applies only to shared caches (e.g., CDNs, proxies). Ignored by private caches. |
| must-revalidate | Tells caches that they must obey any freshness information you give them about a resource. HTTP allows caches to serve stale resources under special conditions; this directive prevents that. |
| proxy-revalidate | Similar to must-revalidate, but applies only to shared caches. |
| immutable | Indicates that the response body will not change over time. The resource, if unexpired, should not be revalidated. Useful for fingerprinted static assets. |
| stale-while-revalidate=<seconds> | Allows a cache to immediately serve a stale resource while it revalidates it in the background. Improves perceived performance. |
| stale-if-error=<seconds> | Allows a cache to serve a stale resource if an attempt to revalidate it with the origin server fails (e.g., due to a network error or server error). |
Example: `Cache-Control: public, max-age=3600, s-maxage=7200, must-revalidate`Common Cache-Control Request Directives:
Section titled “Common Cache-Control Request Directives:”| Directive | Description |
|---|---|
| no-cache | The client wants a fresh response. The cache must revalidate with the origin server. |
| no-store | The client requests that the cache not store the request or any part of the response. |
| max-age=<seconds> | Indicates the client is willing to accept a response whose age is no greater than the specified time. |
| min-fresh=<seconds> | Indicates the client wants a response that will still be fresh for at least the specified number of seconds. |
| only-if-cached | The client only wants a cached response. The cache should not contact the origin server. |
Expiration Headers: Expires
Section titled “Expiration Headers: Expires”The Expires header is an older HTTP/1.0 header that provides an absolute date/time after which the response is considered stale.
Example: `Expires: Wed, 21 Oct 2025 07:28:00 GMT`If both Expires and Cache-Control: max-age (or s-maxage) are present, max-age (or s-maxage) takes precedence. Cache-Control is generally preferred for its flexibility.
Validation Headers: ETag and Last-Modified
Section titled “Validation Headers: ETag and Last-Modified”When a cached resource’s freshness lifetime expires (e.g., max-age is reached), or when Cache-Control: no-cache is used, the cache needs to revalidate the resource with the origin server. This is done using conditional requests with validator headers.
Last-Modified:
The server can include a Last-Modified header in its response, indicating the last modification date of the resource.
Example: `Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT`When revalidating, the client (or cache) can send this date back in an If-Modified-Since request header. If the resource hasn’t changed, the server responds with 304 Not Modified and an empty body, saving bandwidth. Otherwise, it sends 200 OK with the new resource.
ETag (Entity Tag):
An ETag is an opaque identifier assigned by the web server to a specific version of a resource. ETags provide more robust validation, especially when modification dates are not precise or sufficient (e.g., sub-second changes).
Example: `ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"`When revalidating, the client sends the ETag in an If-None-Match request header. If the ETag still matches the server’s current version, the server responds with 304 Not Modified. Otherwise, it sends 200 OK with the new resource and new ETag.
ETags can be “strong” (guaranteeing byte-for-byte identity) or “weak” (prefixed with W/, indicating semantic equivalence).
Caching Strategies
Section titled “Caching Strategies”- Cache immutable assets long-term: For assets like versioned JavaScript/CSS files (e.g.,
app.v1.2.3.js) or fingerprinted images, useCache-Control: public, max-age=31536000, immutable. Theimmutabledirective tells browsers they don’t need to revalidate these. - Cache dynamic content short-term or revalidate: For HTML pages or API responses that change, use shorter
max-agevalues, orno-cache(to force revalidation), orstale-while-revalidatefor better perceived performance. - No caching for sensitive data: Use
Cache-Control: no-storefor any responses containing private user data. - Use
Varyheader: If the response content depends on request headers (e.g.,Accept-Encodingfor compression,Accept-Languagefor internationalization), use theVaryheader to instruct caches to store different versions accordingly. Example:Vary: Accept-Encoding, Accept-Language.
Proper caching configuration is essential for a fast and scalable web application. It requires careful consideration of resource characteristics and user needs.