Skip to content

[BUG] ISR page regenerates on every pageload when using a dynamic route #754

Open
@gianjohansen

Description

@gianjohansen

Describe the bug

Hi, when I have ISR set up for a dynamic route (eg [dynamicId]/page.tsx) the revalidate time is ignored and the page is rebuilt on every page load.

The same nextjs project deployed to Vercel without OpenNext will correctly wait out the timer before regenerating.

I also have a static route deployed to the same Cloudflare worker and that does wait out the revalidate time, so I don't think it's an issue with my R2/doQueue setup.

The dynamic route is listed as "SSG" during build time:

Route (app)                                 Size  First Load JS  Revalidate  Expire
┌ ○ /                                      139 B         101 kB          5m      1y
├ ○ /_not-found                            977 B         102 kB
└ ● /[dynamicId]                           139 B         101 kB
+ First Load JS shared by all             101 kB
  ├ chunks/4bd1b696-67ee12fb04071d3b.js  53.2 kB
  ├ chunks/684-42609a042cd3abcf.js       45.9 kB
  └ other shared chunks (total)          1.89 kB


○  (Static)  prerendered as static content
●  (SSG)     prerendered as static HTML (uses generateStaticParams)

Demo:

Using export const revalidate = 300. I've linked the repo below.

Deployed to Cloudflare Worker (triggers regeneration every pageload):

Screencast.From.2025-06-30.11-34-33.webm

Deployed to Vercel (will not regenerate until the revalidate time):

Screencast.From.2025-06-30.11-31-51.webm

Steps to reproduce

Minimal repro - [dynamicId]/page.tsx:

https://github.com/gianjohansen/isr-revalidate-frequency

You can see it deployed here:

OpenNext: https://isr-revalidate-frequency.gian-johansen.workers.dev/123
Vercel: https://isr-revalidate-frequency-vercel.vercel.app/123

A static page on the same Cloudflare worker which does have working ISR:

https://isr-revalidate-frequency.gian-johansen.workers.dev

The dynamic route uses this code:

type Params = Promise<{ dynamicId: string }>;

export const revalidate = 300;
export const dynamicParams = true;

export async function generateStaticParams() {
  return []; // no generated pages at build time
}

export default async function DynamicPage({ params }: { params: Params }) {
  const { dynamicId } = await params;

  const buildTime = new Date().toLocaleTimeString();
  const nextBuildTime = new Date(Date.now() + revalidate * 1000).toLocaleTimeString();
  
  return (
    <div className="flex flex-col gap-1 items-center justify-center h-screen">
      <p>Dynamic ID: {dynamicId}</p>
      <p>Last built at: <strong>{buildTime} (UTC)</strong></p>
      <p>Should regenerate at: <strong>{nextBuildTime} (UTC)</strong></p>
    </div>
  );
}

Expected behavior

The page should only regenerate after the revalidate time has passed. Should match the behaviour of the Vercel deployment.

@opennextjs/cloudflare version

1.3.1

Wrangler version

4.22.0

next info output

Operating System:
  Platform: linux
  Arch: x64
  Version: #28-Ubuntu SMP PREEMPT_DYNAMIC Mon May 19 14:45:34 UTC 2025
  Available memory (MB): 31728
  Available CPU cores: 32
Binaries:
  Node: 22.14.0
  npm: 10.9.2
  Yarn: N/A
  pnpm: 10.11.0
Relevant Packages:
  next: 15.3.4 // Latest available version is detected (15.3.4).
  eslint-config-next: 15.3.4
  react: 19.1.0
  react-dom: 19.1.0
  typescript: 5.8.3
Next.js Config:
  output: N/A

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingtriage

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions