revalidate, on-demand triggers, and real pitfalls
Incremental Static Regeneration combines the speed of static pages with the freshness of server-rendered content by regenerating individual pages in the background, without triggering a full rebuild. Using revalidate, revalidatePath, and revalidateTag correctly avoids stale content without losing the cache benefits.
Table of Contents
- 1. What Incremental Static Regeneration solves
- 2. Configuring revalidate: time-based vs on-demand
- 3. On-demand revalidation with revalidatePath and revalidateTag
- 4. Stale-While-Revalidate behavior in detail
- 5. ISR and dynamic routes with generateStaticParams
- 6. Caching pitfalls with ISR in practice
- 7. ISR compared to SSG and SSR
- 8. Monitoring and debugging ISR in production
- 9. ISR compared directly
- 10. Summary
- 11. FAQ
1. What Incremental Static Regeneration solves
Incremental Static Regeneration, ISR for short, solves a trade-off that used to force teams to choose between speed and freshness before Next.js. Purely static pages are extremely fast because they are pre-built and served from a CDN, but they go stale the moment the underlying data changes, until a full rebuild runs. Classic SSR always delivers current data, but costs server time on every request. Incremental Static Regeneration combines both worlds: pages are pre-generated statically like SSG, but automatically rebuilt in the background after a defined time, without any user having to wait for that rebuild.
The decisive advantage of Incremental Static Regeneration over a full site rebuild is granularity: only the actually requested, stale page gets regenerated, not the entire website. For an online store with tens of thousands of product pages, a full rebuild on every price change would take minutes or hours. With Incremental Static Regeneration, only the affected product page gets rebuilt, while every other page continues to be served unchanged from the cache.
Next.js implements Incremental Static Regeneration via two complementary mechanisms: time-based revalidation through the revalidate export, and event-driven on-demand revalidation through revalidatePath and revalidateTag. Both mechanisms are covered in detail in the following sections and can also be combined in practice.
2. Configuring revalidate: time-based vs on-demand
The simplest form of Incremental Static Regeneration is time-based revalidation via export const revalidate = 3600 in a Server Component. This value defines that a page is considered stale after at most one hour, and gets regenerated in the background on the next request, while the user who requests the stale version immediately receives the still-cached response. Only the user after that one sees the newly regenerated version.
This time-based strategy works excellently for content with a predictable change frequency, say blog posts that are rarely edited afterward, or product catalogs with planned price changes at specific times. For content whose change moment is unpredictable, say stock levels that change with every completed purchase, a pure time strategy falls short: between two revalidation intervals, users can see stale stock data. For such cases, on-demand revalidation, covered in the next section, is the better choice.