Skip to content

refactor(isr): centralise HIT/STALE/MISS + Cache-Control decision in isr-decision.ts#1883

Open
Divkix wants to merge 2 commits into
cloudflare:mainfrom
Divkix:refactor/isr-decision-module
Open

refactor(isr): centralise HIT/STALE/MISS + Cache-Control decision in isr-decision.ts#1883
Divkix wants to merge 2 commits into
cloudflare:mainfrom
Divkix:refactor/isr-decision-module

Conversation

@Divkix

@Divkix Divkix commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Closes #1783

What

Adds server/isr-decision.ts as the single owner of the ISR cache policy decision. All four call sites that previously re-derived HIT/STALE/MISS disposition, background-regen scheduling, and Cache-Control string selection now delegate to decideIsr() or its MISS helpers.

Also eliminates all hardcoded Cache-Control literals outside cache-control.ts — raw strings like "private, no-cache, no-store, max-age=0, must-revalidate" that were copy-pasted across dev-server.ts, pages-page-response.ts, and pages-page-handler.ts.

Call sites migrated

  • server/app-page-cache.ts — removed local buildAppPageCacheControl wrapper
  • server/app-route-handler-response.ts — removed local buildRouteHandlerCacheControl; cached responses use decideIsr(kind:"app-route"), fresh MISS responses use buildAppRouteMissIsrCacheControl (preserves the revalidate=0→NEVER and Infinity→STATIC gates)
  • server/pages-page-data.tsbuildPagesCacheResponse delegates to decideIsr(kind:"pages")
  • server/dev-server.ts — all four inline literals replaced

Deliberate behaviour change

Dev STALE responses now emit s-maxage=0, stale-while-revalidate (matching prod Pages Router and the canonical buildCachedRevalidateCacheControl helper) instead of s-maxage=<revalidate>, stale-while-revalidate. The old value incorrectly told downstream caches that a stale-served payload was freshly cacheable — a dev/prod parity gap that was masked by the duplication.

Equivalence

Every other migrated path emits the same header as before. The full per-call-site equivalence table is in the isr-decision.ts module doc comment.

Tests

  • tests/isr-decision.test.ts — 33 new unit tests covering all dispositions, router kinds, 0/Infinity special cases, metadata fallback semantics, and the MISS helpers
  • All existing cache-related tests pass unchanged: app-page-cache, app-route-handler-cache, app-route-handler-response, pages-page-data, isr-cache, cache-control, features

…isr-decision.ts

Add server/isr-decision.ts as the single owner of the ISR cache policy
decision across all four call sites (app-page-cache, app-route-handler,
pages-page-data, dev-server). Every cache disposition, background-regen
flag, and Cache-Control string now flows through decideIsr() or its MISS
helpers.

Also eliminate all hardcoded Cache-Control literals outside cache-control.ts
(NEVER_CACHE_CONTROL, NO_STORE_CACHE_CONTROL, and raw s-maxage strings
in dev-server.ts, pages-page-response.ts, pages-page-handler.ts).

One deliberate behaviour change: dev STALE responses now emit
s-maxage=0, stale-while-revalidate (matching prod Pages Router) instead
of s-maxage=<revalidate>, stale-while-revalidate. This closes a dev/prod
parity gap that was masked by the duplication.

Closes cloudflare#1783
@pkg-pr-new

pkg-pr-new Bot commented Jun 9, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@vinext/cloudflare@1883
npm i https://pkg.pr.new/vinext@1883

commit: 26c2a23

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.

Add a single ISR cache-decision module above the handler seam

1 participant