Optimizing a Next.js Blog with Incremental Static Regeneration (ISR)
Use Incremental Static Regeneration (ISR) in Next.js to keep blog posts fresh without full rebuilds. Learn how to set revalidate intervals, trigger regeneration via API, and check that pages update correctly.
17 Oct 2025, 22:31 UTC

Problem: Fresh Blog Content Without a Full Rebuild
When you run a content‑heavy site like a blog, you want new posts to appear quickly for readers and search engines. In a static‑site generator, every change usually forces a full rebuild, which can take minutes or more for large sites. The question becomes: how do we keep the performance of static pages while ensuring editors see their latest work almost immediately?
ISR Fundamentals
Incremental Static Regeneration (ISR) lets Next.js generate pages at build time and then refresh them on demand. The key pieces are:
revalidate– a number of seconds that tells Next.js how often to re‑generate a page.- On‑demand regeneration – an API route or webhook can trigger a rebuild before the timeout expires.
- Cache‑busting – the server returns a fresh page only after regeneration finishes.
ISR works with both static‑generation functions (getStaticProps) and dynamic routes that use generateStaticParams.
Practical Implementation: A Sample Blog Post Page
Below is a minimal example of a blog post page that uses ISR. The page is generated at build time, but will be refreshed every 60 seconds or when an editor triggers it.
// app/blog/[slug]/page.js
import { getPostBySlug, getAllPostSlugs } from '@/lib/posts';
export async function generateStaticParams() {
const slugs = await getAllPostSlugs();
return slugs.map((slug) => ({ slug }));
}
export async function generateMetadata({ params }) {
const post = await getPostBySlug(params.slug);
return {
title: post.title,
description: post.excerpt,
};
}
export async function getStaticProps({ params }) {
const post = await getPostBySlug(params.slug);
return {
props: { post },
revalidate: 60, // seconds
};
}
export default function PostPage({ post }) {
return (
<article>
<h1>{post.title}</h1>
<time>{new Date(post.date).toLocaleDateString()}</time>
<div dangerouslySetInnerHTML={{ __html: post.content }} />
</article>
);
}
Key points:
revalidate: 60tells Next.js to regenerate the page if it’s older than 60 s.- The page is served from the static cache until regeneration completes.
- Because
generateStaticParamsruns at build time, the page is pre‑generated for every known slug.
Triggering Regeneration via API or Webhook
Editors often push content to a CMS that can send a webhook. A simple API route in Next.js can handle that request and call the revalidate function.
// app/api/revalidate/route.js
import { NextResponse } from 'next/server';
export async function POST(request) {
const { secret, slug } = await request.json();
// Basic auth guard – replace with your own secret mechanism
if (secret !== process.env.REVALIDATE_SECRET) {
return NextResponse.json({ error: 'Invalid secret' }, { status: 401 });
}
try {
await revalidate(`/blog/${slug}`);
return NextResponse.json({ revalidated: true });
} catch (err) {
return NextResponse.json({ error: err.message }, { status: 500 });
}
}
Deploy this route to Vercel or another provider. Your CMS can POST to /api/revalidate whenever a post changes. The server will regenerate the page instantly, bypassing the 60‑second window.
Checking That ISR Works
- Local test: Run
npm run dev, visit a blog post, and open the browser’s network tab. The request should show a200 OKwith aCache-Control: max-age=0, stale-while-revalidate=59header. - Deploy test: Push to Vercel, trigger the revalidate endpoint, and observe a new
200 OKafter the regeneration finishes. - Cache check: In the
.next/cachedirectory, look for thepages/blog/[slug]folder. The timestamp should update after regeneration.
Trade‑offs & Limitations
- Stale window: Without an external trigger, content may stay stale up to the revalidate interval. For highly time‑sensitive posts, consider a shorter interval or on‑demand regeneration.
- Cold start: The first request after a page has been invalidated may hit a serverless function cold start, adding latency.
- Complexity: Adding an API route and secret handling increases the attack surface. Keep secrets secure and rotate them regularly.
- Cache consistency: If you use a CDN, ensure that cache headers are respected so that the regenerated page propagates correctly.
Actionable Next Steps
- Set
revalidateto a sensible default (e.g., 60 s) for all blog pages. - Implement the
/api/revalidateroute and secure it with a strong secret. - Configure your CMS to send a POST to that endpoint whenever a post is published or updated.
- Monitor the
.next/cachefolder or use Vercel’s logs to confirm regeneration events. - Adjust the revalidate interval based on content freshness needs and observed latency.
By combining ISR with an on‑demand trigger, you keep the speed of static sites while giving editors near‑real‑time publishing power.