Skip to content

fix(pages): prevent request props from entering ISR - #3067

Open
NathanDrake2406 wants to merge 16 commits into
cloudflare:mainfrom
NathanDrake2406:nathan/fix-isr-app-props-cache-isolation
Open

fix(pages): prevent request props from entering ISR#3067
NathanDrake2406 wants to merge 16 commits into
cloudflare:mainfrom
NathanDrake2406:nathan/fix-isr-app-props-cache-isolation

Conversation

@NathanDrake2406

@NathanDrake2406 NathanDrake2406 commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Overview

Goal Prevent request-derived custom App props from entering shared Pages Router output.
Core change Treat getStaticProps pages with a custom App.getInitialProps as request-aware at runtime and during prerendering.
Key boundary A response is reusable only when its App props and final cache policy permit sharing.
Expected impact One request cannot expose its App props through ISR or static output to a later request.

Why

App.getInitialProps receives the live request and can read cookies or headers. Vinext cannot prove that a custom implementation is request-independent.

For example, a custom App can read a tenant cookie. A request for tenant A could store tenant A props in ISR. A later tenant B request could then receive those props. When the page also uses getStaticProps, the combined output is not safe to share.

Area Invariant Change
Runtime cache Request-derived custom App props must not enter shared ISR state. Bypass all ISR reads, writes, and regeneration for the request-aware combination.
Page data APIs A page component cannot use its own getInitialProps with getStaticProps. Reject the invalid combination during development, runtime, rendering, and static-path discovery.
Response policy Later processing must not weaken an explicit non-shareable policy. Preserve private and no-store through terminal paths and final header merges.
Build output Non-shareable output must not become a reusable artifact or an incomplete export. Skip request-aware output in default builds and fail static export. Keep no-cache output eligible.
Cloudflare cache Directive matching must follow case-insensitive HTTP token rules. Detect non-shareable directives without case sensitivity.

What changed

Scenario Before After
Fresh or stale ISR entry Vinext could return shared custom App props. Vinext ignores the entry and renders request-specific App props.
Cache miss, fallback, or revalidation Vinext could create or replace a shared entry. Vinext bypasses writes, background regeneration, and on-demand revalidation.
Redirect, notFound, 404, or 500 path A terminal path could lose the request-aware policy. The path keeps the explicit non-shareable policy, including recursive error rendering.
Middleware or config header merge A later header could weaken the rendered policy. The explicit rendered policy remains authoritative.
Page getInitialProps plus getStaticProps Development, runtime, and build checks could differ. Missing or empty static paths could hide the conflict. All paths reject the invalid combination. Static-path discovery validates before it checks or calls getStaticPaths.
Request-aware default prerender Vinext could emit reusable HTML or data output. Vinext skips successful, redirect, and custom 404 artifacts.
Request-aware static export Vinext could omit required HTML and still succeed. Static export records an error and fails.
Cache-Control: no-cache Vinext could misclassify a valid static response as dynamic. Vinext emits the artifact because revalidation does not prohibit storage.
Default App or other Pages path ISR and prerender work normally. Behavior does not change.
Maintainer review path
  1. Review packages/vinext/src/server/pages-page-data.ts and pages-data-export-compatibility.ts for cache eligibility and page API compatibility.
  2. Review packages/vinext/src/server/pages-page-handler.ts, pages-page-response.ts, and pages-request-pipeline.ts for policy propagation.
  3. Review packages/vinext/src/server/app-prerender-endpoints.ts and prod-server.ts for static-path export validation before missing or empty path results.
  4. Review packages/vinext/src/build/prerender.ts for default-build, fatal-error, and static-export boundaries.
  5. Review the matching files under tests/ for runtime, development, adapter, endpoint, and prerender regression coverage.
Validation
  • Focused checks passed for all changed source and test files.
  • Focused tests cover Pages data resolution, handling, response finalization, and the request pipeline.
  • Focused tests cover cache policy parsing and the Cloudflare CDN adapter.
  • Targeted integration tests cover Pages Router development fallback behavior.
  • Targeted prerender tests cover default and export modes, no-cache, redirects, custom 404 output, fatal errors, and source-map error text.
  • App/hybrid and Pages-only production endpoint tests cover invalid exports before missing or empty static paths can skip validation.
  • An App prerender regression confirms the lightweight compatibility module does not change bundle behavior.
  • The repository pre-commit checks passed on the final head. These checks include the repository check, staged tests, and Knip.
