Incremental Static Regeneration (ISR) lets a Next.js site regenerate static pages in the background after deployment, combining static performance with content freshness — this guide covers setting it up on a self-hosted VPS.
The Problem ISR Solves
Pure static generation requires a full rebuild/redeploy to reflect content changes; pure server-side rendering sacrifices static performance benefits — ISR offers a middle ground: pages are statically generated but can be regenerated periodically or on-demand without a full site rebuild.
Basic ISR Configuration
export async function getStaticProps() {
const data = await fetchContent();
return {
props: { data },
revalidate: 60,
};
}
revalidate: 60 means this page can be regenerated at most once every 60 seconds — the first request after that window triggers a background regeneration, while still serving the previous (slightly stale) version instantly to that request.
Running Next.js with ISR Support on a VPS
Unlike pure static export (see How to Deploy a Next.js Application on a VPS), ISR requires the Next.js server actually running (not just static files served by Nginx) — since it needs to handle the background regeneration logic; deploy using the standard Node.js server mode.
Setting Up the Node.js Server Process
npm run build
npm run start
Run behind PM2 or as a systemd service (see general Node.js deployment patterns) with Nginx reverse proxying to it, similar to How to Set Up Nginx as a Reverse Proxy for Node.js Apps.
On-Demand Revalidation (More Precise Control)
export default async function handler(req, res) {
await res.revalidate('/blog/my-post');
return res.json({ revalidated: true });
}
Rather than time-based revalidation, trigger regeneration explicitly (from a CMS webhook, for example, when content is actually published/updated) — more precise than waiting for a time-based window, ensuring freshness exactly when content genuinely changes.
Combining with a Headless CMS
See How to Set Up a Jamstack Site with a Headless CMS Backend — ISR pairs naturally with a headless CMS: content editors publish changes, a webhook triggers on-demand revalidation, and the specific affected pages regenerate without a full site rebuild.
Understanding the Caching Behavior
Between regenerations, all requests receive the same cached static page — extremely fast, since no per-request server-side work happens for cached pages; only the periodic (or triggered) regeneration involves actual server-side computation.
Monitoring Regeneration Behavior
Log or monitor when pages actually regenerate — helps verify your revalidation configuration behaves as expected, particularly important when troubleshooting content that seems to update slower than anticipated.
When ISR Might Not Be the Right Fit
For content that's genuinely static (rarely changes) pure static generation is simpler and avoids running a persistent Node.js server; for content needing truly real-time freshness on every request, full server-side rendering may be more appropriate — ISR fits the middle ground of "changes periodically but not on every single request."
Common Errors
Pages never seem to update despite content changes — verify the revalidation window/trigger is actually configured correctly, and confirm the Next.js server process (not just static files) is genuinely running, since ISR requires the server component to function.
Continue Reading
- How to Deploy a Next.js Application on a VPS
- How to Set Up a Jamstack Site with a Headless CMS Backend
- How to Set Up Nginx as a Reverse Proxy for Node.js Apps
Browse more articles in Static Site Hosting & Frontend Deployment.