Next.js allows you to create or update static pages after you've built your site. Incremental Static Regeneration (ISR) enables developers and content editors to use static-generation on a per-page basis, without needing to rebuild the entire site. With ISR, you can retain the benefits of static while scaling to millions of pages.

Static pages can be generated at runtime (on-demand) instead of at build-time with ISR. Using analytics, A/B testing, or other metrics, you are equipped with the flexibility to make your own tradeoff on build times.

Consider an e-commerce store with 100,000 products. At a realistic 50ms to statically generate each product page, the build would take almost 2 hours without ISR. With ISR, we can choose from:

  • Faster Builds → Generate the most popular 1,000 products at build-time. Requests made to other products will be a cache miss and statically generate on-demand: 1-minute builds.
  • Higher Cache Hit Rate → Generate 10,000 products at build-time, ensuring more products are cached ahead of a user's request: 8-minute builds.

The Advantage of ISR: You have the flexibility to choose which pages are generated at build or on-demand. Choose from (A) faster builds or (B) more cached.

Fetching Data

ISR uses the same Next.js API to generate static pages: getStaticProps. By specifying revalidate: 60, we inform Next.js to use ISR to update this page after it's generated.

A diagram of the request flow for Incremental Static Regeneration.

  1. Next.js can define a revalidation time per-page (e.g. 60 seconds).
  2. The initial request to the product page will show the cached page.
  3. The data for the product is updated in the CMS.
  4. Any requests to the page after the initial request and before the 60 seconds window will show the cached (stale) page.
  5. After the 60 second window, the next request will still show the cached (stale) page. Next.js triggers a regeneration of the page in the background.
  6. Once the page has been successfully generated, Next.js will invalidate the cache and show the updated product page. If the background regeneration fails, the old page remains unaltered.
// pages/products/[id].js

export async function getStaticProps({ params }) {
  return {
    props: {
      product: await getProductFromDatabase(params.id),
    },
    revalidate: 60,
  }
}

Generating Paths

Next.js defines which pages to generate at build-time based on the paths returned by getStaticPaths. For example, you can generate the most popular 1,000 products at build-time by returning the paths for the top 1,000 product IDs in getStaticPaths.

The remaining pages can be generated on-demand by specifying fallback as blocking or true in getStaticPaths:

  • fallback: blocking (preferred) – when a request is made to a page that hasn't been generated, Next.js will server-render the page on the first request. Future requests will serve the static file from the cache.
  • fallback: true – when a request is made to a page that hasn't been generated, Next.js will immediately serve a static page with a loading state on the first request. When the data is finished loading, the page will re-render using this data and be cached. Future requests will serve the static file from the cache.
// pages/products/[id].js

export async function getStaticPaths() {
  const products = await getTop1000Products()
  const paths = products.map((product) => ({
    params: { id: product.id },
  }))

  return { paths, fallback: 'blocking' }
}

ISR: Not Just Caching

ISR is designed to persist your generated pages between deployments. This means you are able to rollback instantly and not lose your previously generated pages.

Each deployment is keyed by an ID, which Vercel and Next.js use to persist statically generated pages. When you rollback, Vercel will update the key to point to the previous deployment, allowing for atomic deployments. This means you can visit your previous immutable deployments and they’ll work as intended.

Here’s an example of reverting code with ISR:

  1. You push code and get a deployment ID 123.
  2. Your page contains a typo Vcrl.
  3. You update the page in the CMS. No redeploy needed.
  4. Once your page shows Vercel it’s persisted in storage.
  5. You push some bad code and deploy ID 345.
  6. You roll back to deployment ID 123.
  7. You still see Vercel.

Furthermore, with ISR, your incrementally generated pages can be available in every region. If you use server-rendering with cache-control headers instead, caches expire (by design) and are not shared across regions.

Examples of Incremental Static Regeneration

Incremental Static Regeneration works well for e-commerce, marketing pages, blog posts, ad-backed media, and more.

  • E-commerce Demo – Next.js Commerce is an all-in-one starter kit for high-performance e-commerce sites.
  • GitHub Reactions Demo – React to the original GitHub issue and watch ISR update the statically generated landing page.
  • Static Tweets Demo – This project deploys in 30 seconds, but can statically generate 500M tweets on-demand using ISR.

Vercel customers like HashiCorp and Tuft & Needle use ISR to deliver a better user experience.


Last Edited on April 21st 2021