Commands
vp test run tests/pages-page-data.test.ts tests/pages-page-handler.test.ts tests/pages-page-response.test.ts tests/pages-request-pipeline.test.ts --reporter=dot
vp test run tests/cloudflare-cdn-cache.test.ts tests/pages-page-handler.test.ts --reporter=dot
vp test run tests/cache-control.test.ts -t "distinguishes revalidation from policies that prohibit shared storage" --reporter=dot
vp test run tests/app-prerender-endpoints.test.ts -t "rejects incompatible page exports before empty static paths can skip rendering" --reporter=dot
vp test run tests/prod-server-prerender-endpoints.test.ts --reporter=dot
vp test run tests/prerender.test.ts -t "handles non-cacheable Pages responses safely" --reporter=dot
vp test run tests/prerender.test.ts -t "renders /blog/\\[slug\\] expanded paths" --reporter=dot
Risk / compatibility
  • Public APIs and stored cache formats do not change.
  • Pages with a custom App.getInitialProps can render more often and do not produce reusable build output.
  • Static export fails for that request-aware combination because it cannot generate complete, safe output.
  • The invalid page-level getInitialProps plus getStaticProps combination now fails prerender builds, including dynamic routes with missing or empty static paths.
  • no-cache remains compatible with prerender output; only private and no-store prohibit sharing.
  • Request-independent Pages paths keep their existing ISR and prerender behavior.
Non-goals
  • This PR does not infer whether a custom App.getInitialProps implementation is request-independent.
  • This PR does not change cache behavior for the default App or for pages outside the request-aware combination.
  • This PR does not change public Pages Router APIs or cache storage formats.

Pages that combine getStaticProps with App.getInitialProps can include request cookies or headers in app-level props. Shared ISR entries can then replay those values to later requests.\n\nTreat a custom App.getInitialProps as request-aware. Bypass ISR reads, writes, stale regeneration, fallback persistence, and on-demand persistence for these pages.
@NathanDrake2406

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@pkg-pr-new

pkg-pr-new Bot commented Aug 23, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@vinext/cloudflare@3067
npm i https://pkg.pr.new/create-vinext-app@3067
npm i https://pkg.pr.new/@vinext/types@3067
npm i https://pkg.pr.new/vinext@3067

commit: 254618d

@NathanDrake2406
NathanDrake2406 marked this pull request as ready for review August 23, 2026 13:30
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for security reviews. Please try again later.

@github-actions

github-actions Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Performance benchmarks

Compared 254618d against base 20fdac4 using alternating same-runner rounds. Next.js was unchanged and skipped.

0 improved · 0 regressed · 6 within ±1.5%

Scenario Framework Baseline Current Change
Client bundle size (gzip) vinext 141.4 KB 141.4 KB ⚫ +0.0%
Client entry size (gzip) vinext 128.8 KB 128.8 KB ⚫ +0.0%
Dev server cold start vinext 3.06 s 3.03 s ⚫ -1.1%
Production build time vinext 3.35 s 3.35 s ⚫ +0.1%
RSC entry closure size (gzip) vinext 115.6 KB 115.6 KB ⚫ -0.0%
Server bundle size (gzip) vinext 196.8 KB 197.0 KB ⚫ +0.1%

View detailed results and traces

🟢 improvement · 🔴 regression · ⚫ change below 1.5% · paired base/head

The production integration test still expected an ISR MISS and HIT transition. Custom App.getInitialProps now requires per-request rendering, so assert that both production responses omit the cache-state header.
@NathanDrake2406
NathanDrake2406 marked this pull request as draft August 24, 2026 04:16
@NathanDrake2406

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b0e8fbe31d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/vinext/src/server/pages-page-data.ts Outdated
Comment thread packages/vinext/src/server/pages-page-data.ts Outdated
Comment thread packages/vinext/src/server/pages-page-data.ts Outdated
Only a userland App.getInitialProps override bypasses ISR; the shim's
inherited default keeps shared caching. Request-aware notFound results no
longer carry a cache lifetime, and only-generated revalidation returns the
404 no-op without reading the cache.
@NathanDrake2406

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e3f1456260

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/vinext/src/server/pages-page-data.ts
Comment thread packages/vinext/src/server/pages-page-data.ts
…validation

