Pages

Tuesday, 9 June 2026

ISR in Next.js App Router: Why Your Pages Aren't Updating

 

When building content-driven sites using Next.js App Router, many developers encounter a common issue: API data has been updated, yet page content remains unchanged for an extended period.

This is typically not due to incorrect cache configuration, nor solely because ISR is "unreliable." More often, it stems from misunderstandings about how ISR actually operates and the trade-offs it intentionally makes. This article will explain ISR's actual behavior within App Router—and the problems it can and cannot solve—by examining a real-world troubleshooting case.

Where the Problem Began

Why isn't the homepage content updating after API data refreshes?

While maintaining a content-driven website recently, I encountered an issue during testing: the homepage failed to update after new data was added to the database. Initially, I suspected Cloudflare caching the API response. Postman requests confirmed the data had updated. I then investigated caching on both frontend and backend deployment platforms but found no issues. After recompiling and redeploying the frontend code, the homepage data updated correctly. This narrowed the fault to Next.js's caching mechanism.

A Common Yet Dangerous Equation

API is dynamic ≠ Page will update

Typically, we instinctively assume that changes in API data directly trigger page content updates, following the sequence: API data update -> Page request fetches new data -> Page content updates. However, in certain scenarios, this rendering process breaks down. A commonly overlooked point is whether the page is regenerated—meaning there's a disconnect between data changes and page generation.

We often mistakenly treat Next.js's App Router data fetching as a reactive system that automatically propagates data changes. The official documentation describes it thus:

Caching is a technique for storing the result of data fetching and other computations so that future requests for the same data can be served faster, without doing the work again. While revalidation allows you to update cache entries without having to rebuild your entire application.

This indicates that Next.js's rendered page results can be reused.

What Problem Does ISR Solve?

Before ISR, content-focused sites faced a dilemma:

  • Pure SSG: Stable pages but delayed updates, leaving users seeing outdated content
  • Pure SSR: Timely content delivery but high server load and response times

Unlike e-commerce sites demanding real-time updates, content-driven sites typically require less immediate data freshness—yet they cannot remain static forever. ISR emerged precisely to bridge this gap. ISR was designed to strike a balance between SSG and SSR, enabling pages to leverage the performance benefits of static generation while maintaining content updates within acceptable timeframes.

ISR's design assumptions:

  • Delay is tolerable
  • Inconsistencies are temporary

ISR's core objective is trading time for stability—exchanging predictable latency for deployment and caching benefits. It is not designed for frequently changing data and inherently does not pursue real-time updates.

How ISR Actually Works

When exactly does a page update? It's not "auto-refreshing every N seconds," but rather triggering an update upon the "next visit" after exceeding N seconds.

Contrary to first impressions, ISR isn't a background refresh timer. When the revalidate cycle arrives, pre-generated pages don't update immediately—they wait for the next user visit to trigger the update.

Example:

  • A page set to revalidate: 60 means content can update every 60 seconds
  • User A visits the page at 12:00:00; the page is generated and cached
  • User B visits the page at 12:00:30; the content displayed remains what User A saw
  • User C visits the page at 12:01:05; the revalidate cycle expires, triggering page regeneration in the background, but User C still receives the stale response
  • User D visits the page at 12:01:10, and the page content updates to the latest version, triggered by User C's visit

From the above example, it's clear that page updates in ISR are passively triggered—checking for regeneration only occurs when a user visits. This means delayed visibility is a deliberate design choice, not a flaw.

Advantages and Trade-offs of ISR Compared to Other Rendering Strategies

This is not an evolutionary path, but a trade-off

ISR vs. SSG:

  • Solves the problem of long-term static content by enabling periodic page updates, though not real-time
  • Retains the caching benefits of static generation: fast response times and low server load

ISR vs. SSR:

  • Reduces server load; stable, cacheable content lowers costs
  • Sacrifices real-time content; introduces latency and inconsistency, cannot guarantee freshness on every visit

ISR offers predictable behavior and controllable costs, but isn't suitable for scenarios requiring strong consistency or real-time updates. ISR isn't an upgrade over SSR/SSG—it's a distinct choice

dynamic vs revalidate

dynamic is not a "bug switch," but a solution for different scenarios

In Next.js App Router, dynamic and revalidate are distinct rendering strategies: dynamic determines "whether to render each time," while revalidate determines "whether to reuse old pages."

When a site's content must reflect the latest state on every visit, or when content is highly context-dependent, delayed visibility is unacceptable. dynamic re-renders on every visit, making it ideal for this scenario. Conversely, when page content is relatively stable, revalidate offers a suitable solution. It trades time for stability by allowing some delay.

If I notice a site's homepage isn't updating promptly, I might choose dynamic to ensure fresh content on every visit. This seems like a solution, but it merely shifts the problem to a different scenario. dynamic and revalidate aren't mutually exclusive choices—they represent different rendering strategies for distinct requirements.

Page-Level Revalidation vs. API-Level Revalidation

Granularity depends on consistency requirements, not flexibility

Consider a news site homepage with multiple sections: Today's News, Yesterday's News, etc. When these sections fetch data from separate APIs and use API-level revalidation, this scenario may occur: Today's News remains unchanged while Yesterday's News updates. If spanning multiple days, this could even create a disjointed scenario where Yesterday's News appears more recent than Today's News—directly undermining the site's credibility.

For pages aggregating multiple APIs, API-level revalidate struggles to guarantee content consistency. As the final delivery point, the aggregated page should shoulder consistency responsibility, making page-level revalidate more advantageous. Similarly, if a page's content originates from multiple interfaces but lacks strict suppression requirements between modules, API-level revalidate may be considered for higher performance. Ultimately, the choice of revalidate granularity should be based on the page's consistency requirements, not flexibility.

ISR Behavior in Low-Traffic Content Sites

Why does the website seem broken?

As mentioned earlier, ISR can be configured to revalidate, triggering page updates on the user's next visit. When site traffic is very low, page refresh frequency drastically decreases, potentially leading to pages remaining unchanged for extended periods. When users visit such pages, they may see content that is days or even weeks old, creating the impression that the website is "broken."

This is actually an intended outcome of ISR design. When User A visits a page, they see content generated long ago, and their visit triggers a page re-generation. However, due to the potentially days-long intervals between visits on low-traffic sites, by the time User B visits next, the page content remains the version last updated by User A. Consequently, User B still sees outdated information.

For low-traffic content sites, traffic volume may dictate content refresh frequency. As long as this aligns with the original design intent and is acceptable, this "lazy updating" behavior is reasonable and does not indicate a "broken" website.

Does ISR Lead to Out-of-Sync Pages?

This is not an issue requiring excessive concern

While ISR implementation may indeed encounter scenarios of content asynchrony, this represents a design trade-off that should be understood and accepted—not an issue warranting undue alarm. ISR's architecture inherently permits transient inconsistencies. Rather than fixating on "whether inconsistencies occur," the critical question is whether such inconsistencies are predictable. During design, clearly define the content site's actual consistency requirements. Analyze when inconsistencies might occur and whether their potential impact is acceptable—rather than blindly pursuing timeliness or uniformity. When content inconsistencies are controllable and predictable, "page asynchrony" ceases to be an excessive concern. It becomes a known factor in the design.

Time-Driven Content ISR Strategy

Take the homepage I maintain as an example. It aggregates "Future Content" and "Latest Content" modules—time-driven content where "Future Content" manages content beyond today, while "Latest Content" manages content from today and earlier.

This introduces a trade-off between consistency and flexibility. Opting for API-level revalidate would make a module's caching strategy independent of the page, turning the homepage into an "assembled snapshot." For my homepage, this unnatural state is unacceptable. Furthermore, the homepage has a stable structure with changes occurring only at the content layer. Therefore, page-level ISR is more suitable as the overall invalidation strategy. A page-level strategy allows my pages to update and expire synchronously as a whole, avoiding a state where "part is new and part is old." This aligns with my business semantics.

Data updates on my site occur concentrated at a specific time point within a day. There is only one critical change window per day, with data remaining largely stable at other times. Setting revalidate to one day could easily result in users accessing the page before the critical window, followed by no refreshes for the entire subsequent day. Given the site's low traffic, revalidate effectively functions as "the maximum number of visit opportunities I'm willing to let this page miss daily." Considering the homepage doesn't require minute-level real-time updates, yet I also don't want it displaying stale data for half a day or an entire day, I set revalidate to 1 hour. This ensures that even with low traffic, there are 24 opportunities daily to trigger a page refresh. As long as one user visits after the critical window, they will likely see the updated data.

