Skip to content

feat(cloudflare): key Response Store App pages by the query-free cache identity - #3463

Draft
james-elicx wants to merge 3 commits into
isr-query/12-cache-identityfrom
isr-query/13-response-store-identity
Draft

james-elicx wants to merge 3 commits into
isr-query/12-cache-identityfrom
isr-query/13-response-store-identity

Conversation

@james-elicx

Copy link
Copy Markdown
Member

Stacked on #3462. Plan PR 5 (Response Store adapter).

Change

  • Opt-in: ResponseStoreCdnCacheAdapter declares responseStageCacheIdentity = "query-free".

  • Where the identity is used: response-store-adapter.worker.ts uses cacheIdentity, falling back to the full request and props, for:

    • the lookup key;
    • put;
    • the route revalidator arguments;
    • the warmup RSC seed.

    The render itself still gets the real request. Every query of a static App page now shares one stored entry. A regeneration replays the query-free identity, so it never bakes one visitor's query into the shared entry.

  • Per-request headers: X-Vinext-Params and X-Vinext-Rendered-Path-And-Search are removed before every put and from regenerated responses. The request stage rebuilds them for each App RSC response, HITs included.

  • Unchanged: vinext:data revalidator entries keep the full invocation. Replaying a query-dependent fetch without its query would compute a different fetch key, so the entry could never be refreshed.

Tests

  • tests/cloudflare-response-store-worker.test.ts:

    • two queries share one entry, with one render and then a HIT;
    • route replay arguments use the identity, while data replay arguments keep the full request;
    • the headers are removed before put and after regeneration;
    • a warmup seeds the RSC entry under the identity;
    • without an identity, keys fall back to the full request.
  • packages/cloudflare/tests/response-store-adapter.e2e.test.ts (examples/response-store-demo):

    • /cached/query-identity requested with two different queries gives a MISS, then a HIT with the same render, for both HTML and RSC;
    • RSC responses carry the right per-request x-vinext-params and x-vinext-rendered-path-and-search;
    • exactly two route entries are stored, with no query in them.

    Two existing cases used queries to force separate entries and now use distinct paths. 29/29 pass.

@james-elicx

Copy link
Copy Markdown
Member Author

/bigbonk review for issues

Please review exact head aca5982930484e4df7bf5ca54f31c38df8d5964d without modifying or pushing the branch. Report all actionable findings within your 8-minute time limit.

@pkg-pr-new

pkg-pr-new Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

@vinext/cloudflare

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

create-vinext-app

npm i https://pkg.pr.new/create-vinext-app@3463

@vinext/types

npm i https://pkg.pr.new/@vinext/types@3463

vinext

npm i https://pkg.pr.new/vinext@3463

@cloudflare/workers-response-store

npm i https://pkg.pr.new/@cloudflare/workers-response-store@3463

commit: caa35be

@github-actions

github-actions Bot commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Performance benchmarks

Compared caa35be against base 2b12885 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 143.4 KB 143.4 KB ⚫ -0.0%
Client entry size (gzip) vinext 131.5 KB 131.5 KB ⚫ +0.0%
Dev server cold start vinext 3.39 s 3.35 s ⚫ -1.2%
Production build time vinext 3.92 s 3.90 s ⚫ -0.3%
RSC entry closure size (gzip) vinext 131.0 KB 131.0 KB ⚫ -0.0%
Server bundle size (gzip) vinext 232.7 KB 232.7 KB ⚫ -0.0%

View detailed results and traces

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

@ask-bonk

ask-bonk Bot commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

LGTM!

github run

@james-elicx
james-elicx force-pushed the isr-query/13-response-store-identity branch from aca5982 to e153f06 Compare September 25, 2026 03:28
@james-elicx

Copy link
Copy Markdown
Member Author

/bigbonk review for issues

Please review exact head e153f06b6cd067b786094098316913ab57b2ead8 without modifying or pushing the branch. Report all actionable findings within your 8-minute time limit.

@ask-bonk

ask-bonk Bot commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

LGTM!

github run

@github-actions

github-actions Bot commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor
Example Preview Production Original
app-router-cloudflare preview production
pages-router-cloudflare preview production
app-router-playground preview production original
realworld-api-rest preview production
nextra-docs-template preview production
benchmarks preview production
hackernews preview production original
response-store-demo preview production
workers-cache preview production
kv preview production
static-assets-cache preview production
static-export preview production
web preview production

@james-elicx
james-elicx force-pushed the isr-query/13-response-store-identity branch from e153f06 to 3a24111 Compare September 25, 2026 04:12
@james-elicx

Copy link
Copy Markdown
Member Author

/bigbonk review for issues

Please review exact head 3a241112dad3da9e74aa0369154cb935bc6b51d3 without modifying or pushing the branch. Report all actionable findings within your 8-minute time limit.

@ask-bonk

ask-bonk Bot commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

LGTM!

github run

@james-elicx

Copy link
Copy Markdown
Member Author

/bigbonk review for issues

Please review exact head f7b06544f631c782072ca53521a073ee730bf3cd without modifying or pushing the branch. Report all actionable findings within your 8-minute time limit.

@ask-bonk

ask-bonk Bot commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

LGTM!

github run

@james-elicx
james-elicx force-pushed the isr-query/13-response-store-identity branch from f7b0654 to b69ad69 Compare September 25, 2026 05:16
@james-elicx

