Revalidation & ISR
Incremental Static Regeneration serves a cached page fast, then rebuilds it in the background on a schedule.
export const revalidate = 60; // secondsIncremental Static Regeneration (ISR) gives you the speed of a static page with the freshness of a dynamic one. You set a revalidate time; Next serves the cached page instantly and, after that window passes, regenerates it in the background on the next request.
Set it per-fetch with next: { revalidate }, or for a whole route by exporting a revalidate constant.
Example
// app/blog/page.tsx — rebuild this page at most every 60s
export const revalidate = 60;
export default async function Blog() {
const posts = await getPosts();
return posts.map((p) => <article key={p.id}>{p.title}</article>);
}When to use it
- An e-commerce site uses ISR to pre-render product pages at build time and refresh them every 10 minutes without redeploying.
- A news site revalidates its homepage every 30 seconds so breaking news appears quickly while old HTML is served instantly.
- A developer calls the revalidatePath API from a CMS webhook so a page rebuilds the moment an editor publishes a change.
More examples
Route-level revalidation
Exporting revalidate at the route level makes the entire page re-generate every 60 seconds via ISR.
// app/products/page.tsx
export const revalidate = 60; // seconds
export default async function ProductsPage() {
const products = await fetch('/api/products').then(r => r.json());
return <ul>{products.map((p: any) => <li key={p.id}>{p.name}</li>)}</ul>;
}On-demand revalidation handler
revalidatePath purges the cache for a specific route on demand, triggered by a CMS webhook.
// app/api/revalidate/route.ts
import { revalidatePath } from 'next/cache';
import { NextRequest, NextResponse } from 'next/server';
export async function POST(req: NextRequest) {
const { path } = await req.json();
revalidatePath(path);
return NextResponse.json({ revalidated: true });
}Revalidate by tag
Tags let multiple pages share a cache entry that can be invalidated together with a single revalidateTag call.
// Tag the fetch
const res = await fetch('/api/posts', { next: { tags: ['posts'] } });
// Invalidate all routes using that tag
import { revalidateTag } from 'next/cache';
revalidateTag('posts');
Discussion