Request-aware App renders now emit the never-cache policy on HTML and
_next/data responses, and revalidate values are still validated when the
result bypasses the shared cache.
@NathanDrake2406

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c8d6046af9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/vinext/src/server/pages-page-data.ts Outdated
Comment thread packages/vinext/src/server/pages-page-response.ts Outdated
…he headers

Fallback shells inherit the request-aware bypass, and every bypass site
applies the never-cache policy through the CDN adapter so provider-owned
edge headers are removed too.
@NathanDrake2406

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3e7a8d40d4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/vinext/src/server/pages-page-response.ts Outdated
The shared-cache bypass is now checked before the nonce branch, so a
request-aware render always routes its never-cache policy through the CDN
adapter.
@NathanDrake2406

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b414ff90a7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/vinext/src/server/pages-page-data.ts
Comment thread packages/vinext/src/server/pages-page-data.ts Outdated
Comment thread packages/vinext/src/server/pages-page-data.ts
Pages that combine getInitialProps with getStaticProps can mix request data with shared static output. Request-aware fallback and response short-circuit paths can also retain shared cache behavior.

Reject the incompatible page exports, bypass fallback cache reads, and apply the CDN adapter never-cache policy to App response short-circuits. Focused tests cover each regression.
@NathanDrake2406

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 59f6034779

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/vinext/src/server/pages-page-data.ts Outdated
Comment thread packages/vinext/src/server/pages-page-response.ts
Comment thread packages/vinext/src/server/pages-page-data.ts
Development can accept an invalid page getInitialProps and getStaticProps pair that production rejects. Document short-circuits and recursive 404 responses can also retain provider cache headers after request-aware App rendering.

Share the Next.js export validator across dev and production. Carry the source bypass through notFound handling, and apply the CDN adapter never-cache policy before every affected response exits.
@NathanDrake2406

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ba194afacb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/vinext/src/server/pages-page-data.ts
Comment thread packages/vinext/src/server/dev-server.ts Outdated
Comment thread packages/vinext/src/server/pages-page-response.ts
Reject invalid data exports before dev fallback rendering, carry request-aware cache bypass through early not-found results, and keep rendered no-store policy authoritative after staged headers merge.
@NathanDrake2406

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 14d6c4698a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/vinext/src/server/pages-request-pipeline.ts Outdated
Use a canonical non-cacheable policy after the final header merge whenever the active CDN adapter detects an explicit storage opt-out, including provider-only no-store headers.
@NathanDrake2406

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: adba844c51

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/vinext/src/server/pages-request-pipeline.ts Outdated
Comment thread packages/vinext/src/server/dev-server.ts Outdated
Keep rendered private browser cache policies while clearing conflicting CDN metadata, and validate incompatible Pages data exports before every development static-path exit.
@NathanDrake2406

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: abb5ad7376

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/vinext/src/server/pages-request-pipeline.ts
Comment thread packages/vinext/src/server/pages-page-data.ts
Comment thread packages/vinext/src/server/pages-page-handler.ts
Skip non-cacheable Pages prerender artifacts, preserve adapter no-store semantics for case-insensitive directives, and carry request-aware cache bypass through recursive 500 rendering.
@NathanDrake2406

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3f8cc1f667

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/vinext/src/build/prerender.ts Outdated
@NathanDrake2406

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0e63b3dd7f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/vinext/src/server/pages-page-data.ts Outdated
@NathanDrake2406

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5e059d1653

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/vinext/src/build/prerender.ts Outdated
Comment thread packages/vinext/src/server/pages-page-data.ts
@NathanDrake2406

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 20772e7b3f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/vinext/src/server/prod-server.ts
@NathanDrake2406

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. You're on a roll.

Reviewed commit: 254618da33

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@NathanDrake2406
NathanDrake2406 marked this pull request as ready for review August 24, 2026 10:42
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for security reviews. Please try again later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant