Effective caching is the single most impactful optimization for network performance. For senior engineers, moving beyond basic max-age involves understanding how intermediaries (CDNs, corporate proxies) interacts with browser caches.
Cache-Control Directives Deep Dive
The Cache-Control header is the primary mechanism for defining caching policies. It is a composite header allowing multiple directives.
- no-store: The most strict directive. No part of the request or response can be stored in any cache. Use this for highly sensitive data like banking transactions.
- no-cache: Counter-intuitively, this allows caching but requires validation with the origin server (via ETags or Last-Modified) before releasing the cached copy to the client. It effectively means "do not serve from cache without revalidation".
- must-revalidate: Similar to no-cache, but strictly for expired content. Once the max-age expires, the cache must verify with the origin. If the origin is unreachable, it cannot serve the stale content (unlike default behavior which might allow serving stale content on error).
Private vs. Public
In a distributed system, you have private caches (browser local storage) and shared caches (CDNs, ISPs).
- public: Marks the response as cacheable by any cache, even if it is normally non-cacheable or valid only for a specific user (e.g., HTTP authentication).
- private: Indicates that the response is intended for a single user and must not be stored by a shared cache. A CDN will respect this and bypass caching, while the browser will cache it.
Max-Age vs. S-Maxage
When you control both the edge (CDN) and the client experience, you often want different rules for each.
- max-age: Specifies the maximum amount of time (in seconds) a resource is considered fresh. Applies to all caches.
- s-maxage: Overrides
max-age but only for shared caches (CDNs). This allows you to cache content on the CDN for a short period (e.g., 1 minute) while allowing browsers to cache it for longer, or vice-versa.
Stale-While-Revalidate
This directive creates a non-blocking revalidation flow. It tells the cache: "If the content is expired, but within the stale window, serve the stale content immediately, then check for an update in the background." This completely eliminates latency spikes for users hitting expired content.
The Vary Header
When a response depends on request headers (like Accept-Encoding or User-Agent), shared caches need to know which variations to store. Failing to set Vary can result in a compressed Brotli response being served to a client that only supports Gzip, or a mobile layout served to a desktop user.