Modern sites need to feel instant. Users shouldn’t wait while your server prepares fresh data. This is where stale-while-revalidate shines. It lets caches serve old content immediately while they fetch a fresh version in the background.
It’s one of the best tricks for fast, resilient web apps.
What Does stale-while-revalidate Do?
You add it inside your Cache-Control header:
Cache-Control: max-age=60, stale-while-revalidate=300
Meaning:
- If the response is fresh (within 60 seconds), serve it normally.
- If it’s stale, the cache can still serve it instantly for up to 300 seconds.
- Meanwhile, the cache fetches a new version behind the scenes.
Users get fast responses, and your server updates quietly.
Why It’s So Useful
1. Instant page loads
Even if your API or server is slow at the moment, users see cached content right away.
2. Fewer origin server hits
Your server gets hammered far less, especially during peak traffic.
3. Zero downtime resiliency
If your backend has a hiccup, caches can still serve the stale copy. Your app feels “up” even if something is broken.
4. Perfect for content that updates often
Dashboards, news feeds, product lists… Users get good performance and reasonably fresh data.
How It Works Step by Step
Let’s say:
Cache-Control: max-age=60, stale-while-revalidate=300
User visits at:
- 00:00–01:00 → Cache is fresh → served fast.
- 01:01–06:00 → Cache is stale → still served instantly + background refresh.
- After 06:00 → Too stale → cache must fetch a new version before serving.
This balance gives speed without sacrificing freshness.
Where It’s Most Useful
- SPAs with API calls
- Next.js / React apps with static JSON data
- CDN-cached HTML (Vercel, Cloudflare, Fastly)
- Product catalogs
- User dashboards
- News / articles
- Public API endpoints
It’s basically a free performance boost.
Examples
Express.js
jsapp.get("/feed", (req, res) => {
res.set("Cache-Control", "public, max-age=60, stale-while-revalidate=300");
res.json({ items: [] });
});
Nginx
nginxadd_header Cache-Control "public, max-age=60, stale-while-revalidate=300";
Go
gow.Header().Set("Cache-Control", "public, max-age=60, stale-while-revalidate=300")
Best Practices
-
Keep
max-ageshort for fast-changing data. -
Keep
stale-while-revalidatelonger to reduce server load. -
Combine with
ETagfor strong validation. - Don’t use it for private or sensitive data.
Conclusion
stale-while-revalidate makes your app feel instant while still staying fresh in the background. It’s one of the easiest, most impactful caching optimizations you can apply—especially on CDNs.
Album of the blog:




