Using Vercel ISR with On‑Demand Revalidation to Keep Static Sites Fresh Without Sacrificing Speed
Static sites deliver lightning‑fast performance, yet content updates can make them stale. Vercel’s ISR with on‑demand revalidation lets you keep the speed while ensuring recent changes are visible within seconds.
27 Sept 2025, 11:12 UTC

The Stale‑Content Problem
Static sites are fast because they serve pre‑rendered HTML from a CDN. The downside: every content change forces a full rebuild and redeploy. For a marketing site that updates once a week that’s fine; for a documentation hub or a blog that publishes several times a day, the rebuild cycle becomes a bottleneck.
Vercel’s Incremental Static Regeneration (ISR) with on‑demand revalidation changes that equation. You keep the static‑site performance—sub‑100 ms Time‑to‑First‑Byte from the edge—while gaining the ability to refresh individual pages in seconds, not minutes.
How ISR Works Under the Hood
At build time Next.js runs getStaticProps (or the App Router equivalent) for each path you define. The resulting HTML and JSON are written to Vercel’s edge network. When a request arrives, the edge cache serves the stored response instantly. The magic is the revalidate option:
export async function getStaticProps() {
const data = await fetchContent()
return {
props: { data },
revalidate: 30 // seconds
}
}With revalidate: 30, the first request after 30 seconds triggers a background regeneration. The visitor still sees the cached version immediately; the next visitor gets the fresh page. No full rebuild, no downtime.
On‑Demand Revalidation: Targeted Updates
Time‑based revalidation works for predictable schedules, but sometimes you need to push an update the moment a CMS entry changes. Vercel exposes an API endpoint (/api/revalidate) that accepts a secret token and a path. Your webhook calls it, and Vercel queues a regeneration for that single path.
Example webhook handler (Next.js API route):
export default async function handler(req, res) {
if (req.query.secret !== process.env.REVALIDATE_SECRET) {
return res.status(401).json({ message: 'Invalid token' })
}
const path = req.query.path || '/'
try {
await res.revalidate(path)
return res.json({ revalidated: true })
} catch (err) {
return res.status(500).send('Error revalidating')
}
}Now a content editor hits “Publish” in the CMS, the webhook fires, and the affected page is refreshed globally within seconds.
Worked Example: Verifying Cache Behavior
Deploy a minimal Next.js project to Vercel with the revalidate: 30 setting above. Open Chrome DevTools → Network, reload the page, and inspect the response headers:
x-vercel-cache: HIT– served from edge cache.cache-control: public, max-age=0, must-revalidate– tells the browser to revalidate but allows the edge to serve stale content while regenerating.
Wait 35 seconds, reload again. You’ll see x-vercel-cache: STALE on the first request (background regeneration started) and HIT on the next request with updated content. This confirms the background regeneration flow without any manual cache purging.
Trade‑offs and Limitations
- Stale window: If the edge cache TTL exceeds the
revalidateinterval, visitors may see outdated content until the cache expires. ExplicitCache-Controlheaders (e.g.,s-maxage=30, stale-while-revalidate=60) mitigate this. - Not for per‑user data: ISR caches one version per path. Personalized dashboards or A/B variants need middleware or Server‑Side Rendering for those routes.
- Cold‑start latency: The first request that triggers regeneration may experience a few hundred milliseconds of added latency while the edge function spins up.
Actionable Checklist
- Add
revalidate: Nto your static props (Pages Router) orexport const revalidate = N(App Router). - Set
Cache-Control: s-maxage=N, stale-while-revalidate=Minnext.config.jsor via middleware for finer control. - Create a secured
/api/revalidateendpoint and configure your CMS webhook to call it on publish. - Verify with DevTools: watch
x-vercel-cachetransition fromHIT→STALE→HITafter the interval. - Monitor Vercel’s “Function Invocations” and “Edge Requests” dashboards to ensure regeneration frequency matches expectations.
ISR with on‑demand revalidation gives you the best of both worlds: static‑site speed for the 99 % of traffic that reads cached pages, and near‑real‑time freshness for the moments that matter. Start with a single high‑traffic page, measure the cache‑hit ratio, and expand once you’re comfortable with the stale‑window behavior.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.