Stale-While-Revalidate: The Caching Strategy Explained
Stale-while-revalidate serves a cached response instantly while fetching a fresh one in the background, so no request waits on the network.
Stale-while-revalidate is a caching strategy that returns a cached response immediately, even if it’s slightly out of date, while a fresh copy is fetched in the background and swapped in for next time. The user never waits on a network round trip — they see the stale version now and the updated one on their next visit. It’s one of the few caching techniques that improves both perceived speed and freshness at once, instead of trading one for the other.
The problem it solves
Most caching decisions boil down to a single tension: serve from cache and risk showing stale data, or hit the network and make the user wait. A short cache lifetime keeps content fresh but sacrifices speed. A long one is fast but risks staleness. Stale-while-revalidate sidesteps the trade-off by doing both — serve the cached copy synchronously, then revalidate asynchronously so the next request gets the update.
This only works because the response is served before the revalidation even starts. The user’s request completes as fast as any cache hit; the network fetch happens off to the side, invisible to them.
How it works, step by step
- A request comes in for a resource that’s cached but past its
max-age. - The cache immediately returns the stale response to the caller.
- In the background, the cache (a browser, a CDN edge node, or a service worker) issues a fresh request to the origin.
- When the fresh response arrives, it replaces the stale entry.
- The next request for that resource gets the updated version — assuming it isn’t stale again by then.
Because step 2 and step 3 happen concurrently rather than sequentially, the strategy adds zero latency to the request that triggers the revalidation. Someone always eats one stale response, but nobody ever waits for a fetch.
Where you’ll actually meet it
The most common place is the HTTP Cache-Control header:
Cache-Control: max-age=60, stale-while-revalidate=86400
This tells a supporting cache — CDNs and modern browsers both understand it — that the response is fresh for 60 seconds, and for the following 86,400 seconds (a day) it can still be served stale while a background revalidation runs. Past that combined window, the cache must block and fetch synchronously. See HTTP caching headers for how this directive sits alongside max-age and no-cache.
The other common home is a service worker’s fetch handler, where you implement the same pattern manually: return whatever’s in the Cache Storage API immediately, then fetch() in the background and write the result back to the cache for next time. Client-side data-fetching libraries in the JavaScript ecosystem popularized the same idea under the same name — serve cached data instantly, refetch in the background, and re-render if the data changed.
Stale-while-revalidate vs plain max-age caching
Plain max-age | Stale-while-revalidate | |
|---|---|---|
| Behavior after expiry | Blocks and refetches synchronously | Serves stale immediately, refetches in background |
| Worst-case latency | Full network round trip | Same as a cache hit |
| Freshness | Guaranteed after expiry | Eventually consistent — one request may see stale data |
| Server load pattern | Spiky, tied to expiry | Smoothed out over time |
| Best for | Data that must never be outdated | Content where a few extra seconds of staleness is harmless |
Where it doesn’t belong
Stale-while-revalidate assumes staleness is an acceptable, bounded risk — not a correctness problem. It’s a poor fit for anything where an outdated response could cause a wrong decision: account balances, inventory counts that gate a purchase, or authorization checks. For those, you want a cache policy that fails toward a real fetch, not one that fails toward “close enough.” It’s a great fit for the opposite case: navigation content, article pages, dashboards, and API responses that are read far more often than they change.
It also doesn’t replace core web vitals work elsewhere in the stack. Serving a stale HTML shell instantly still depends on that shell being lightweight and free of layout shift once the revalidated content lands — stale-while-revalidate reduces network wait, not rendering cost.
Combining it with other cache directives
stale-while-revalidate is usually paired with stale-if-error, which tells the cache to keep serving the stale copy (rather than surfacing an error) if the background revalidation fails — a useful fallback during a brief origin outage. Together, the two directives turn a cache from a pure freshness mechanism into a resilience layer: fast under normal load, and quietly degraded rather than broken when the origin has a bad moment. For a broader look at how caching fits into a system’s design beyond HTTP, see what caching is.
The takeaway
Stale-while-revalidate serves a cached response immediately and refreshes it in the background, so the request that triggers the update never pays for it — only the next one might see slightly old data. It’s a directive on the Cache-Control header, a pattern in service workers, and the model behind most client-side data-fetching libraries. Reach for it whenever a resource changes often enough to need refreshing but not so often that a few seconds of staleness matters — and pair it with stale-if-error if you also want a cushion against origin downtime.
Keep reading
The Lycoris Team · · 5 min read What Is Incremental Static Regeneration (ISR)?
ISR lets a static page be rebuilt in the background after deploy, on a timer or on demand, without a full site rebuild. How it works and its tradeoffs.
Takina · · 3 min read Reflow vs Repaint: How Browsers Redraw Pages
Reflow recalculates layout; repaint just redraws pixels. Why the difference matters for animation performance and how to avoid triggering reflow.
Takina · · 4 min read Interaction to Next Paint (INP) Explained
INP measures how long a page takes to visually respond to a click, tap, or keypress. What it counts, how it's scored, and how to bring it down.