Skip to content

[e2e] Separate event-log-race-repro harness noise from real regressions#2190

Merged
VaguelySerious merged 1 commit into
mainfrom
peter/event-log-race-repro-classify-infra
Jun 1, 2026
Merged

[e2e] Separate event-log-race-repro harness noise from real regressions#2190
VaguelySerious merged 1 commit into
mainfrom
peter/event-log-race-repro-classify-infra

Conversation

@VaguelySerious
Copy link
Copy Markdown
Member

Summary

The event-log-race-repro job is currently red for the wrong reason. In a recent run, it reported 1231 of 2000 runs "did not complete cleanly" — yet CORRUPTED_EVENT_LOG / USER_ERROR / RUNTIME_ERROR were all 0. The entire count was harness-side noise.

What the other column was

The repro sorts each run into completed, CORRUPTED_EVENT_LOG, USER_ERROR, RUNTIME_ERROR, stuck, or other. Only the three named error codes mapped to their own bucket; everything else fell into other, and the --check gate failed the job on any non-completed run. So other conflated genuine corruption with:

  • HOOK_RESUME_FAILED — the run completed fine, but the harness's own resumeHook() rejected (typically because the sleep branch already finished the run and disposed the hook).
  • NO_WAKE_BRANCH — the run completed but the sleep branch won every iteration, so the wake path was never taken.
  • transport errors / timeouts thrown in the driver, and cancellations.

What was actually going wrong

A timing race in the test harness, not an SDK bug. The workflow's sleep budget is iterations × sleepMs = 5 × 5000 = 25000ms; the harness resumes the hook at resumeDelayMs + rand(resumeJitterMs) = up to 25000ms — the resume ceiling exactly equals the budget. On a fast/warm deployment the workflow exhausts its sleeps before the resume lands, so the resume hits a disposed hook and/or the wake branch is never taken.

The smoking gun: the #2 retry against the same already-warm deployment jumped 767→1231 other while stuck dropped to 0 and the step scenarios stayed perfect. Faster execution = the resume misses the window more often. It also means most "green" runs weren't even exercising the wake-branch shape the repro is meant to stress.

Changes

  1. Reclassify harness-side, non-corruption outcomes into a dedicated non-gating infra bucket (test + renderer). The job now gates only on regression-class outcomes (CORRUPTED_EVENT_LOG / USER_ERROR / RUNTIME_ERROR / stuck / other); infra is reported but never fails the job. The PR comment now reads "No event-log regressions… N runs hit harness-side infra outcomes (… do not fail the job)."
  2. Surface regressions ahead of infra in the failures table so the 20-row cap never hides a real failure behind a flood of timing rows.
  3. Restore wake-branch coverage: raise the default iterations ceiling (5 → 8). Because the run short-circuits via returnOnWake the moment the hook wins, a higher ceiling widens the window for the resume to land before sleep-budget exhaustion at ~no runtime cost. Added a beforeAll guard that warns when the resume ceiling is not below the sleep budget.
  4. Testability: the renderer's pure helpers are now exported and covered by node:test (run via a new lightweight Lint job).

Tests

node --test .github/scripts/**/*.test.js (8 tests) covers: infra is non-gating; regressionCount ignores completed/infra; an all-infra results file (mirroring the production comment) yields 0 regressions; regressions sort ahead of infra; --check exits 0 on infra-only and 1 on a corruption-class outcome.

Note: the full 2000-run repro only runs against a deployment behind the event-log-race-repro label, so the reclassification's end-to-end effect is best confirmed by adding that label to this PR.

🤖 Generated with Claude Code

The event-log-race-repro job classified every non-completed run into an
`other` grab-bag and gated on it. Hook-resume timing races (HOOK_RESUME_FAILED,
NO_WAKE_BRANCH) and transport errors in the repro driver — none of which are
event-log corruption — landed there and failed the job, drowning the signal it
exists to detect.

- Route harness-side, non-corruption outcomes to a dedicated non-gating `infra`
  bucket (test + renderer). The job now gates only on regression-class outcomes
  (CORRUPTED_EVENT_LOG / USER_ERROR / RUNTIME_ERROR / stuck / other).
- Sort regressions ahead of infra rows so the 20-row cap never hides a real
  failure behind a flood of harness-timing rows.
- Raise the default hook/sleep iteration ceiling (5 -> 8). Because the run
  short-circuits via returnOnWake the moment the hook wins, this widens the
  window for the delayed resume to land before the sleep budget is exhausted,
  at ~no runtime cost — restoring the wake-branch coverage the scenario exists
  to exercise. Add a beforeAll guard that warns when the resume ceiling is not
  below the sleep budget.
