By Rahul — Google Frontend Engineer
Why Caching is the Most Important Performance Optimization
The fastest network request is the one never made. HTTP caching can eliminate network requests entirely for returning users. At Google, proper caching strategies reduce page load times by 40-60% for repeat visitors.
Two Types of Caching
Strong Cache (Cache-Control)
The browser uses the cached copy WITHOUT contacting the server at all. The response shows status 200 (from disk cache) or 200 (from memory cache).
Cache-Control: max-age=31536000
// Cache for 1 year. Do not even ask the server.Conditional Cache (ETags / Last-Modified)
The browser asks the server "has this changed?" If not, the server responds with 304 Not Modified (no body). If changed, it sends the new resource with 200.
// First response
ETag: "abc123"
// Browser's next request
If-None-Match: "abc123"
// Server response if unchanged
304 Not Modified (no body, saves bandwidth)Cache-Control Directives
// Cache for 1 hour, any cache can store it
Cache-Control: public, max-age=3600
// Only browser can cache (not CDN/proxy)
Cache-Control: private, max-age=3600
// Do not use cached version without checking with server
Cache-Control: no-cache
// IMPORTANT: no-cache does NOT mean "don't cache"
// It means "cache it but validate before using"
// Do not store at all — for sensitive data
Cache-Control: no-store
// Cache is stale but usable while revalidating in background
Cache-Control: max-age=3600, stale-while-revalidate=86400The Modern Caching Strategy
This is the pattern used by most production apps including at Google:
For Hashed Assets (JS, CSS bundles)
// Files like app.a1b2c3.js
Cache-Control: public, max-age=31536000, immutable
// Cache forever. The hash in the filename changes when content changes.
// "immutable" tells browser to not even revalidate.For HTML Documents
// index.html — must always be fresh
Cache-Control: no-cache
// Browser will check with server every time
// But if unchanged, gets a fast 304For API Responses
// User-specific data
Cache-Control: private, no-cache
// Public, rarely changing data (like product catalog)
Cache-Control: public, max-age=300, stale-while-revalidate=3600Real Production Issues
The Broken Deploy
You deploy new JS but HTML still references old JS file. Users see a white screen because the old JS bundle is gone from the server. Solution: keep old bundles alive for at least 24 hours after deploy.
CDN Cache Stampede
A popular resource expires from cache. 10,000 users request it simultaneously, all hitting your origin server. Solution: stale-while-revalidate lets the CDN serve the stale version while fetching fresh content.
Cache Poisoning
A CDN caches an error page (500 response) because you forgot to set Cache-Control on error responses. Now all users see the error. Always set Cache-Control: no-store on error responses.
Debugging Cache Issues
Best Practices
- Hash your static assets and cache them forever
- Never cache HTML with
max-age— useno-cache - Use
stale-while-revalidatefor non-critical data - Set
no-storeon sensitive data and error responses - Keep old asset versions available after deploys
- Use
Varyheader carefully — wrong Vary headers fragment your cache
Summary
HTTP caching is the highest-impact performance optimization. Use content hashing with immutable caching for assets, no-cache for HTML, and stale-while-revalidate for API data. Getting caching right can cut load times in half.