Why not use a smaller value, like 5 minutes? Because based on the project's actual circumstances, it's unnecessary. Setting revalidate to 5 minutes would make the page behave almost like dynamic rendering, while retaining the complexity of ISR without significant benefit. Most importantly, the business can tolerate the current threshold of latency. For me, ISR's revalidate isn't a caching parameter, but a way to model the business rhythm.

When to Transition from ISR to On-Demand Revalidate

The decision to transition to on-demand revalidate doesn't hinge on technical maturity, but on whether the "content update -> user visibility" chain begins impacting user trust.

My current site updates only during a single daily critical window, with low traffic and users likely in exploratory or occasional visit phases. Their expectations lean toward "stability" rather than "timeliness." Transitioning becomes necessary if:

  • Users start treating my site as a "near-real-time information source"
  • Data update frequency increases/becomes irregular
  • Users frequently report outdated content

This indicates my site's content has shifted from time-driven to event-driven, with users demanding greater real-time relevance. At this point, transitioning from ISR to an on-demand revalidate mechanism becomes necessary. In other words, when users begin perceiving "uncertainty in update timing," it's time to reconsider rendering strategies. On-demand revalidate represents a distinct approach for the site's new phase—not merely a patch for ISR.

Conclusion

ISR isn't unreliable—it's just placed under the wrong expectations.

ISR is valid only when site content can tolerate delays and brief inconsistencies, and when access frequency is unstable. Software engineering has no silver bullets, and ISR isn't omnipotent. The key isn't whether to use ISR, but whether you're willing to accept its inherent delays and inconsistencies. Understand ISR's design trade-offs and choose the appropriate rendering strategy based on business needs.


References

------------------------------------------

Isr,  incremental static regeneration

增量静态再生,它是SSR和SSG的结合。当一个ISR路由被访问时,页面会像SSR一样生成并存储在缓存中,然后提供给客户端。之后任何访问都会直接从缓存中获取渲染后的内容。你可以设置TTL或者无限期地保留缓存,直到你手动重新验证该路由,导致下一次访问该路由时重新以SSR方式渲染并重新缓存。

这对于例如博客文章来说非常棒。你可以无限期地缓存博客文章,当管理员编辑博客文章时,你重新验证特定的博客文章路由。这意味着更少的数据库调用,更少的服务器运行时,这转化为更少的支付给托管平台的费用... 

------------

 https://juejin.cn/post/7453286740078526516

-----------------

 

ISR(Incremental Static Regeneration)是一种Web前端开发中的静态网页生成技术。它是Next.js框架引入的一项功能,旨在改进静态站点的性能和用户体验。在了解ISR之前,我们需要先了解几个相关的概念。

静态网页生成(Static Site Generation)

静态网页生成是一种生成静态HTML文件的技术,它将数据与页面内容结合,一次性生成所有页面。这种方法的优势在于提高了网站的加载速度和性能,因为访问者可以直接获取静态HTML而无需等待服务器处理。

服务器端渲染(Server-Side Rendering)

服务器端渲染是在每次请求时动态生成HTML页面的过程。这意味着服务器负责渲染页面的内容,并将最终的HTML发送给客户端。这种方法的好处是可以在每次请求时动态地生成页面,以确保始终提供最新的数据。

预渲染(Pre-rendering)

预渲染是一种在构建时生成页面的技术,它不像静态网页生成那样在每次请求时生成。这样可以减轻服务器的负担,但在某些情况下可能会导致页面内容过时。

ISR 的工作原理

ISR 结合了静态网页生成和服务器端渲染的优点。它的核心思想是在构建时生成静态页面,然后在运行时根据需要进行更新。这意味着你可以预先生成大部分静态页面,然后根据用户的请求,在需要时再重新生成某些页面。

在 Next.js 中,ISR 是通过在页面组件中使用 getStaticProps 函数实现的。这个函数在构建时运行,用于获取页面所需的数据。通过在 getStaticProps 中使用 revalidate 选项,可以指定页面的重新生成时间,即多长时间后页面内容将被更新。如果用户在这段时间内访问该页面,他们将获得旧的静态页面,而同时,Next.js 会在后台异步重新生成新的页面内容,并在下一次请求时提供更新后的页面。