Copy link
Copy Markdown
Member Author

/bigbonk review for issues

Please review exact head b69ad69f52f238d10b7986fe9a2b739e4fd660bf without modifying or pushing the branch. Report all actionable findings within your 8-minute time limit.

@ask-bonk

ask-bonk Bot commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

LGTM!

github run

@james-elicx
james-elicx force-pushed the isr-query/13-response-store-identity branch from b69ad69 to 2946380 Compare September 25, 2026 06:05
@james-elicx

Copy link
Copy Markdown
Member Author

/bigbonk review for issues

Please review exact head 2946380aefaceb7267d383c20a2df9939b8698bb without modifying or pushing the branch. Report all actionable findings within your 8-minute time limit.

return;
}
await responseStore.put(key, admitted, {
await responseStore.put(key, withoutRequestScopedHeaders(admitted), {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Restrict this stripping to App-page RSC entries (or otherwise prove the request stage will restore these headers). This branch also handles cacheable App route handlers, metadata routes, and hybrid Pages responses, but app-rsc-handler.ts only recomposes these headers for kind === "app-page" && isRscRequest. A route handler that returns either header therefore exposes it on the MISS and silently loses it on the HIT/regenerated response. The unconditional calls at lines 231 and 509 have the same issue.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed in 6f58508: the params/rendered-search headers are only stripped for App page RSC entries, in all three places, which is the only case the request stage recomposes. Route handlers, metadata routes and Pages responses keep their headers. Tests cover a route handler's headers across MISS→HIT and regeneration.

@ask-bonk

ask-bonk Bot commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

Posted 1 actionable inline finding. Targeted unit tests pass.

github run

@james-elicx
james-elicx force-pushed the isr-query/13-response-store-identity branch from 2946380 to 6f58508 Compare September 25, 2026 06:41
@james-elicx

Copy link
Copy Markdown
Member Author

/bigbonk review for issues

Please review exact head 6f5850871ca87790ea5edc6ecf680c489954dfe3 without modifying or pushing the branch. Report all actionable findings within your 8-minute time limit.

@james-elicx

Copy link
Copy Markdown
Member Author

/bigbonk review for issues

Please review exact head c8e4e6bd92f9d4030d3201d05fe340084298a75d without modifying or pushing the branch. Report all actionable findings within your 8-minute time limit.

@ask-bonk

ask-bonk Bot commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

LGTM!

github run

@james-elicx
james-elicx force-pushed the isr-query/13-response-store-identity branch from c8e4e6b to c5ce774 Compare September 25, 2026 15:31
@james-elicx
james-elicx force-pushed the isr-query/13-response-store-identity branch from c5ce774 to 25738a0 Compare September 25, 2026 18:07
@james-elicx
james-elicx removed this pull request from stack #3471 September 25, 2026 18:50
@james-elicx
james-elicx force-pushed the isr-query/13-response-store-identity branch from 25738a0 to 00b41f3 Compare September 25, 2026 18:51
@james-elicx
james-elicx added this pull request to stack #3474 September 25, 2026 18:51
@james-elicx
james-elicx force-pushed the isr-query/13-response-store-identity branch from 00b41f3 to 75a60db Compare September 25, 2026 19:18
@james-elicx
james-elicx force-pushed the isr-query/13-response-store-identity branch 2 times, most recently from 869eff2 to 3a3e801 Compare September 25, 2026 20:46
@james-elicx
james-elicx removed this pull request from stack #3474 September 25, 2026 21:30
@james-elicx
james-elicx force-pushed the isr-query/13-response-store-identity branch from 3a3e801 to c3d6371 Compare September 25, 2026 21:31
@james-elicx
james-elicx added this pull request to stack #3481 September 25, 2026 21:32
@james-elicx
james-elicx force-pushed the isr-query/13-response-store-identity branch from c3d6371 to 2b7f58e Compare September 25, 2026 21:56
@james-elicx
james-elicx removed this pull request from stack #3481 September 25, 2026 22:13
@james-elicx
james-elicx added this pull request to stack #3482 September 25, 2026 22:14
…e identity

The Response Store adapter declares responseStageCacheIdentity and uses
options.cacheIdentity for its lookup key, stored entry, route revalidator
replay and warmup RSC seed, so App pages that admission stores share one
entry across queries. The render still receives the real request, and
data-cache replays keep the full invocation that produced them.
X-Vinext-Params and X-Vinext-Rendered-Path-And-Search are dropped before
storing and after regeneration; the request stage recomposes them.
…entries

The request stage recomposes X-Vinext-Params and
X-Vinext-Rendered-Path-And-Search only for App page RSC responses, so the
Response Store adapter now drops them only when the response-stage props
say kind app-page with isRscRequest. Route handlers, metadata routes,
App page HTML and hybrid Pages entries keep the headers they rendered on
the stored, admitted and regenerated paths, so a HIT matches the MISS.
…eries in the Response Store

Request the static /search-params/suspense page with two fresh queries and
require the second to HIT with the same render ID, so the test proves one
stored document serves every query rather than only the exact URL.
@james-elicx
james-elicx force-pushed the isr-query/13-response-store-identity branch from 2b7f58e to caa35be Compare September 27, 2026 23:55
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