> incremental static regeneration in next.js

// august 20, 2020

Incremental Static Regeneration in Next.js

Incremental Static Regeneration in Next.js

Next.js v9.5 introduced a feature that fundamentally changes the static site generation landscape: Incremental Static Regeneration (ISR). Combined with built-in Web Vitals measurement and improved environment variable handling, this release represented a significant step forward for the React ecosystem.

The Static vs. Dynamic Dilemma

Traditional web development forces a choice:

  • Static Site Generation (SSG) — pages built at deploy time. Blazing fast, but stale until the next build
  • Server-Side Rendering (SSR) — pages generated per request. Always fresh, but slower and more resource-intensive

ISR offers a third path: statically generated pages that automatically regenerate in the background after a specified interval.

How ISR Works

The concept is elegantly simple. In getStaticProps, you add a revalidate property:

export async function getStaticProps() {
  const posts = await fetchBlogPosts();

  return {
    props: { posts },
    revalidate: 60, // regenerate at most every 60 seconds
  };
}

Here's what happens:

  1. At build time, the page is statically generated as usual
  2. For the first 60 seconds, every request serves the cached static page — no server computation
  3. After 60 seconds, the next request still serves the stale page (for speed), but triggers a background regeneration
  4. Once regeneration completes, subsequent requests serve the fresh page
  5. If regeneration fails, the previous version continues to be served

This is the stale-while-revalidate pattern, borrowed from HTTP caching semantics and applied at the page level.

Real-World Benefits

For a university course portal I built with Next.js, ISR solved a concrete problem. The site displayed:

  • Course schedules updated weekly by faculty
  • Student project galleries updated by TAs
  • Announcement feeds from multiple sources

Previously, any content change required a full rebuild and redeploy. With ISR, I set revalidate: 300 (5 minutes), and the site stays current without manual intervention. Build times dropped from 4 minutes to 30 seconds since only a shell of pages needs initial generation.

Web Vitals Integration

Next.js 9.5 also improved the built-in Web Vitals reporting function:

export function reportWebVitals(metric) {
  if (metric.label === 'web-vital') {
    console.log(metric.name, metric.value);
    // Send to analytics endpoint
    analytics.track(metric.name, { value: metric.value });
  }
}

This reports Core Web Vitals (LCP, FID, CLS) and Next.js-specific metrics (hydration time, route change duration) directly from real user sessions. For academic projects, this data helped students understand the performance impact of their architectural decisions.

Environment Configuration

The updated environment variable system brought clarity to a previously confusing area:

  • .env.local — local overrides, gitignored by default
  • .env.development / .env.production — environment-specific defaults
  • NEXT_PUBLIC_ prefix — variables exposed to the browser bundle
# .env.local
DATABASE_URL=postgresql://localhost:5432/mydb
NEXT_PUBLIC_API_URL=https://api.example.com

No more next.config.js hacks or webpack DefinePlugin configuration. The convention is clear and secure — server-only variables stay on the server unless explicitly prefixed.

When to Use ISR

ISR works best when:

  • Content changes periodically but not in real-time
  • You want CDN-level performance without sacrificing freshness
  • Rebuild times are becoming a bottleneck
  • You need guaranteed uptime even when the data source is temporarily unavailable

It's less suitable for highly personalized content or data that must be real-time accurate (financial dashboards, live scores).

Conclusion

Incremental Static Regeneration represents a thoughtful evolution in how we think about rendering strategies. Rather than forcing developers to choose between static and dynamic, it offers a pragmatic middle ground that works well for the majority of content-driven applications.