Instrument workflow replay scaling#2969
Conversation
🦋 Changeset detectedLatest commit: 21397aa The changes in this PR will be included in the next version bump. This PR includes changesets to release 16 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
🧪 E2E Test Results✅ All tests passed Summary
Details by Category✅ ▲ Vercel Production
✅ 💻 Local Development
✅ 📦 Local Production
✅ 🐘 Local Postgres
✅ 🪟 Windows
✅ 📋 Other
✅ vercel-multi-region
|
📊 Workflow Benchmarks⏳ Benchmarks are running for
commit Backend:
📜 Previous results (3)0ed0294Fri, 17 Jul 2026 01:44:11 GMT · run logs
b0ded7fFri, 17 Jul 2026 00:47:52 GMT · run logs
5f7515aFri, 17 Jul 2026 00:18:52 GMT · run logs
Avg deltas compare against the most recent benchmark run on Metrics — TTFS: time to first step body execution · STSO: step-to-step overhead (gap between consecutive step bodies) · WO: workflow overhead (time outside step bodies, client start → last step body exit) · SL: stream latency (first chunk write → visible to the reader) Scenarios — stream: one step that streams chunks back to the client; no hooks, so the run stays in turbo mode · hook + stream: registers a hook before the same streaming step, which exits turbo mode · 1020 steps: 1020 trivial sequential steps; STSO is measured between consecutive steps in the given step ranges 🟢/🔴 mark percentiles within/above target. Targets (p75/p90/p99, ms) — TTFS 200/300/600 · SL 50/60/125 · STSO (1-20) 20/30/60 · STSO (101-120) 30/45/90 · STSO (1001-1020) 40/60/120 TTFS/WO compare client vs deployment clocks and SL compares the step runner’s clock vs the client’s (NTP-synced in CI). WO ends at the last step body exit, the closest observable proxy for the final step-completion request. |
|
The benchmark triggered by the final preview-config restore commit was intentionally canceled because it would no longer run with the debug-off/non-turbo experimental controls. The latest valid diagnostic result is commit |
Summary
workflow.runinto VM context, bundle evaluation, argument hydration, execution, serialization, and drain spansProduction finding
The production VM itself is not intrinsically hundreds of milliseconds slower than local replay. The original comparison mixed a tiny synthetic local bundle with a 1.322 MB production bundle, encrypted object results, OpenTelemetry, and
DEBUG=workflow:*.Disabling debug logging on the same preview reduced late
workflow.runfrom 604.6 ms to 247.6 ms. The synchronous event-consumer scan fell from 165.3 ms to 11.9 ms because each enabled per-event debug call emitted console output and an active-span event.The final instrumented, debug-off, non-turbo run was CI 29548488910, workflow run
wrun_41KXPWKTB70GJFGJB4Q00XBH2W.step_completeddurable writeworkflow.runstep_starteddurable writeThe refresh cliff is the event pagination issue being handled separately in workflow-server PR #632. It is not the continuous replay slope.
Replay breakdown
The subscription-wait metric is 18.8 / 39.3 / 160.8 ms, but it overlaps hydration and VM continuation and must not be added to the rows above.
Every benchmark result is an object, so all 10 / 110 / 1010 historical step values are non-memoizable by the primitive-only hydration cache. Each replay serially performs one WebCrypto AES-GCM decrypt and one fresh deserialize per historical result. Across 1020 serial steps that is approximately
sum(1..1020) = 520,710decrypt/parse operations in one invocation.The exact local reproduction used the generated 1.322 MB bundle, encrypted object results, Node 22 Linux, and a 1-vCPU/2-GB container. At K1020 it measured 183.7 ms total
workflow.run, including 50.6 ms bundle evaluation, 124.5 ms execution, 86.0 ms hydration, and 9.1 ms synchronous event scan. The preview measured 242.0 / 51.5 / 187.2 / 144.7 / 11.5 ms respectively. The remaining local-cloud gap is therefore hydration/WebCrypto throughput and scheduling, notnode:vmcontext or bundle evaluation.Evidence
d6ec13404e2537410dac512a521da423andfec6da2c5114eb50e1eb9a9c31a239020d3358d44cc286fec90623114cce3d92and80879ec66b238c5727fb3f981d164ea3Verification
pnpm --filter @workflow/core typecheckpnpm --filter @workflow/core build