TL;DR — Quick Summary
Caching stores resources locally to avoid re-downloading them on every visit. Use `Cache-Control: max-age=31536000, immutable` for versioned static assets (JS, CSS with content hashes) and `Cache-Control: no-cache` with ETag for HTML pages. CDN caching reduces TTFB from 200–500ms to 10–50ms globally. The `stale-while-revalidate` directive serves cached content instantly while updating in the background. Proper multi-layered caching (browser + CDN + server-side) reduces return-visit load times from seconds to under 500ms, cuts bandwidth costs by 60–80%, and directly improves LCP, FCP, and TTFB. Approximately 40% of websites still have suboptimal cache headers — fixing this is one of the easiest, highest-impact performance wins available.
What is Caching / HTTP Caching?
Caching is the process of storing copies of web resources at intermediate points between the origin server and the end user, allowing subsequent requests to be served faster without re-fetching from the origin. It operates at multiple complementary levels, and understanding each layer is essential for implementing an effective caching strategy.
Browser Cache (HTTP Cache): The browser's built-in cache stores responses locally based on HTTP headers. When a user revisits a page, the browser checks its cache before making network requests. `Cache-Control: max-age=31536000, immutable` tells the browser to cache a resource for one year and never revalidate — ideal for versioned static assets with content hashes in their filenames (e.g., `main.a1b2c3.js`). `Cache-Control: no-cache` caches the response but forces revalidation with the server on every request using ETag or Last-Modified headers — ideal for HTML documents that may change.
CDN Cache (Edge Cache): A Content Delivery Network distributes cached content across hundreds of global Points of Presence (PoPs). When a user requests a resource, DNS routes them to the nearest CDN edge server. If the resource is cached (cache hit), it's served in 10–50ms instead of 200–800ms from the origin. CDN caching is the single most effective way to reduce TTFB for geographically diverse users.
Server-Side Cache: Server-side caching operates at two levels: (1) page cache stores complete rendered HTML pages, eliminating the need to execute PHP/Node/Python and query databases on every request, and (2) object cache (Redis, Memcached) stores database query results, computed values, and session data in memory for sub-millisecond retrieval. On WordPress, WooCommerce, and other database-driven platforms, server-side caching can reduce server response time from 2–5 seconds to under 100ms.
Service Worker Cache: Service workers are JavaScript files that run in a separate browser thread, intercepting network requests and implementing custom caching strategies. They enable: cache-first (serve from cache, fall back to network), network-first (try network, fall back to cache), and stale-while-revalidate (serve cached, update in background). Service workers are the foundation of Progressive Web Apps (PWAs) and offline-first experiences.
Key HTTP Cache Headers:
- •`Cache-Control` — The primary caching directive. Key values: `max-age` (cache duration in seconds), `no-cache` (cache but revalidate), `no-store` (never cache), `immutable` (never revalidate), `stale-while-revalidate` (serve stale while updating), `public`/`private` (CDN cacheability).
- •`ETag` — A content fingerprint (hash) used for conditional requests. The browser sends `If-None-Match: [ETag]` to check if content changed. Server responds with 304 Not Modified (no body) if unchanged.
- •`Last-Modified` — Timestamp-based validation. Browser sends `If-Modified-Since` header. Less precise than ETag but simpler.
- •`Vary` — Specifies which request headers affect the cached response. `Vary: Accept-Encoding` caches separate versions for gzip/Brotli. `Vary: Cookie` caches per-user responses (careful: can destroy cache hit rates).
Caching / HTTP Caching Thresholds
| Metric | Good | Needs Improvement | Poor |
|---|---|---|---|
| CDN Cache Hit Ratio | > 90% | 70–90% | < 70% |
| Static Asset max-age | 31536000 (1 year) | 86400–2592000 | < 86400 (1 day) |
| TTFB (CDN-cached) | < 50ms | 50–200ms | > 200ms |
| Return Visit Load Time | < 1s | 1–3s | > 3s |
| Lighthouse Cache Audit | 0 warnings | 1–5 warnings | > 5 warnings |
| Server Page Cache Hit Rate | > 85% | 60–85% | < 60% |
| Bandwidth Savings (CDN) | > 70% | 40–70% | < 40% |
Google evaluates the 75th percentile (p75) of real-user field data over a rolling 28-day window.
History & Evolution
Caching has been fundamental to web performance since the early days of the web, evolving from simple browser storage to sophisticated multi-layer strategies.
Timeline of key milestones:
- •1996 — HTTP/1.0 introduces `Expires` header for basic time-based caching and `Pragma: no-cache` for cache prevention.
- •1997 — HTTP/1.1 (RFC 2068) introduces the `Cache-Control` header, providing granular cache directives that supersede the limited `Expires` header.
- •1999 — `ETag` (entity tag) is standardized in RFC 2616 for content-based cache validation, enabling conditional requests that return 304 Not Modified responses.
- •2004 — Akamai and early CDN providers popularize edge caching, reducing origin server load and improving global performance.
- •2010 — Cloudflare launches with a free CDN tier, democratizing edge caching for small and medium websites. CDN adoption begins rapid growth.
- •2014 — `stale-while-revalidate` directive proposed, enabling cached content to be served immediately while updating in the background — a breakthrough for balancing freshness and speed.
- •2015 — Service Workers ship in Chrome and Firefox, enabling JavaScript-controlled caching with offline support. This enables Progressive Web Apps (PWAs) with granular cache strategies.
- •2016 — The `immutable` Cache-Control directive is proposed and quickly adopted by major browsers. It prevents unnecessary revalidation of versioned assets, eliminating 304 round-trips.
- •2019 — `stale-while-revalidate` gains wide browser support, becoming the standard approach for semi-dynamic content caching.
- •2020 — Cache partitioning begins rollout in Chrome (later Safari and Firefox). Third-party caches are partitioned by top-level domain for privacy, ending cross-site cache sharing.
- •2022 — Modern build tools (Vite, Webpack 5, esbuild) make content-hash filenames the default, making immutable caching trivial to implement.
- •2025–2026 — Multi-layered caching is standard practice: content-hashed immutable browser caching + CDN edge caching + `stale-while-revalidate` for dynamic content + optional service worker for offline. Shared dictionary compression (Zstandard) begins reducing delta transfer sizes between cached and updated versions of resources.
How Caching / HTTP Caching is Measured
Cache effectiveness is measured through a combination of cache hit ratios, resource loading analysis, and HTTP header inspection. Understanding what to measure and which tools to use is critical for diagnosing caching issues and validating improvements.
Cache Hit Ratio (The Primary KPI): The cache hit ratio measures the percentage of requests served from cache vs. origin. A CDN with 95% cache hit ratio serves 95 out of 100 requests from edge — only 5 require origin fetches. Target: > 90% for static assets, > 70% for dynamic content with edge caching.
Formula: Cache Hit Ratio = (Cache Hits / Total Requests) × 100
Browser Cache Analysis: Chrome DevTools Network panel shows cache status for every resource. The 'Size' column displays 'disk cache' (cached on disk), 'memory cache' (cached in RAM from earlier in session), or the actual transfer size (fetched from network). Filter for resources served from network that should be cached.
First View vs. Repeat View: WebPageTest's 'Repeat View' test loads the page twice — First View (empty cache) and Repeat View (warm cache). The difference quantifies your caching benefit. A well-cached site should load 60–80% faster on Repeat View.
Lighthouse Cache Audit: The 'Serve static assets with an efficient cache policy' audit identifies resources with short or missing cache headers. It recommends a minimum cache duration of 1 year (31536000 seconds) for versioned static assets.
CDN Dashboard Metrics: All major CDNs provide dashboards showing:
- •Cache hit ratio (overall and per-resource)
- •Bandwidth saved (cache hits × resource size)
- •Origin offload percentage
- •Cache purge frequency and latency
- •Geographic distribution of cache hits
The Practical Measurement Workflow:
- 1Check Lighthouse cache audit → identify resources with suboptimal cache headers.
- 2Inspect Cache-Control headers in Chrome DevTools → understand current caching policy.
- 3Run WebPageTest First View vs. Repeat View → quantify the caching benefit.
- 4Check CDN dashboard → verify cache hit ratio > 90%.
- 5Monitor over time → ensure cache headers aren't regressing after deployments.
Key rule: Field data (CrUX) determines Google rankings. Lab data (Lighthouse, WebPageTest) is for debugging and iteration.
Common Causes of Poor Caching / HTTP Caching Scores
Poor caching performance has specific, diagnosable causes that fall into several categories:
Missing or Misconfigured Cache Headers:
- •No `Cache-Control` header on static assets — forces browsers to use heuristic caching (unpredictable behavior, typically 10% of the `Last-Modified` age).
- •Short `max-age` on versioned static assets — setting `max-age=3600` (1 hour) for JS/CSS forces unnecessary revalidation every hour, adding 50–200ms per resource per visit.
- •`Cache-Control: no-store` applied globally — over-cautious policy prevents all caching, even for public static resources.
- •Missing `immutable` directive on content-hashed assets — causes browsers to revalidate on navigation even when the content hash hasn't changed.
CDN Caching Issues:
- •`Vary: Cookie` in server responses — fragments CDN cache into per-user variations, effectively preventing CDN caching. Common on WordPress sites with session cookies.
- •`Set-Cookie` headers on static assets — CDNs won't cache responses that set cookies. Ensure static asset responses don't include session cookies.
- •`Cache-Control: private` on public resources — prevents CDN caching. Only appropriate for user-specific content.
- •Query string variations — URLs like `style.css?v=1` and `style.css?v=2` are cached as separate entries. Use content-hash filenames instead.
- •Low-traffic pages — CDN cache entries expire before being reused. Consider longer CDN TTLs or origin-shield configuration.
Server-Side Caching Issues:
- •No page caching on dynamic sites — every request executes PHP/Node/Python and queries the database, even for identical content.
- •Redis/Memcached not configured — database queries run on every request instead of serving cached results.
- •Cache invalidation failures — stale cached pages persist after content updates, showing outdated information.
- •Overly aggressive purging — cache purges on every edit clear the entire cache instead of just affected pages.
Build Tool & Deployment Issues:
- •No content hashes in filenames — using `style.css` instead of `style.a1b2c3.css` makes cache busting impossible without changing max-age.
- •Cache headers reset after deployment — CI/CD pipelines or hosting platforms may override custom cache headers.
- •Different cache headers in development vs. production — local dev servers often set `Cache-Control: no-cache` on everything.
Diagnostic tip: Start with Lighthouse's 'Serve static assets with an efficient cache policy' audit to identify the most impactful issues. Then use Chrome DevTools Network panel to inspect actual Cache-Control headers on each resource. Check your CDN dashboard for cache hit ratio — if it's below 80%, investigate `Vary` headers and `Set-Cookie` responses.
Frequently Asked Questions
For step-by-step optimization, platform-specific fixes, code examples, and case studies, read our full guide:
The Ultimate Guide to Web Hosting, CDN & Infrastructure for Speed: TTFB, Caching, Edge Workers & Traffic Resilience in 2026Struggling with Caching / HTTP Caching?
Request a free speed audit and we'll identify exactly what's holding your scores back.