Stale-While-Revalidate: Serving Speed Without Sacrificing Freshness
Stale-while-revalidate (SWR) is a Cache-Control extension defined in RFC 5861 that allows a cache to serve an expired response immediately while fetching a fresh copy from the origin server in the background. This eliminates the latency penalty of cache revalidation — users always receive instant responses, and the cache updates itself asynchronously for subsequent requests. For CDN operators seeking the performance of long cache TTLs with the freshness of short ones, stale-while-revalidate is the single most impactful directive in the Cache-Control header toolkit.
What Problem Does Stale-While-Revalidate Solve?
Traditional CDN caching forces a binary tradeoff between speed and freshness. Set a long TTL and users get fast cached responses, but content goes stale. Set a short TTL and content stays fresh, but users frequently experience the full latency of origin fetches when cached entries expire. For foundational context, read CDN Caching Strategies: Pull, Push, and Hybrid — FlyFish NWA.
Consider a news site with Cache-Control: max-age=60 on article pages. Every 60 seconds, the first user to request each article hits an expired cache entry. The CDN must fetch from the origin before responding, adding 200-500 milliseconds of latency. During that origin fetch, every other concurrent request for the same resource either waits (blocking) or also fetches from origin (stampeding).
Stale-while-revalidate eliminates this penalty entirely:
Cache-Control: max-age=60, stale-while-revalidate=300
With this header, the CDN serves the cached response for the first 60 seconds (fresh). After 60 seconds, the cache entry is considered stale but remains servable for an additional 300 seconds. During this stale window, the first request triggers a background revalidation while immediately receiving the stale response. All subsequent requests during revalidation also receive the stale response instantly. When the fresh response arrives from the origin, the cache is silently updated.
The result is that users never experience revalidation latency. Every request gets an instant response, either fresh or stale-but-being-refreshed.
How Does the Asynchronous Revalidation Flow Work?
Understanding the step-by-step revalidation flow clarifies why SWR is so effective. Here is what happens at the CDN edge when SWR is configured:
| Metric | Edge Processing | Origin Processing | Improvement |
|---|---|---|---|
| Latency (p50) | 8–15 ms | 120–300 ms | 15–20x faster |
| Cache Hit Ratio | 85–95% | N/A | Reduces origin load |
| TLS Handshake | 1–5 ms (nearby PoP) | 50–150 ms | 10–30x faster |
| Bandwidth Cost | $0.01–0.04/GB | $0.05–0.12/GB | 3–5x cheaper |
| Availability | 99.99% (multi-PoP) | 99.9% (single DC) | 10x fewer outages |
Phase 1: Fresh (0 to max-age seconds). The cached response is within its max-age TTL. Every request receives the cached response. No origin contact occurs. This phase is identical to standard caching behavior.
Phase 2: Stale-while-revalidate window (max-age to max-age + SWR seconds). The cached response has exceeded its max-age but is within the SWR window. The CDN marks the entry as stale. The next incoming request triggers the following sequence:
- The CDN immediately serves the stale cached response to the requesting user.
- The CDN initiates a background HTTP request to the origin (or next tier in the cache hierarchy).
- Concurrent requests during the background fetch continue receiving the stale response.
- When the origin responds, the CDN updates the cached entry with the fresh response and resets the TTL.
- All requests arriving after the update receive the new fresh response.
Phase 3: Expired (beyond max-age + SWR seconds). If no request triggered revalidation during the SWR window, the cache entry is fully expired. The next request must wait for an origin fetch, just like standard cache behavior with no SWR.
The key insight is that Phase 2 is the normal operating state for popular content. As long as at least one request arrives during each SWR window, the cache entry is perpetually refreshed in the background and users never experience origin latency.
What Is Stale-If-Error and How Does It Complement SWR?
While stale-while-revalidate handles the performance case, its companion directive stale-if-error handles the reliability case. Defined in the same RFC 5861, stale-if-error allows the CDN to serve stale content when the origin returns an error (500, 502, 503, 504) or is unreachable.
Cache-Control: max-age=60, stale-while-revalidate=300, stale-if-error=86400
This configuration means:
- Content is fresh for 60 seconds.
- After 60 seconds, serve stale and revalidate in background (for up to 300 seconds).
- If the origin is down, continue serving stale content for up to 86,400 seconds (24 hours).
Together, SWR and stale-if-error provide both performance optimization and failover protection. The CDN serves fast responses during normal operation and continues serving cached content during outages, giving your team time to resolve origin issues without user-facing downtime. For more detail on caching error responses intentionally, see our negative caching guide.
How Do Major CDN Providers Implement SWR?
Each CDN provider has its own level of support and configuration options for stale-while-revalidate:
| Provider | SWR Support | stale-if-error Support | Configuration |
|---|---|---|---|
| Cloudflare | Honored from origin headers | Honored from origin headers | Automatic when headers are present, or via Page Rules / Cache Rules |
| Fastly | Full support via VCL | Full support via VCL | Set in VCL with beresp.stale_while_revalidate and beresp.stale_if_error |
| AWS CloudFront | Honored from origin headers | Limited (custom error pages instead) | Origin must send the header; no CDN-side override |
| Akamai | Supported via Property Manager | Supported via Property Manager | Configurable with serve-stale behavior rules |
| Bunny CDN | Supported | Supported | Stale cache mode in pull zone settings |
Fastly offers the most granular control. You can set SWR and stale-if-error values per-response in VCL, override origin headers, and fine-tune revalidation behavior. Fastly also supports request collapsing during SWR revalidation, ensuring only one background fetch occurs even under high concurrency.
Cloudflare handles SWR transparently when the origin sends the appropriate headers. No additional configuration is needed. Cloudflare also implements its own form of stale serving through its Always Online feature, which is separate from the HTTP stale-if-error mechanism.
CloudFront honors origin-sent stale-while-revalidate headers but does not provide a CDN-side mechanism to set SWR values independently of the origin. You must configure your origin server to send the headers.
How Should You Configure SWR for Different Content Types?
The optimal SWR configuration depends on how frequently content changes and how tolerant users are of stale data. Here are recommended values by content type:
| Content Type | max-age | stale-while-revalidate | stale-if-error | Rationale |
|---|---|---|---|---|
| Static assets (CSS, JS, fonts) | 31536000 (1 year) | Not needed | 86400 | Filename-hashed; TTL handles freshness |
| Images | 2592000 (30 days) | 86400 | 604800 | Rarely change; long SWR prevents cold cache |
| HTML pages (blog, docs) | 300 (5 min) | 3600 | 86400 | Updated occasionally; hour-long SWR absorbs peaks |
| News articles | 60 (1 min) | 300 | 3600 | Frequent updates; short SWR keeps content near-fresh |
| API responses (public) | 30 | 120 | 300 | Short-lived; SWR prevents origin hits between updates |
| API responses (user-specific) | 0 | Not applicable | Not applicable | Cannot cache; use private, no-store |
| Product catalog | 600 (10 min) | 1800 | 7200 | Prices may change; balanced freshness |
The general pattern is: the shorter the max-age, the more valuable a proportionally longer SWR window becomes. A 5-minute max-age with a 1-hour SWR window means users experience revalidation latency only if the resource goes unvisited for an entire hour — which happens rarely for popular content. For comprehensive TTL guidance, see our TTL optimization guide.
How Does SWR Prevent Cache Stampedes?
One of the most significant benefits of stale-while-revalidate is its natural prevention of cache stampedes (also called the thundering herd problem).
Without SWR, when a popular resource's TTL expires, the next batch of concurrent requests all discover an expired cache entry simultaneously. If the CDN does not implement request coalescing, each of these requests triggers a separate origin fetch. A resource receiving 1,000 requests per second generates 1,000 simultaneous origin requests the moment its cache expires.
With SWR enabled, the stampede cannot form because:
- All requests during the stale window receive the cached response instantly.
- Only the first request triggers a background revalidation.
- The background fetch is a single request to the origin, regardless of concurrent user traffic.
- When the fresh response arrives, the cache is updated, and new requests receive fresh content.
This makes SWR a first-line defense against origin overload during cache transitions. It works alongside request collapsing (which prevents stampedes at the cache-fill level) and origin shield (which consolidates fetches from multiple cache tiers) to provide multiple layers of origin protection.
Does SWR Work in Browsers as Well as CDNs?
Yes, stale-while-revalidate is supported in modern browsers and behaves similarly to CDN implementations. When the browser encounters a stale-while-revalidate directive in a response, it can serve the stale cached version from its local cache while revalidating in the background.
Browser support as of 2026:
- Chrome/Chromium — Full support since Chrome 75 (June 2019).
- Firefox — Full support since Firefox 68 (July 2019).
- Safari — Full support since Safari 16.4 (March 2023).
- Edge — Full support (Chromium-based).
When SWR is used in a multi-layer caching architecture with both browser and CDN caches, the directive works at both levels. The browser serves stale content from its local cache while revalidating with the CDN, and the CDN serves stale content from its edge cache while revalidating with the origin. This creates a two-tier SWR pipeline where users almost never wait for a network round-trip.
One caveat: the browser's background revalidation request still goes to the CDN. If the CDN cache is fresh, the browser gets an instant response. If the CDN cache is also in its SWR window, the CDN serves stale content to the browser while revalidating with the origin. The staleness does not compound — both caches independently track their own max-age timers.
What Is the Measurable Performance Impact of SWR?
The performance impact of stale-while-revalidate depends on the ratio of stale-window requests to fresh-window requests. For popular content with short TTLs, the improvement is dramatic.
Consider a resource with max-age=60, stale-while-revalidate=300 receiving 100 requests per minute:
Without SWR: Every 60 seconds, 1-5 requests (depending on concurrency) experience full origin latency (200-500 ms). Over an hour, approximately 60-300 requests experience degraded performance. If request collapsing is not enabled, the origin receives 60-300 refetches per hour.
With SWR: Zero requests experience origin latency because every request during the stale window (seconds 60-360) receives the stale response instantly. The origin receives exactly 1 refetch every 60 seconds (60 per hour, always in the background). Users perceive the resource as always being served from cache.
Real-world performance measurements from production CDN deployments show that enabling SWR typically produces:
- P99 latency reduction of 40-60% for resources with TTLs under 5 minutes.
- Origin request reduction of 30-50% compared to equivalent max-age without SWR.
- Cache hit ratio increase of 5-15 percentage points, because stale responses count as hits.
- Core Web Vitals improvement in Largest Contentful Paint (LCP) due to eliminated revalidation blocking.
The most impactful use case is combining a short max-age (30-60 seconds) with a generous SWR window (300-600 seconds) for semi-dynamic content like news feeds, product listings, and API aggregation endpoints. This achieves near-real-time content freshness with the perceived performance of a static CDN cache.
Stale-while-revalidate is not a replacement for proper TTL optimization or cache invalidation — it is a complement that smooths the performance cliffs that occur at cache boundaries. Combined with stale-if-error for reliability, SWR transforms CDN caching from a system that oscillates between fast-cached and slow-revalidating states into one that delivers consistently fast responses under all conditions.