- Make the renderer's pure helpers unit-testable and add node:test coverage,
  wired into the Lint workflow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 31, 2026

🦋 Changeset detected

Latest commit: e100a60

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 0 packages

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

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

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 31, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
example-nextjs-workflow-turbopack Ready Ready Preview, Comment May 31, 2026 1:35pm
example-nextjs-workflow-webpack Ready Ready Preview, Comment May 31, 2026 1:35pm
example-workflow Ready Ready Preview, Comment May 31, 2026 1:35pm
workbench-astro-workflow Ready Ready Preview, Comment May 31, 2026 1:35pm
workbench-express-workflow Ready Ready Preview, Comment May 31, 2026 1:35pm
workbench-fastify-workflow Ready Ready Preview, Comment May 31, 2026 1:35pm
workbench-hono-workflow Ready Ready Preview, Comment May 31, 2026 1:35pm
workbench-nitro-workflow Ready Ready Preview, Comment May 31, 2026 1:35pm
workbench-nuxt-workflow Ready Ready Preview, Comment May 31, 2026 1:35pm
workbench-sveltekit-workflow Ready Ready Preview, Comment May 31, 2026 1:35pm
workbench-tanstack-start-workflow Ready Ready Preview, Comment May 31, 2026 1:35pm
workbench-vite-workflow Ready Ready Preview, Comment May 31, 2026 1:35pm
workflow-docs Ready Ready Preview, Comment, Open in v0 May 31, 2026 1:35pm
workflow-swc-playground Ready Ready Preview, Comment May 31, 2026 1:35pm
workflow-tarballs Ready Ready Preview, Comment May 31, 2026 1:35pm
workflow-web Ready Ready Preview, Comment May 31, 2026 1:35pm

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 31, 2026

🧪 E2E Test Results

Some tests failed

Summary

Passed Failed Skipped Total
❌ ▲ Vercel Production 1263 3 219 1485
❌ 💻 Local Development 1670 1 219 1890
✅ 📦 Local Production 1671 0 219 1890
✅ 🐘 Local Postgres 1671 0 219 1890
✅ 🪟 Windows 135 0 0 135
❌ 📋 Other 768 1 176 945
Total 7178 5 1052 8235

❌ Failed Tests

▲ Vercel Production (3 failed)

express (1 failed):

  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_01KSZ4H8N0DE044HA3WQ2AG25H | 🔍 observability

nextjs-webpack (2 failed):

  • AbortController abortHookOrderingWorkflow [listener-first-abort-first]: addEventListener → hook.then → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [listener-first-hook-first]: addEventListener → hook.then → resumeHook → abort()
💻 Local Development (1 failed)

express-stable (1 failed):

  • hookWithSleepFinalStepWorkflow - step only on final payload | wrun_01KSZ4NB8SC1XKHH9GSXQEKXZR
📋 Other (1 failed)

e2e-vercel-prod-tanstack-start (1 failed):

  • AbortController abortHookOrderingWorkflow [listener-first-abort-first]: addEventListener → hook.then → abort() → resumeHook

Details by Category

