Technical
ISR in Production: Incremental Static Regeneration Without Surprises
Next.js ISR is one of those features that looks magical in the docs and gets weird in production. Stale pages. Revalidation storms. Cache mismatches. I have now run ISR for six months on a site that matters. Here is what actually works and what to watch out for.
What ISR Is Doing
ISR lets you serve a page from a static build, but regenerate it in the background on a schedule or on-demand. The user gets fast static HTML. The content stays fresh. In theory, it is the best of both worlds.
In practice, the moving parts are:
- The static cache layer (CDN edge)
- The revalidation trigger (timer or manual)
- The backend that generates the new version
- The cache invalidation that propagates the new version
When any of those gets out of sync, you see stale content. Most ISR issues are cache sync issues in disguise.
The Revalidate Interval Trap
export const revalidate = 60; // secondsThat one line says "regenerate every 60 seconds if there is traffic." The catch is "if there is traffic." A page with no traffic never regenerates. A page with bursty traffic regenerates many times in a minute, then not at all for an hour. The interval is a minimum, not a guarantee.
On-Demand Revalidation
For content-driven pages, I use on-demand revalidation instead. When a post changes, I call the revalidation endpoint with the slug. That page regenerates immediately, everything else stays cached:
await fetch('/api/revalidate?path=/posts/' + slug, {
headers: { 'x-revalidate-token': process.env.REVALIDATE_TOKEN! },
});That pattern gives me both speed and freshness. Pages are static by default. Updates are immediate. Traffic has no effect on freshness.
The Cache Mismatch Failure
The worst ISR bug I hit was a mismatch between the app-level cache and the CDN cache. App-level cache was fresh. CDN cache was stale. Users saw stale pages, I saw fresh ones. Fix: make sure revalidation triggers both layers. I now explicitly purge the CDN cache on critical revalidations.
What Works in Production
- On-demand revalidation for content-driven pages
- Time-based revalidation for aggregations (category lists, recent posts)
- Explicit CDN purge on critical content changes
- Monitoring: I alert on pages that have not regenerated in 24 hours
ISR is powerful, but it is not magic. Treat it like a cache layer that needs explicit management, not a feature that just works. Your users will see the difference.
The Next.js ISR documentation has the full API.
RELATED READING
The Consulting Shift I Am Making In Year Two
After a year of writing and building, my consulting practice is changing shape. Shorter engagements. Sharper outcomes.
ReadThe Frontend Shift: Shipping Less JavaScript In Year Two
A year ago I reached for Next.js for everything. This year I often reach for nothing.
ReadThe Serverless Lesson I Would Write On A Sticky Note
After a year of shipping serverless projects, one rule explains most of the wins and all of the losses.
Read