HTTP caching remains a cornerstone of web performance, yet its intricacies often elude even seasoned developers. The latest iteration, RFC 9111 (2022), refines how caches—from private browser stores to shared CDN and proxy layers—interpret directives to balance speed and freshness. Understanding these mechanics is critical for optimizing application responsiveness and reducing origin server load.

Article illustration 1

The Freshness Lifeline

Caches evaluate responses using two core metrics: age (time since last validation) and freshness lifetime (duration a response remains valid). RFC 9111 prioritizes freshness signals:
1. Cache-Control: max-age=<seconds> explicitly sets the lifetime
2. Expires and Date headers calculate a fallback interval
3. Heuristic methods using Last-Modified when explicit cues are absent

When responses exceed their freshness lifetime, they become stale—but not useless. Caches can validate stale content via conditional requests using If-Modified-Since (based on Last-Modified) or If-None-Match (leveraging ETag hashes). A 304 Not Modified response confirms validity, resetting the freshness clock without transferring redundant data.

Cache-Control Directives Demystified

RFC 9111 expands Cache-Control's vocabulary. Key response directives include:
- must-revalidate: Blocks stale reuse without validation; critical for authenticated content
- no-store: Attempts to prevent storage (volatile/non-volatile), though eavesdropping risks remain
- stale-while-revalidate=<seconds>: Permits stale serving during background revalidation
- immutable: Signals static content, suppressing refresh-triggered revalidations (though browser adoption varies)

Request directives express client intent:
- max-age=<seconds>: Demands responses younger than specified age
- no-cache: Forces revalidation before reuse
- only-if-cached: Restricts responses to cached content (failing to 504 Gateway Timeout)

Browser Refreshes: Soft vs. Hard

User-triggered reloads reveal caching’s practical nuances:
- Soft reloads (Ctrl/Cmd+R): Typically revalidate main resource (HTML) via conditional requests while loading sub-resources normally
- Hard reloads (Ctrl/Cmd+Shift+R): Bypass caches with Cache-Control: no-cache for all resources

Safari’s outlier behavior—using non-conditional requests for soft reloads—highlights implementation divergence.

Authenticated Caching: Proceed with Caution

Shared caches typically ignore Authorization-header requests unless overridden by:
- public
- s-maxage (which implies proxy-revalidate)
- must-revalidate
Combining these directives requires careful evaluation to avoid unintended data exposure.

The Evolving Cache Landscape

While RFC 9111 standardizes behavior, real-world gaps persist. Browser inconsistencies (like Safari’s reload quirks) and spotty support for directives like stale-if-error necessitate defensive coding. Yet the trajectory is positive: modern reload policies and tighter spec adherence reduce historical workarounds. As CDNs and browsers converge, developers gain finer control over the latency-freshness tradeoff—making mastery of HTTP caching more valuable than ever.

Source: HTTP caching, a refresher