❌ ▲ Vercel Production
App Passed Failed Skipped
✅ astro 109 0 26
✅ example 109 0 26
❌ express 108 1 26
✅ fastify 109 0 26
✅ hono 109 0 26
✅ nextjs-turbopack 133 0 2
❌ nextjs-webpack 131 2 2
✅ nitro 109 0 26
✅ nuxt 109 0 26
✅ sveltekit 128 0 7
✅ vite 109 0 26
❌ 💻 Local Development
App Passed Failed Skipped
✅ astro-stable 110 0 25
❌ express-stable 109 1 25
✅ fastify-stable 110 0 25
✅ hono-stable 110 0 25
✅ nextjs-turbopack-canary 116 0 19
✅ nextjs-turbopack-stable-lazy-discovery-disabled 135 0 0
✅ nextjs-turbopack-stable-lazy-discovery-enabled 135 0 0
✅ nextjs-webpack-canary 116 0 19
✅ nextjs-webpack-stable-lazy-discovery-disabled 135 0 0
✅ nextjs-webpack-stable-lazy-discovery-enabled 135 0 0
✅ nitro-stable 110 0 25
✅ nuxt-stable 110 0 25
✅ sveltekit-stable 129 0 6
✅ vite-stable 110 0 25
✅ 📦 Local Production
App Passed Failed Skipped
✅ astro-stable 110 0 25
✅ express-stable 110 0 25
✅ fastify-stable 110 0 25
✅ hono-stable 110 0 25
✅ nextjs-turbopack-canary 116 0 19
✅ nextjs-turbopack-stable-lazy-discovery-disabled 135 0 0
✅ nextjs-turbopack-stable-lazy-discovery-enabled 135 0 0
✅ nextjs-webpack-canary 116 0 19
✅ nextjs-webpack-stable-lazy-discovery-disabled 135 0 0
✅ nextjs-webpack-stable-lazy-discovery-enabled 135 0 0
✅ nitro-stable 110 0 25
✅ nuxt-stable 110 0 25
✅ sveltekit-stable 129 0 6
✅ vite-stable 110 0 25
✅ 🐘 Local Postgres
App Passed Failed Skipped
✅ astro-stable 110 0 25
✅ express-stable 110 0 25
✅ fastify-stable 110 0 25
✅ hono-stable 110 0 25
✅ nextjs-turbopack-canary 116 0 19
✅ nextjs-turbopack-stable-lazy-discovery-disabled 135 0 0
✅ nextjs-turbopack-stable-lazy-discovery-enabled 135 0 0
✅ nextjs-webpack-canary 116 0 19
✅ nextjs-webpack-stable-lazy-discovery-disabled 135 0 0
✅ nextjs-webpack-stable-lazy-discovery-enabled 135 0 0
✅ nitro-stable 110 0 25
✅ nuxt-stable 110 0 25
✅ sveltekit-stable 129 0 6
✅ vite-stable 110 0 25
✅ 🪟 Windows
App Passed Failed Skipped
✅ nextjs-turbopack 135 0 0
❌ 📋 Other
App Passed Failed Skipped
✅ e2e-local-dev-nest-stable 110 0 25
✅ e2e-local-dev-tanstack-start- 110 0 25
✅ e2e-local-postgres-nest-stable 110 0 25
✅ e2e-local-postgres-tanstack-start- 110 0 25
✅ e2e-local-prod-nest-stable 110 0 25
✅ e2e-local-prod-tanstack-start- 110 0 25
❌ e2e-vercel-prod-tanstack-start 108 1 26

📋 View full workflow run


Some E2E test jobs failed:

  • Vercel Prod: failure
  • Local Dev: failure
  • Local Prod: success
  • Local Postgres: success
  • Windows: success

Check the workflow run for details.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 31, 2026

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Express 0.042s (-5.9% 🟢) 1.006s (~) 0.964s 10 1.00x
💻 Local Nitro 0.045s (+5.3% 🔺) 1.006s (~) 0.961s 10 1.09x
💻 Local Next.js (Turbopack) 0.059s 1.007s 0.947s 10 1.42x
🐘 Postgres Express 0.060s (+2.8%) 1.012s (~) 0.952s 10 1.43x
🐘 Postgres Nitro 0.062s (-35.2% 🟢) 1.012s (-2.9%) 0.951s 10 1.48x
🐘 Postgres Next.js (Turbopack) 0.071s 1.013s 0.941s 10 1.71x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 0.304s (+29.2% 🔺) 9.230s (+332.2% 🔺) 8.926s 10 1.00x
▲ Vercel Nitro 0.467s (+14.0% 🔺) 8.212s (+227.3% 🔺) 7.745s 10 1.54x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Express | Nitro

workflow with 1 step

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 1.090s (-3.6%) 2.007s (~) 0.917s 10 1.00x
💻 Local Express 1.094s (-2.8%) 2.006s (~) 0.912s 10 1.00x
🐘 Postgres Nitro 1.100s (-3.5%) 2.008s (~) 0.909s 10 1.01x
🐘 Postgres Express 1.108s (-3.4%) 2.011s (~) 0.903s 10 1.02x
💻 Local Next.js (Turbopack) 1.137s 2.006s 0.869s 10 1.04x
🐘 Postgres Next.js (Turbopack) 1.154s 2.011s 0.856s 10 1.06x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 1.951s (-49.9% 🟢) 8.918s (+50.9% 🔺) 6.967s 10 1.00x
▲ Vercel Express 2.816s (+50.2% 🔺) 11.043s (+190.0% 🔺) 8.227s 10 1.44x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Nitro | Express

workflow with 10 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Express 10.509s (-3.8%) 11.022s (~) 0.513s 3 1.00x
🐘 Postgres Express 10.527s (-4.0%) 11.018s (~) 0.490s 3 1.00x
🐘 Postgres Nitro 10.543s (-3.0%) 11.018s (~) 0.475s 3 1.00x
💻 Local Nitro 10.549s (-3.6%) 11.023s (~) 0.475s 3 1.00x
💻 Local Next.js (Turbopack) 10.771s 11.022s 0.251s 3 1.02x
🐘 Postgres Next.js (Turbopack) 10.864s 11.019s 0.155s 3 1.03x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 13.250s (-44.2% 🟢) 17.759s (-29.3% 🟢) 4.509s 3 1.00x
▲ Vercel Express 18.536s (+9.2% 🔺) 25.082s (+25.3% 🔺) 6.546s 2 1.40x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Nitro | Express

