Skip to content

perf(server): skip duplicate App RSC vary merge#2177

Merged
james-elicx merged 1 commit into
cloudflare:mainfrom
NathanDrake2406:nathan/optimize-app-rsc-vary-finalizer
Jun 20, 2026
Merged

perf(server): skip duplicate App RSC vary merge#2177
james-elicx merged 1 commit into
cloudflare:mainfrom
NathanDrake2406:nathan/optimize-app-rsc-vary-finalizer

Conversation

@NathanDrake2406

Copy link
Copy Markdown
Contributor

Overview

This PR avoids running the generic Vary merge path when App Router response finalization sees the internal RSC Vary header is already present, or when the header is missing and can be set directly.

Area Change Impact
App Router SSR Fast-path App RSC Vary finalization Removes repeated split, trim, dedupe work from the common page response path
Custom Vary responses Keep using mergeVaryHeader Preserves existing wildcard and dedupe semantics

Why

App page helpers already stamp VINEXT_RSC_VARY_HEADER before finalizeAppRscResponse() runs. The finalizer was still calling the generic merge helper, which reparsed and deduped the same known header value on every non-static App Router response.

Validation

  • vp check tests/app-rsc-response-finalizer.test.ts packages/vinext/src/server/app-rsc-response-finalizer.ts
  • vp test run tests/app-rsc-response-finalizer.test.ts
  • vp run vinext#build

Perf note

Local 20k warmed SSR profile against the benchmark app showed mergeVaryHeader self-time on this path drop from 70.33ms to 0ms, with finalizeAppRscResponse self-time dropping from 12.29ms to 5.37ms.

Non-goals

This does not change the broader mergeVaryHeader helper or optimize route tree construction. Those are separate hot paths.

App Router page responses commonly already carry the internal RSC Vary header before response finalization runs. Re-running the generic Vary merge in that case splits and deduplicates the known header value on every SSR response without changing the result.

Read the current Vary value first, set the internal header directly when missing, and only fall back to the generic merge path for custom Vary values that still need preservation and deduplication.
@NathanDrake2406 NathanDrake2406 marked this pull request as ready for review June 19, 2026 13:32
@pkg-pr-new

pkg-pr-new Bot commented Jun 19, 2026

Copy link
Copy Markdown

Open in StackBlitz

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

commit: f2600d9

@github-actions

Copy link
Copy Markdown
Contributor

Performance benchmarks

Compared f2600d9 against base 388b5c3 using alternating same-runner rounds. Next.js was unchanged and skipped.

1 improved · 0 regressed · 4 within ±1.5%

Scenario Framework Baseline Current Change
Client bundle size (gzip) vinext 129.9 KB 129.9 KB ⚫ 0.0%
Dev server cold start vinext 2.50 s 2.48 s ⚫ -0.9%
Production build time vinext 2.80 s 2.75 s 🟢 -1.6%
RSC entry size (gzip) vinext 64.1 KB 64.1 KB ⚫ +0.0%
Server bundle size (gzip) vinext 181.7 KB 181.8 KB ⚫ +0.0%

View detailed results and traces

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

@james-elicx james-elicx merged commit 46b8fe8 into cloudflare:main Jun 20, 2026
92 checks passed
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.

2 participants