~3 min read • Updated Oct 27, 2025
Introduction
Incremental Static Regeneration (ISR) in Next.js lets you update static content gradually without rebuilding your entire site. It improves performance, reduces build time, and ensures fresh data is served efficiently.
Basic Example
In app/blog/[id]/page.tsx, you can configure ISR like this:
export const revalidate = 60 // revalidate every 60 seconds
export async function generateStaticParams() {
const posts = await fetch('https://api.vercel.app/blog').then(res => res.json())
return posts.map(post => ({ id: String(post.id) }))
}
export default async function Page({ params }) {
const { id } = await params
const post = await fetch(`https://api.vercel.app/blog/${id}`).then(res => res.json())
return (
<main>
<h1>{post.title}</h1>
<p>{post.content}</p>
</main>
)
}Pages are generated at build time and revalidated in the background after 60 seconds.
Time-Based Revalidation
For example, on the /blog route:
export const revalidate = 3600 // revalidate every hour
export default async function Page() {
const data = await fetch('https://api.vercel.app/blog')
const posts = await data.json()
return (
<main>
<h1>Blog Posts</h1>
<ul>
{posts.map(post => <li key={post.id}>{post.title}</li>)}
</ul>
</main>
)
}On-Demand Revalidation with revalidatePath
To revalidate a specific route after a mutation:
'use server'
import { revalidatePath } from 'next/cache'
export async function createPost() {
revalidatePath('/posts')
}On-Demand Revalidation with revalidateTag
To revalidate data tagged with posts:
fetch('https://api.vercel.app/blog', {
next: { tags: ['posts'] }
})Then:
'use server'
import { revalidateTag } from 'next/cache'
export async function createPost() {
revalidateTag('posts')
}Using unstable_cache
For database queries:
import { unstable_cache } from 'next/cache'
const getCachedPosts = unstable_cache(
async () => await db.select().from(posts),
['posts'],
{ revalidate: 3600, tags: ['posts'] }
)Error Handling
If revalidation fails, the last successful version is served. Next.js retries revalidation on the next request.
Custom Cache Location
You can configure cache storage to persist across deployments or share between containers.
Debugging in Development
To inspect cache behavior locally:
// next.config.js
module.exports = {
logging: {
fetches: {
fullUrl: true,
},
},
}
// .env
NEXT_PRIVATE_DEBUG_CACHE=1Caveats
- ISR works only with the Node.js runtime
- Not supported with Static Export
- If any fetch uses
revalidate: 0orno-store, the route becomes dynamic - Proxy rewrites are not applied during on-demand ISR
Platform Support
| Deployment Option | Supported |
|---|---|
| Node.js Server | ✅ |
| Docker Container | ✅ |
| Static Export | ❌ |
| Adapters | Platform-specific |
Conclusion
ISR in Next.js enables efficient, scalable static page regeneration. With time-based and on-demand options, you can keep content fresh while maintaining performance and minimizing build time.
Written & researched by Dr. Shahin Siami