workflow with 25 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 13.713s (-6.0% 🟢) 14.018s (-6.7% 🟢) 0.304s 5 1.00x
💻 Local Express 13.737s (-8.2% 🟢) 14.027s (-6.7% 🟢) 0.290s 5 1.00x
🐘 Postgres Express 13.748s (-5.7% 🟢) 14.016s (-6.7% 🟢) 0.268s 5 1.00x
💻 Local Nitro 13.768s (-8.6% 🟢) 14.027s (-12.5% 🟢) 0.260s 5 1.00x
💻 Local Next.js (Turbopack) 14.375s 15.031s 0.656s 4 1.05x
🐘 Postgres Next.js (Turbopack) 14.516s 15.019s 0.503s 4 1.06x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 22.401s (-65.2% 🟢) 41.317s (-38.0% 🟢) 18.916s 2 1.00x
▲ Vercel Express 22.701s (-54.9% 🟢) 31.002s (-41.0% 🟢) 8.301s 2 1.01x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Nitro | Express

workflow with 50 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 12.332s (-11.7% 🟢) 13.018s (-9.0% 🟢) 0.687s 7 1.00x
🐘 Postgres Express 12.367s (-11.7% 🟢) 13.017s (-10.8% 🟢) 0.649s 7 1.00x
💻 Local Express 12.445s (-25.0% 🟢) 13.025s (-23.5% 🟢) 0.580s 7 1.01x
💻 Local Nitro 12.686s (-24.4% 🟢) 13.168s (-22.7% 🟢) 0.482s 7 1.03x
💻 Local Next.js (Turbopack) 13.628s 14.028s 0.400s 7 1.11x
🐘 Postgres Next.js (Turbopack) 13.797s 14.164s 0.367s 7 1.12x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 27.762s (-77.1% 🟢) 31.197s (-74.8% 🟢) 3.435s 3 1.00x
▲ Vercel Nitro 28.303s (-93.3% 🟢) 36.682s (-91.4% 🟢) 8.379s 3 1.02x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Express | Nitro

Promise.all with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 1.186s (-5.9% 🟢) 2.008s (~) 0.822s 15 1.00x
💻 Local Express 1.198s (-19.6% 🟢) 2.006s (~) 0.808s 15 1.01x
💻 Local Nitro 1.206s (-26.1% 🟢) 2.007s (-3.2%) 0.800s 15 1.02x
🐘 Postgres Nitro 1.214s (-4.8%) 2.007s (~) 0.794s 15 1.02x
🐘 Postgres Next.js (Turbopack) 1.258s 2.007s 0.750s 15 1.06x
💻 Local Next.js (Turbopack) 1.347s 2.005s 0.659s 15 1.14x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.716s (-5.0% 🟢) 19.336s (+318.3% 🔺) 16.620s 2 1.00x
▲ Vercel Nitro 2.825s (~) 9.853s (+127.9% 🔺) 7.027s 4 1.04x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Express | Nitro

Promise.all with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 1.236s (-47.7% 🟢) 2.008s (-33.3% 🟢) 0.772s 15 1.00x
🐘 Postgres Nitro 1.255s (-46.6% 🟢) 2.007s (-33.3% 🟢) 0.752s 15 1.02x
🐘 Postgres Next.js (Turbopack) 1.428s 2.008s 0.579s 15 1.16x
💻 Local Next.js (Turbopack) 1.687s 2.074s 0.387s 15 1.36x
💻 Local Express 1.717s (-41.9% 🟢) 2.006s (-41.9% 🟢) 0.289s 15 1.39x
💻 Local Nitro 2.000s (-36.4% 🟢) 2.365s (-39.1% 🟢) 0.365s 14 1.62x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 3.186s (-21.4% 🟢) 11.331s (+91.4% 🔺) 8.145s 3 1.00x
▲ Vercel Express 6.602s (+82.4% 🔺) 18.243s (+257.0% 🔺) 11.642s 3 2.07x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Nitro | Express

