Skip to content

test(cache): add App Router Response Store load harness - #3299

Draft
james-elicx wants to merge 3 commits into
mainfrom
codex/response-store-load-test
Draft

james-elicx wants to merge 3 commits into
mainfrom
codex/response-store-load-test

Conversation

@james-elicx

@james-elicx james-elicx commented Sep 15, 2026

Copy link
Copy Markdown
Member

Scenario

This adds an isolated vinext App Router load-test app for the production Workers Response Store path. It intentionally uses unique route IDs so each lifecycle starts from a cold key rather than measuring an already-warm Workers Cache hit.

Cacheable lifecycle

  • Requests /cacheable/:id, an App Router page forced to render at runtime.
  • next.config.mjs applies Cache-Control: public, s-maxage=15, stale-while-revalidate=15 only to this route.
  • Verifies MISS on the first request, then the same render token on a stored HIT.
  • Waits for freshness to expire, verifies stale UPDATING with the old token, then polls until a recovered HIT has a new token.
  • This exercises cold metadata/body admission, Workers Cache population, SWR claim/regeneration, publication, and return to a hit.

Dynamic lifecycle

  • Requests /dynamic/:id twice at the same URL.
  • The page remains force-dynamic with no public cache-policy override.
  • Verifies both responses are no-store, neither reports HIT/UPDATING, and each render has a different token.
  • This exercises repeated Response Store misses that must never be admitted.

Load shape and output

  • Defaults to 5,000 cacheable and 5,000 dynamic lifecycles.
  • Uses a closed-loop concurrency ladder of 50, 100, 200, 400, and 800; this is not a fixed-arrival-rate RPS benchmark.
  • Stops a scenario after its cumulative lifecycle failure rate exceeds 1%.
  • Emits ignored, chart-ready JSON with per-second RPS, p50/p95/p99/max latency, statuses, cache states, errors, lifecycle totals, and admission/SWR transition timings.
  • Enables logs, invocation logs, traces, and 1% head sampling on both the app and cache Workers.
  • Keeps the manually provisioned Workers, Durable Object namespace, and R2 bucket after runs.

The in-directory README documents prerequisites, one-time bucket creation, build/deploy ordering, smoke and high-load commands, every runner option, JSON fields, and CSV export for charting.

Observed App Router experiment

  • Cacheable lifecycles were clean through concurrency 200.
  • At concurrency 400, 107 of 1,333 cacheable lifecycles failed (8.03%).
  • A dedicated concurrency-800 cacheable run failed 871 of 1,000 lifecycles (87.1%).
  • Dynamic lifecycles reached concurrency 800 with 37 of 1,668 failures at that level (2.22%).
  • Failures included Durable Object is overloaded. Requests queued for too long.
  • The dashboard showed a 249.42 Durable Object invocations/s minute-average peak. This is experiment context, not a precise single-instance capacity limit.

The generated experiment JSON and graph artifacts are not committed.

Validation

  • node --check examples/response-store-demo/load-test/load.mjs
  • App Router production build completed through all five vinext build stages.
  • Live smoke: 1 cacheable and 1 dynamic lifecycle passed, 9 requests total, zero failures.
  • git diff --check

@pkg-pr-new

pkg-pr-new Bot commented Sep 15, 2026

Copy link
Copy Markdown

Open in StackBlitz

@vinext/cloudflare

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

create-vinext-app

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

@vinext/types

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

vinext

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

@cloudflare/workers-response-store

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

commit: 2ded4f2

@james-elicx
james-elicx marked this pull request as draft September 15, 2026 17:24
@github-actions

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
static-export preview production
web preview production

@github-actions

github-actions Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Performance benchmarks

Compared 2ded4f2 against base 3aa24cf 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 142.2 KB 142.2 KB ⚫ +0.0%
Client entry size (gzip) vinext 129.6 KB 129.6 KB ⚫ +0.0%
Dev server cold start vinext 3.35 s 3.32 s ⚫ -0.8%
Production build time vinext 3.86 s 3.85 s ⚫ -0.2%
RSC entry closure size (gzip) vinext 121.0 KB 121.0 KB ⚫ +0.0%
Server bundle size (gzip) vinext 211.0 KB 211.0 KB ⚫ +0.0%

View detailed results and traces

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

@james-elicx

Copy link
Copy Markdown
Member Author

Closing because this load experiment was not requested as a pull request. The harness and result work will continue locally.

@james-elicx james-elicx reopened this Sep 15, 2026
@james-elicx james-elicx changed the title test(cache): add Response Store load harness test(cache): add App Router Response Store load harness Sep 15, 2026
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