Articles

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.

Takina Takina · · 4 min read
A black stopwatch on a dark surface

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

  1. A request comes in for a resource that’s cached but past its max-age.
  2. The cache immediately returns the stale response to the caller.
  3. In the background, the cache (a browser, a CDN edge node, or a service worker) issues a fresh request to the origin.
  4. When the fresh response arrives, it replaces the stale entry.
  5. 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-ageStale-while-revalidate
Behavior after expiryBlocks and refetches synchronouslyServes stale immediately, refetches in background
Worst-case latencyFull network round tripSame as a cache hit
FreshnessGuaranteed after expiryEventually consistent — one request may see stale data
Server load patternSpiky, tied to expirySmoothed out over time
Best forData that must never be outdatedContent 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.

The Lycoris Team 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.

#Web Development #Performance #Frontend
Takina 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.

#Web Development #Performance #Frontend
Takina 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.

#Performance #Web Development #Frontend