Promise.all with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 1.383s (-60.3% 🟢) 2.007s (-50.0% 🟢) 0.624s 15 1.00x
🐘 Postgres Nitro 1.398s (-59.8% 🟢) 2.007s (-49.9% 🟢) 0.609s 15 1.01x
🐘 Postgres Next.js (Turbopack) 1.735s 2.315s 0.580s 13 1.25x
💻 Local Next.js (Turbopack) 4.602s 5.298s 0.696s 7 3.33x
💻 Local Express 4.827s (-42.1% 🟢) 5.514s (-38.9% 🟢) 0.687s 6 3.49x
💻 Local Nitro 6.170s (-26.1% 🟢) 6.617s (-26.6% 🟢) 0.447s 5 4.46x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 5.289s (+24.7% 🔺) 7.700s (+25.7% 🔺) 2.411s 4 1.00x
▲ Vercel Nitro 5.461s (+54.9% 🔺) 11.366s (+105.4% 🔺) 5.905s 3 1.03x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Express | Nitro

Promise.race with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.178s (-6.3% 🟢) 2.009s (~) 0.831s 15 1.00x
🐘 Postgres Express 1.193s (-5.1% 🟢) 2.008s (~) 0.815s 15 1.01x
🐘 Postgres Next.js (Turbopack) 1.249s 2.009s 0.760s 15 1.06x
💻 Local Next.js (Turbopack) 1.407s 2.006s 0.599s 15 1.19x
💻 Local Express 1.456s (-23.1% 🟢) 2.007s (-15.1% 🟢) 0.551s 15 1.24x
💻 Local Nitro 1.681s (-9.9% 🟢) 2.073s (-11.4% 🟢) 0.392s 15 1.43x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.482s (-3.8%) 8.298s (+90.8% 🔺) 5.816s 4 1.00x
▲ Vercel Nitro 2.653s (+7.9% 🔺) 5.245s (+25.8% 🔺) 2.592s 6 1.07x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Express | Nitro

Promise.race with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.242s (-46.9% 🟢) 2.009s (-33.3% 🟢) 0.767s 15 1.00x
🐘 Postgres Express 1.261s (-46.1% 🟢) 2.010s (-33.3% 🟢) 0.748s 15 1.02x
🐘 Postgres Next.js (Turbopack) 1.403s 2.008s 0.605s 15 1.13x
💻 Local Express 1.970s (-37.1% 🟢) 2.392s (-36.4% 🟢) 0.423s 13 1.59x
💻 Local Next.js (Turbopack) 2.017s 2.591s 0.574s 12 1.62x
💻 Local Nitro 2.086s (-31.9% 🟢) 2.591s (-33.3% 🟢) 0.505s 12 1.68x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 3.436s (+6.3% 🔺) 10.457s (+106.0% 🔺) 7.020s 3 1.00x
▲ Vercel Express 3.725s (+16.7% 🔺) 8.451s (+76.3% 🔺) 4.726s 4 1.08x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Nitro | Express

Promise.race with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.382s (-60.3% 🟢) 2.008s (-49.9% 🟢) 0.626s 15 1.00x
🐘 Postgres Express 1.385s (-60.4% 🟢) 2.008s (-49.9% 🟢) 0.622s 15 1.00x
🐘 Postgres Next.js (Turbopack) 1.746s 2.156s 0.411s 14 1.26x
💻 Local Express 4.650s (-47.2% 🟢) 5.180s (-44.1% 🟢) 0.530s 6 3.36x
💻 Local Next.js (Turbopack) 5.127s 5.683s 0.557s 6 3.71x
💻 Local Nitro 5.886s (-35.6% 🟢) 6.413s (-36.0% 🟢) 0.527s 5 4.26x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 6.106s (+19.9% 🔺) 10.232s (+50.1% 🔺) 4.125s 5 1.00x
▲ Vercel Express 10.634s (+65.7% 🔺) 15.236s (+86.3% 🔺) 4.602s 2 1.74x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Nitro | Express

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 0.565s (-32.6% 🟢) 1.007s (-1.6%) 0.442s 60 1.00x
💻 Local Express 0.578s (-41.3% 🟢) 1.005s (-6.6% 🟢) 0.427s 60 1.02x
🐘 Postgres Nitro 0.593s (-27.7% 🟢) 1.040s (+3.4%) 0.447s 59 1.05x
💻 Local Nitro 0.697s (-29.0% 🟢) 1.096s (~) 0.399s 55 1.23x
🐘 Postgres Next.js (Turbopack) 0.837s 1.007s 0.170s 60 1.48x
💻 Local Next.js (Turbopack) 0.868s 1.004s 0.136s 60 1.54x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 4.851s (-78.0% 🟢) 7.522s (-68.7% 🟢) 2.672s 8 1.00x
▲ Vercel Express 4.974s (-73.8% 🟢) 12.581s (-41.0% 🟢) 7.606s 6 1.03x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Nitro | Express

