HomeMethod

Knowledge

Web VitalsTechniquesSnippetsAnswersImpactsBottlenecks

Stale-While-Revalidate

Serve cached content immediately while refreshing it in the background, eliminating cache-expiry latency spikes.

Overview

stale-while-revalidate is a cache directive that allows a server or CDN to serve a stale (expired) cached response immediately to the visitor while simultaneously triggering a background refresh of the cache. The visitor never waits for regeneration — they receive the previous cached version in milliseconds, and the next visitor receives the freshly generated version. It eliminates the ‘thundering herd’ problem where cache expiry causes a burst of simultaneous uncached requests all hitting the origin at once.

Impact grade, A+ to D: how much of the Lighthouse score this technique can move. Unaffected: TBT, CLS.

The Problem

Standard cache TTL behavior creates a predictable latency spike: at the moment of expiry, the cached page is gone. The first visitor at that moment triggers a full PHP + database page generation — which may take 500ms–2s — and waits for it. Every concurrent visitor during that generation window also hits the uncached origin. On high-traffic pages with a short cache TTL, this creates periodic performance degradation for every visitor who happens to land during a cache refresh cycle.

Performance Impact

LCP

Consistent

LCP remains cache-fast even at the moment of TTL expiry — no latency spike

FCP

Eliminates spikes

no visitor ever waits for cache regeneration — stale content is served instantly

SI

Consistent

consistent cache delivery means Speed Index never degrades at cache expiry boundary

TTFB

High

TTFB never degrades to uncached PHP execution time — always serves from cache

Risk: Low

visitors may see content slightly older than the TTL — acceptable for most content types

How it works

  1. 01

    The HTTP Cache-Control directive

    Cache-Control: max-age=3600, stale-while-revalidate=86400 tells CDNs and reverse proxies: serve this page from cache for 1 hour fresh. After that, the cache is ‘stale’ — but continue serving it for up to 24 additional hours while a background revalidation request refreshes it. The visitor sees no latency; the refresh happens invisibly.

  2. 02

    CDN-level implementation

    Major CDNs — Cloudflare, Fastly, Varnish — honor stale-while-revalidate natively. When the cached response expires, the CDN edge node serves the stale copy to the requesting visitor and asynchronously makes a request to the origin to refresh the cached version. No origin hit occurs from the visitor’s perspective.

  3. 03

    Server-side implementation with WordPress

    Add the directive to pages via the send_headers hook or by configuring Nginx headers. For page cache plugins, WP Rocket supports stale cache serving natively. LiteSpeed Server supports it via the X-LiteSpeed-Cache-Control header with a stale-while-revalidate value.

  4. 04

    Stale cache as a fallback for origin errors

    The related directive stale-if-error extends stale serving to cover origin errors: Cache-Control: max-age=3600, stale-if-error=86400. If the origin returns a 5xx error during revalidation, the CDN continues serving the stale cached version rather than propagating the error to visitors — a form of automatic high-availability.

Code Example

Before
# Standard cache: at TTL expiry, visitors wait for full PHP regeneration
Cache-Control: max-age=3600

# Timeline:
# t=0     → cache populated
# t=3600  → cache EXPIRED, first visitor waits 800ms for regeneration
# t=3601  → new cache populated, subsequent visitors fast again
After
# Stale-While-Revalidate: stale content served instantly, refresh in background
Cache-Control: max-age=3600, stale-while-revalidate=86400, stale-if-error=86400

# Timeline:
# t=0      → cache populated  
# t=3600   → cache 'stale' — but visitor still served instantly from stale copy
#           → background revalidation request fires to origin
# t=3602   → new cache populated, next visitor gets fresh version

In WordPress with Nginx, add to your server block: add_header Cache-Control "public, max-age=3600, stale-while-revalidate=86400";. For WP Rocket: the ‘Keep current cache while updating’ option implements this pattern.

Limitations

  • The stale-while-revalidate window means visitors may see content up to (max-age + stale-while-revalidate) seconds old in the worst case. Not suitable for pages with real-time data requirements — stock prices, live scores, breaking news.
  • Browser caches also honor stale-while-revalidate for assets, but the browser revalidation happens on the user’s next navigation, not immediately — the user may see stale CSS or JS until they reload.
  • Not all CDNs honor the stale-while-revalidate directive from the Cache-Control header — some require proprietary configuration. Verify CDN support before relying on it.

Common Mistakes

Setting stale-while-revalidate on pages with personalized or session-specific content

Stale-while-revalidate is designed for public, cacheable responses. Applying it to logged-in pages or pages with user-specific content risks serving one user’s session data to another. Always pair with private or no-store for authenticated responses.

Using stale-while-revalidate as a substitute for cache warming

SWR eliminates the penalty for the first visitor after expiry, but that first visitor still triggers origin load. For very high-traffic pages, cache warming (proactively regenerating before TTL) is more reliable. Use both: SWR as a safety net, cache warming as the primary strategy.

Test this techniqueCache AnalysisRun the tool

Targeted fixes, not guesswork.

Start an Engagement
Support our family now