ISR 的优势

  1. 提高性能: ISR 允许大部分页面在构建时生成,从而提高了网站的加载速度。用户可以立即获取静态页面,而不必等待服务器响应。
  2. 实时数据 与传统的静态网页生成不同,ISR 可以在需要时动态更新页面内容。这意味着你可以在不牺牲性能的情况下获取实时数据。
  3. 降低服务器负担: 由于大部分页面在构建时生成,服务器无需在每次请求时都动态生成页面,从而降低了服务器的负担。

举例说明

假设我们有一个博客网站,每篇博客文章都是一个页面。我们希望实现ISR,以便在用户访问每篇文章时,能够提供最新的内容。

  1. 创建博客文章页面

```jsx // pages/blog/[slug].js

import { useRouter } from 'next/router'; import { getStaticProps } from 'next';

const BlogPost = ({ postData }) => { const router = useRouter();

if (router.isFallback) {
   return <div>Loading...</div>;
 }

 return (
   <div>
     <h1>{postData.title}</h1>
     <p>{postData.content}</p>
   </div>
 );

};

export async function getStaticPaths() { // Fetch the list of blog post slugs const paths = getBlogPostSlugs();

return {
   paths,
   fallback: true, // Set to true to enable ISR
 };

}

export async function getStaticProps({ params }) { // Fetch necessary data for the blog post using the slug const postData = getBlogPostData(params.slug);

return {
   props: {
     postData,
   },
   revalidate: 60, // Regenerate page every 60 seconds (1 minute)
 };

}

export default BlogPost; ```

  1. 启用 ISR

在上述代码中,我们通过设置 fallback: true 启用了 ISR。这意味着如果用户访问的页面在构建时不存在(例如,新发布的博客文章),Next.js 会在后台重新生成页面并提供更新后的内容。同时,我们通过 revalidate 选项指定了页面重新生成的时间间隔。

这样,用户可以立即获取现有的静态页面,并在稍后获取更新的内容,而不必等待重新生成。

总体来说,ISR 是一项强大的技术,能够在静态网页生成和服务器端渲染之间找到平衡,提供高性能和实时数据更新的优势。在构建现代Web应用程序时,特别是对于内容频繁变化的页面,使用ISR可以显著改善用户体验。

SSG 是预先生成网页的过程,这意味着在构建阶段,我们会生成所有可能的页面并保存下来。然后,当用户请求一个页面时,我们只需从存储中获取预生成的页面并将其发送给用户。这种方式的好处是,因为页面已经预生成,所以响应速度非常快。然而,对于内容经常变化的网站来说,SSG 不是一个理想的选择,因为每次内容更新,都需要重新构建整个网站。

SSR 则是在用户请求一个页面时,服务器会生成并返回该页面。这意味着每个请求都会触发一个生成页面的过程。这种方式的好处是,能够处理内容频繁更新的情况。然而,因为每个请求都需要生成页面,所以可能会增加服务器的负担,并且可能导致响应时间变慢。

ISR 试图将 SSG 和 SSR 的优点结合起来。在 ISR 中,页面在构建阶段会被预生成,但是可以设置一个 fallback 参数来处理那些未在构建阶段生成的页面。当用户请求一个未预生成的页面时,Next.js 会在后台生成该页面,并返回一个 “fallback” 页面给用户。一旦页面生成,Next.js 会保存它,以便下次请求时可以立即返回。

另外,ISR 还引入了一个 revalidate 参数。这个参数定义了在多长时间后,页面应该被重新生成。例如,如果 revalidate 设置为 1,那么每隔 1 秒,Next.js 会检查页面是否需要更新。如果需要,Next.js 会在后台重新生成页面,并在下次请求时返回新的页面。

让我们以一个博客网站为例来说明 ISR 的使用。假设我们有一个博客网站,其中包含数千篇博客文章。每篇文章都有自己的页面,而且每天都会有新的文章发布。

如果我们使用传统的 SSG,那么每次新文章发布时,我们都需要重新构建整个网站,这将花费大量的时间和计算资源。如果我们使用 SSR,那么每次用户请求一篇文章时,我们都需要在服务器上生成那个页面,这可能会使服务器的负担加重,并可能导致响应时间变慢。

No comments:

Post a Comment