Using Vercel’s Incremental Static Regeneration with On‑Demand Revalidation in Next.js
Learn how to keep a static site fresh without rebuilding the whole site by using ISR and on‑demand revalidation on Vercel. The post walks through configuration, an example API route, trade‑offs, and how to verify the results.
16 Jul 2025, 09:22 UTC

Why ISR and On‑Demand Revalidation Matter
Static sites built with Next.js and deployed on Vercel can ship instant HTML to users, but the content can become stale when data changes. Incremental Static Regeneration (ISR) lets a page be regenerated in the background after a revalidate interval, while the stale page is still served. On‑Demand Revalidation adds a layer of control: editors or external systems can explicitly invalidate specific paths or tag groups, triggering a regeneration without a full rebuild. This balances content freshness against build cost and deployment latency.
How ISR Works on Vercel
When a page is requested for the first time, Vercel builds it and caches the HTML at the edge. Subsequent requests hit the edge cache. When the revalidate time passes, the next request triggers a stale‑while‑revalidate cycle:
- The stale page is served immediately.
- In the background Vercel rebuilds the page.
- The new page replaces the stale one in the cache for future requests.
Because the cache is distributed globally, the first request after expiry is the one that starts the regeneration. All other requests meanwhile keep receiving the stale version until regeneration completes.
On‑Demand Revalidation: Targeted Cache Invalidation
ISR alone only knows when a page should be refreshed based on time. On‑Demand Revalidation gives you a programmatic hook to invalidate content immediately:
- Deploy an API route that calls
next/cache’srevalidatePathorrevalidateTag. - Protect the route with a secret or Vercel deployment protection.
- Trigger the route from an editor’s UI or a webhook when the underlying data changes.
Example: an e‑commerce product page uses revalidateTag('products') to refresh all product pages when a price update occurs.
Concrete Example (Next.js 13 App Router)
// app/api/revalidate.js
import { revalidatePath, revalidateTag } from 'next/cache';
export const runtime = 'edge'; // Edge runtime for low latency
export default async function handler(req) {
// Basic secret check – replace with your own auth
if (req.headers.get('x-secret') !== 'my-secret-token') {
return new Response('Unauthorized', { status: 401 });
}
const body = await req.json();
const { path, tag } = body;
try {
if (path) {
await revalidatePath(path); // e.g., '/products/123'
}
if (tag) {
await revalidateTag(tag); // e.g., 'products'
}
return new Response('Revalidated', { status: 200 });
} catch (err) {
return new Response('Revalidation failed', { status: 500 });
}
}
Usage from a webhook (e.g., a CMS publishing event):
fetch('https://your-app.vercel.app/api/revalidate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-secret': 'my-secret-token',
},
body: JSON.stringify({ tag: 'products' }),
});
Verifying the Behavior
- Deploy the app and request a page with
revalidate: 60. - Wait 61 seconds, then request the page again. Inspect the
X‑Vercel-Cacheheader: the first request after expiry showsMISS, subsequent onesHIT. - Trigger the on‑demand revalidation endpoint and observe a new
MISSimmediately, confirming the cache was purged.
Trade‑Offs and Limitations
- Revalidation Frequency vs. Build Cost: A short
revalidateinterval means more frequent regenerations, potentially hitting Vercel’s concurrency limits (e.g., 20 concurrent ISR builds per project). Choose a value that balances freshness with build budget. - Concurrent Regenerations: If many users hit a page simultaneously after expiry, Vercel will queue the regeneration. The first request still receives stale content until the build finishes.
- Edge vs. Serverless: The example uses the
edgeruntime for minimal latency, but on‑demand revalidation functions must run in a runtime that supports thenext/cacheAPI (currently Edge or Node 18+). - Security: Exposing the revalidation endpoint publicly can lead to cache poisoning. Always protect it with a secret or Vercel’s deployment protection.
- Tag Support: Tags are a newer feature; older Next.js versions or the Pages Router may not expose
revalidateTag. Verify your Next.js version supports the API you use.
Actionable Checklist
- Define
revalidateintervals ingetStaticPropsor page components. - Implement a protected on‑demand revalidation endpoint using
revalidatePathorrevalidateTag. - Wire the endpoint to your CMS or data source webhook.
- Test cache headers (X‑Vercel-Cache, Age) to confirm stale‑while‑revalidate behavior.
- Monitor Vercel’s ISR usage metrics to ensure you stay within concurrency limits.
By combining ISR with on‑demand revalidation, you can serve static‑fast pages that stay fresh on demand, giving editors instant control over content updates without incurring heavy rebuild costs.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.