HTTP Caching Headers, Demystified
Cache-Control, ETag, and stale-while-revalidate in plain terms.
The Problem
HTTP caching is easy to misconfigure. The wrong header can make users see stale private data or force every request back to the origin.
Why It Matters
Correct caching reduces latency, protects origin servers, and makes CDNs useful. Incorrect caching creates subtle production bugs: stale content, privacy leaks, and hard-to-debug behavior that changes between browser, CDN, and origin.
MDN, Cloudflare, Fastly, and Vercel all document these headers because HTTP caching is a core production tool, not a frontend-only detail.
Project Example
A public docs page can use Cache-Control: public, max-age=300, stale-while-revalidate=86400. A logged-in dashboard response should use
Cache-Control: private, no-store unless you have a carefully designed browser-only
cache policy.
Implementation Example
Cache-Control: public, max-age=300, stale-while-revalidate=86400
ETag: "article-42-v7"
For public pages, this lets the cache serve fresh content for five minutes and serve stale content while it refreshes in the background. For authenticated responses, prefer:
Cache-Control: private, no-store
For a blog or documentation site, this is especially useful. Article pages can be cached publicly because every reader sees the same content. Admin previews, newsletter subscriber dashboards, and analytics pages should not share that policy because they are user-specific or sensitive.
Implementation Checklist
- Use
publiconly for content safe across users. - Use
privatefor browser-only user-specific caching. - Use
ETagfor conditional requests. - Add
stale-while-revalidatefor public content that can refresh in background. - Test headers through the CDN, not only locally.
- Add
Varywhen response changes byAccept-Encoding, language, or auth shape. - Define invalidation strategy for pages with long TTLs.
- Check headers in browser devtools and CDN logs.
Common Mistakes
- Caching authenticated responses at the CDN.
- Setting long TTLs without invalidation.
- Forgetting
Varywhen responses differ by header. - Assuming
no-cachemeans "do not store." - Sending different cache headers from app and CDN config.
How To Validate
Test from the outside, not only from application code. Use browser devtools, curl -I, and CDN response headers to confirm what is actually cached:
curl -I https://example.com/docs/caching
Look for Cache-Control, ETag, Age, and CDN-specific headers such as cache
hit/miss indicators. Then test an authenticated page and confirm it cannot be
stored by shared caches.
Summary
HTTP caching headers are production controls. Decide who may cache the response, how long it stays fresh, and how it revalidates.
The weekly engineering digest
Production-grade engineering writing in your inbox. No spam, unsubscribe anytime.