workflow with 25 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 1.325s (-33.0% 🟢) 2.008s (-11.1% 🟢) 0.682s 45 1.00x
🐘 Postgres Nitro 1.351s (-29.9% 🟢) 2.030s (-3.4%) 0.679s 45 1.02x
💻 Local Nitro 1.510s (-50.3% 🟢) 2.006s (-46.6% 🟢) 0.497s 45 1.14x
💻 Local Express 1.515s (-49.8% 🟢) 2.006s (-44.1% 🟢) 0.491s 45 1.14x
🐘 Postgres Next.js (Turbopack) 2.084s 2.468s 0.384s 37 1.57x
💻 Local Next.js (Turbopack) 2.112s 3.008s 0.896s 30 1.59x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 12.360s (-64.2% 🟢) 17.479s (-52.5% 🟢) 5.119s 6 1.00x
▲ Vercel Nitro 12.401s (-68.6% 🟢) 15.005s (-63.7% 🟢) 2.605s 7 1.00x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Express | Nitro

workflow with 50 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 2.594s (-36.8% 🟢) 3.033s (-34.1% 🟢) 0.439s 40 1.00x
🐘 Postgres Express 2.702s (-32.3% 🟢) 3.137s (-28.2% 🟢) 0.434s 39 1.04x
💻 Local Nitro 3.229s (-65.3% 🟢) 4.009s (-60.0% 🟢) 0.780s 30 1.24x
💻 Local Express 3.324s (-63.9% 🟢) 4.043s (-59.6% 🟢) 0.719s 30 1.28x
🐘 Postgres Next.js (Turbopack) 3.925s 4.010s 0.085s 30 1.51x
💻 Local Next.js (Turbopack) 4.452s 5.052s 0.601s 24 1.72x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 25.276s (-73.9% 🟢) 30.878s (-68.6% 🟢) 5.602s 4 1.00x
▲ Vercel Express 26.350s (-79.7% 🟢) 32.626s (-75.3% 🟢) 6.276s 4 1.04x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Nitro | Express

workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 0.217s (-23.3% 🟢) 1.006s (~) 0.788s 60 1.00x
🐘 Postgres Express 0.227s (-19.6% 🟢) 1.006s (~) 0.779s 60 1.05x
🐘 Postgres Next.js (Turbopack) 0.305s 1.023s 0.719s 59 1.40x
💻 Local Nitro 0.424s (-29.9% 🟢) 1.004s (-1.7%) 0.581s 60 1.95x
💻 Local Express 0.441s (-21.3% 🟢) 1.004s (~) 0.563s 60 2.03x
💻 Local Next.js (Turbopack) 0.627s 1.022s 0.395s 59 2.89x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.394s (+22.5% 🔺) 12.031s (+230.8% 🔺) 9.638s 5 1.00x
▲ Vercel Nitro 3.625s (+118.3% 🔺) 10.359s (+209.1% 🔺) 6.733s 6 1.51x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Express | Nitro

workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 0.339s (-31.7% 🟢) 1.006s (~) 0.668s 90 1.00x
🐘 Postgres Express 0.361s (-29.1% 🟢) 1.006s (~) 0.645s 90 1.07x
🐘 Postgres Next.js (Turbopack) 0.515s 1.007s 0.492s 90 1.52x
💻 Local Nitro 2.152s (-15.2% 🟢) 2.638s (-12.3% 🟢) 0.486s 35 6.35x
💻 Local Express 2.471s (-1.7%) 2.979s (-1.0%) 0.508s 31 7.29x
💻 Local Next.js (Turbopack) 2.513s 3.225s 0.712s 28 7.42x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 4.568s (+41.6% 🔺) 10.630s (+120.5% 🔺) 6.062s 9 1.00x
▲ Vercel Express 5.640s (+85.1% 🔺) 10.451s (+117.4% 🔺) 4.811s 10 1.23x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Nitro | Express

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 0.683s (-13.6% 🟢) 1.006s (~) 0.323s 120 1.00x
🐘 Postgres Express 0.705s (-13.9% 🟢) 1.015s (~) 0.310s 119 1.03x
🐘 Postgres Next.js (Turbopack) 1.048s 1.960s 0.912s 62 1.53x
💻 Local Nitro 9.742s (-12.9% 🟢) 10.277s (-11.9% 🟢) 0.534s 12 14.27x
💻 Local Next.js (Turbopack) 10.810s 11.575s 0.766s 11 15.83x
💻 Local Express 11.232s (~) 11.856s (-0.7%) 0.624s 11 16.45x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 13.763s (+85.5% 🔺) 17.466s (+88.9% 🔺) 3.702s 7 1.00x
▲ Vercel Nitro 15.302s (+98.1% 🔺) 21.654s (+130.4% 🔺) 6.352s 6 1.11x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Express | Nitro

