Stale-While-Revalidate Planner
Plan max-age and stale-while-revalidate values and output the header.
stale-while-revalidate (SWR) is a caching strategy that, right after a cached response expires, still serves the stale copy to the user instantly while quietly fetching a fresh version in the background. This removes the slow requests that pile up at the expiry boundary and lets you respond at cache speed almost every time while keeping content reasonably fresh.
This planner takes max-age, stale-while-revalidate, an optional stale-if-error, and a public/private scope, then assembles a ready-to-use Cache-Control header. It also converts each window into seconds and minutes and explains, on a timeline, how the response behaves depending on when a request arrives.
Cache-Control: public, max-age=60, stale-while-revalidate=600
| Fresh window (0 to max-age) | 60s (1 min) |
|---|---|
| Background refresh window (swr) | 600s (10 min) |
| Total stale allowance (max-age + swr) | 660s (11 min) |
| Served on error (stale-if-error) | — |
- 0 to 60s: fresh. The cache responds instantly with no origin call.
- 60 to 660s: serve stale immediately + revalidate origin in the background. No user wait.
- after 660s: SWR window closed. The next request does a synchronous revalidation (waits for origin).
What each directive means
In the Cache-Control response header, these directives tell caches (browsers and CDNs) how to treat the response.
- max-age=N: how long (in seconds) the response is considered fresh. During this window the cache answers directly without asking the origin.
- stale-while-revalidate=N: for N seconds after
max-ageexpires, the cache may return the stale response immediately and, at the same moment, revalidate (re-fetch from origin) in the background. The user never waits. - stale-if-error=N: if the origin errors (5xx) or is unreachable, the cache may serve the stale response for up to N seconds past expiry, masking the outage. It is an availability insurance.
- public / private:
publicallows shared caches like CDNs to store the response;privaterestricts storage to the end user's browser (per-user content).
The response timeline
Calling the moment a response is stored in the cache time 0, the cache behaves as follows depending on when the next request arrives.
- 0 to max-age: the fresh window. The cache responds instantly with no origin call.
- max-age to (max-age + swr): the background refresh window. The user gets the stale response immediately while the cache fetches a new copy from the origin. Perceived latency is zero.
- after (max-age + swr): the SWR window has closed, so a stale response is no longer allowed. The next request waits for a synchronous revalidation to complete.
So a short max-age with a long stale-while-revalidategives you "almost always fast responses plus steady background refresh." Pair it with the Cache-Control builder when assembling the full header, and design expiry times for temporary-access signed URLs with the signed URL expiry calculator.
Benefits and caveats
Key benefits of SWR:
- It removes the "thundering herd" of cache misses and the slow first request at the expiry edge.
- Nearly every response is served at cache speed, so TTFB stays stable.
- Adding
stale-if-errorlets you ride out an origin outage on the last good copy.
Things to watch:
- It does not guarantee users always see the newest copy. During the SWR window they may get data that is one step behind, so it is unsuitable for responses that need instant accuracy like prices or stock counts.
- Not every browser or CDN supports SWR identically. Unsupported caches usually treat the response as fresh only up to max-age.
- Background refreshes still produce origin requests. With a very long swr window, low-traffic resources may refresh rarely and serve increasingly stale responses.