Keeping Static Pages Fresh with Incremental Static Regeneration in Next.js
Learn how Incremental Static Regeneration (ISR) in Next.js lets you keep static pages fresh without rebuilding the entire site. A step‑by‑step example, trade‑offs, and verification tips are included.
19 Oct 2025, 04:33 UTC

Why Your Static Site Needs a Refresh Button
Static Site Generation (SSG) in Next.js lets you pre‑render pages at build time, giving you blazing performance and SEO benefits. The catch is that the content is only as fresh as the last build. If you have a news site, a product catalog, or any data that changes more often than your CI pipeline, you’ll end up serving stale pages until the next full rebuild.
Incremental Static Regeneration (ISR) solves this by letting you specify a revalidate interval in getStaticProps. After the interval expires, Next.js will regenerate the page in the background the next time it’s requested. Users see the cached version until the new build finishes, at which point the CDN or server serves the fresh page.
Core Concept in One Line
Set revalidate: N (seconds) in getStaticProps, and Next.js will automatically rebuild that page in the background on the next request after N seconds.
Practical Usage: A Step‑by‑Step Example
- Create a simple page that fetches data from an external API.
- Return a
revalidatevalue fromgetStaticProps. - Deploy to a platform that supports stale‑while‑revalidate (e.g., Vercel).
- Observe the regeneration in the logs or by inspecting response headers.
Below is a concrete example that fetches the latest posts from a placeholder API and revalidates every 60 seconds.
import { useEffect } from "react";
export default function Blog({ posts }) {
return (
{posts.map((p) => (
-
{p.title}
{p.body}
))}
);
}
export async function getStaticProps() {
const res = await fetch("https://jsonplaceholder.typicode.com/posts");
const posts = await res.json();
return {
props: { posts },
// Rebuild this page in the background after 60 seconds.
revalidate: 60,
};
}
Deploy this to Vercel. After the first request, the page is cached. Once 60 seconds have passed, the next visitor triggers a regeneration. In the Vercel dashboard you’ll see a “Revalidation” entry in the deployment logs, and the response header X‑Next‑Revalidate will contain the timestamp of the last successful rebuild.
Dynamic Routes and Fallback Strategies
ISR also works for dynamic routes generated with getStaticPaths. When you set fallback: "blocking", the first request to a new path will generate the page on the fly, then cache it for subsequent requests. After the revalidate interval, the next request will trigger an in‑background rebuild.
Example for a product page:
export async function getStaticPaths() {
const res = await fetch("https://api.example.com/products");
const products = await res.json();
const paths = products.map((p) => ({ params: { id: p.id.toString() } }));
return { paths, fallback: "blocking" };
}
export async function getStaticProps({ params }) {
const res = await fetch(`https://api.example.com/products/${params.id}`);
const product = await res.json();
return {
props: { product },
revalidate: 120, // 2 minutes
};
}
Trade‑offs and Limitations
- CDN or server support required. ISR relies on stale‑while‑revalidate semantics. On a plain Node.js server without a CDN, the background regeneration might not happen as expected.
- Short revalidate intervals increase load. A
revalidateof 1 second will cause a rebuild on almost every request, potentially overloading your API or build system. - Stale content window. Data that changes more frequently than the revalidate period will be out of date until the next regeneration. For truly hyper‑dynamic data, consider client‑side fetching or Edge Functions.
- Deployment cost. Each regeneration triggers a new build step that may incur build minutes on platforms like Vercel.
How to Verify ISR in Production
- Deploy the example to Vercel or another CDN‑enabled platform.
- Open the page in a browser and note the timestamp (you can add a
{new Date().toISOString()}in the component for visibility). - Wait for the
revalidateinterval to pass. - Refresh the page; the timestamp should update without a full page reload.
- Check the deployment logs for a “Revalidation” event and inspect the
X‑Next‑Revalidateheader in the network tab.
When ISR Is the Right Choice
- You need the performance of SSG but your data updates moderately often.
- Your deployment target supports stale‑while‑revalidate (Vercel, Netlify, Cloudflare Pages).
- You can tolerate a small window of stale data (seconds to a few minutes).
Actionable Takeaway
Start by adding a revalidate key to the pages that change most often. Test the regeneration in a staging environment, monitor the logs for frequent rebuilds, and adjust the interval to balance freshness against load. If you hit the limits of ISR, mix it with client‑side fetching for the most dynamic parts of your site.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.