Stream Benchmarks (includes TTFB metrics)
workflow with stream

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.156s (+463.8% 🔺) 2.000s (+100.1% 🔺) 0.001s (-6.7% 🟢) 2.010s (+98.8% 🔺) 0.855s 10 1.00x
💻 Local Express 1.163s (+484.4% 🔺) 2.005s (+99.6% 🔺) 0.011s (-13.2% 🟢) 2.018s (+98.2% 🔺) 0.854s 10 1.01x
💻 Local Nitro 1.165s (+445.3% 🔺) 2.005s (+99.6% 🔺) 0.012s (-0.8%) 2.020s (+98.2% 🔺) 0.854s 10 1.01x
🐘 Postgres Express 1.169s (+469.8% 🔺) 1.995s (+99.8% 🔺) 0.001s (-31.3% 🟢) 2.010s (+98.7% 🔺) 0.841s 10 1.01x
💻 Local Next.js (Turbopack) 1.214s 2.003s 0.011s 2.017s 0.804s 10 1.05x
🐘 Postgres Next.js (Turbopack) 1.233s 2.003s 0.001s 2.012s 0.779s 10 1.07x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.318s (-7.5% 🟢) 6.376s (+55.9% 🔺) 1.539s (+60.1% 🔺) 8.459s (+51.3% 🔺) 6.140s 10 1.00x
▲ Vercel Nitro 3.129s (-18.4% 🟢) 6.747s (+27.9% 🔺) 1.486s (+100.3% 🔺) 9.559s (+47.4% 🔺) 6.431s 10 1.35x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - - -

🔍 Observability: Express | Nitro

stream pipeline with 5 transform steps (1MB)

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 1.584s (+88.9% 🔺) 2.010s (+98.6% 🔺) 0.011s (+14.5% 🔺) 2.022s (+81.2% 🔺) 0.438s 30 1.00x
🐘 Postgres Nitro 1.588s (+154.4% 🔺) 2.007s (+99.4% 🔺) 0.004s (-9.7% 🟢) 2.026s (+98.1% 🔺) 0.438s 30 1.00x
🐘 Postgres Express 1.621s (+157.3% 🔺) 2.001s (+98.8% 🔺) 0.004s (~) 2.027s (+98.1% 🔺) 0.406s 30 1.02x
💻 Local Express 1.722s (+127.5% 🔺) 2.043s (+98.6% 🔺) 0.013s (+36.7% 🔺) 2.059s (+98.0% 🔺) 0.336s 30 1.09x
🐘 Postgres Next.js (Turbopack) 1.809s 2.011s 0.004s 2.029s 0.220s 30 1.14x
💻 Local Next.js (Turbopack) 1.917s 2.008s 0.010s 2.201s 0.284s 28 1.21x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 6.501s (~) 13.670s (+70.7% 🔺) 0.154s (-62.3% 🟢) 14.972s (+69.5% 🔺) 8.471s 5 1.00x
▲ Vercel Nitro 7.642s (-74.0% 🟢) 7.694s (-75.0% 🟢) 0.328s (+192.9% 🔺) 10.227s (-67.8% 🟢) 2.585s 6 1.18x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - - -

🔍 Observability: Express | Nitro

10 parallel streams (1MB each)

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 0.699s (-27.3% 🟢) 1.012s (-20.8% 🟢) 0.000s (-22.0% 🟢) 1.027s (-21.4% 🟢) 0.328s 59 1.00x
🐘 Postgres Nitro 0.704s (-27.3% 🟢) 1.015s (-18.6% 🟢) 0.000s (+22.0% 🔺) 1.032s (-18.0% 🟢) 0.328s 59 1.01x
🐘 Postgres Next.js (Turbopack) 0.835s 1.091s 0.000s 1.099s 0.264s 55 1.19x
💻 Local Nitro 1.375s (+12.5% 🔺) 2.013s (~) 0.000s (+100.0% 🔺) 2.015s (~) 0.640s 30 1.97x
💻 Local Next.js (Turbopack) 1.497s 2.013s 0.001s 2.016s 0.520s 30 2.14x
💻 Local Express 1.602s (+30.8% 🔺) 2.018s (~) 0.000s (-40.0% 🟢) 2.020s (~) 0.418s 30 2.29x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 3.997s (+31.0% 🔺) 8.575s (+95.2% 🔺) 0.000s (-100.0% 🟢) 9.792s (+103.6% 🔺) 5.796s 7 1.00x
▲ Vercel Express 5.270s (+40.9% 🔺) 8.952s (+75.4% 🔺) 0.001s (+358.3% 🔺) 10.718s (+93.8% 🔺) 5.448s 6 1.32x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - - -

🔍 Observability: Nitro | Express

fan-out fan-in 10 streams (1MB each)

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.409s (-21.3% 🟢) 2.142s (~) 0.000s (-100.0% 🟢) 2.154s (-0.9%) 0.745s 28 1.00x
🐘 Postgres Express 1.513s (-14.6% 🟢) 2.174s (~) 0.000s (+Infinity% 🔺) 2.189s (~) 0.677s 28 1.07x
🐘 Postgres Next.js (Turbopack) 1.650s 2.145s 0.000s 2.162s 0.512s 28 1.17x
💻 Local Nitro 3.097s (-8.6% 🟢) 3.775s (-6.4% 🟢) 0.001s (+40.6% 🔺) 3.777s (-6.4% 🟢) 0.681s 16 2.20x
💻 Local Next.js (Turbopack) 3.186s 3.674s 0.000s 3.678s 0.492s 17 2.26x
💻 Local Express 3.351s (-3.4%) 4.028s (~) 0.001s (+41.7% 🔺) 4.032s (~) 0.681s 15 2.38x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 5.775s (+25.9% 🔺) 12.656s (+110.2% 🔺) 0.001s (+Infinity% 🔺) 15.088s (+133.7% 🔺) 9.313s 4 1.00x
▲ Vercel Nitro 5.828s (+42.4% 🔺) 17.093s (+218.1% 🔺) 0.000s (-100.0% 🟢) 17.759s (+206.5% 🔺) 11.931s 4 1.01x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - - -

🔍 Observability: Express | Nitro

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World 🥇 Fastest Framework Wins
💻 Local Express 9/21
🐘 Postgres Nitro 13/21
▲ Vercel Express 11/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework 🥇 Fastest World Wins
Express 🐘 Postgres 16/21
Next.js (Turbopack) 🐘 Postgres 15/21
Nitro 🐘 Postgres 17/21
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Redis + BullMQ: Community world (local development)
  • 🌐 Cloudflare: Community world (local development)
  • 🌐 MySQL: Community world (local development)
  • 🌐 Azure: Community world (local development)
  • 🌐 NATS JetStream: Community world (local development)
  • 🌐 Upstash: Community world (local development)

📋 View full workflow run


Some benchmark jobs failed:

  • Local: success
  • Postgres: success
  • Vercel: failure

Check the workflow run for details.

@VaguelySerious VaguelySerious marked this pull request as ready for review June 1, 2026 09:06
@VaguelySerious VaguelySerious requested a review from a team as a code owner June 1, 2026 09:06
@VaguelySerious VaguelySerious merged commit ae3c833 into main Jun 1, 2026
112 of 122 checks passed
@VaguelySerious VaguelySerious deleted the peter/event-log-race-repro-classify-infra branch June 1, 2026 09:07
VaguelySerious added a commit that referenced this pull request Jun 1, 2026
(cherry picked from commit ae3c833)
(cherry picked from commit c1d7bab)
pranaygp added a commit that referenced this pull request Jun 2, 2026
* origin/main:
  [world-vercel] Retry transient response-body parse failures in the HTTP client (#2204)
  Add virtualization to the trace viewer (#2205)
  Trace viewer: scroll-load events past an auto-load cap (#2200)
  fix(core): resolve forwarded stream keys across deployments (#2191)
  [e2e] Improve error labeling in event-log-race-repro CI job (#2190)
  [core] Harden event pagination response parsing (#2180) (#2179)
  Add loading skeleton to the new trace viewer (#2164)
  Add tooltip components + apply on up/down detail pane  (#2163)
  fix(swc-plugin): allow wasm host imports during link (#2174)
  [test] Forward-port reused-sleep replay divergence test (#2172)
  [e2e] Add `event-log-race-repro` label for triggering CI stress-test (#2159)
  Version Packages (beta) (#2162)
  fix(world-local): skip Nov 2025 ghost versions on npm (#2168)
  fix(core,errors): classify SDK encryption failures as RUNTIME_ERROR (#2145)
  [web-shared][web] Fix events tab search (#2107)
  Version Packages (beta) (#2147)
  Allow setting workflow attributes from steps (#2157)
  Better search handling on the trace viewer (#2144)
  [docs] Document experimental attributes feature (#2141)
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