Skip to content

[core] Retry stream reopen against the reconnect budget#2334

Open
VaguelySerious wants to merge 1 commit into
mainfrom
peter/reconnect-budgeted-reopen
Open

[core] Retry stream reopen against the reconnect budget#2334
VaguelySerious wants to merge 1 commit into
mainfrom
peter/reconnect-budgeted-reopen

Conversation

@VaguelySerious

@VaguelySerious VaguelySerious commented Jun 10, 2026

Copy link
Copy Markdown
Member

Follow-up to #2318 (now merged), addressing @TooTallNate's review note on it.

#2318's forward-port made object-stream reconnect retry on reader.read() errors, but a transient failure of the reopen itselfconnect() throwing inside reconnect() because the server is briefly unavailable during the reconnect window — was fatal. That's exactly the blip the wrapper exists to survive.

This makes the reopen retry against the reconnect budget instead of erroring the stream: each reopen attempt counts against the consecutive-failure cap (and the absolute backstop), so a server that stays down still terminates the stream, but a momentary blip no longer kills it. The cancel/reset of buffered state moves ahead of the retry loop so every attempt resumes from the same frame index.

Test

New case in reconnecting-framed-stream.test.ts: a reopen that throws once then succeeds recovers transparently (the failed reopen never surfaces to the consumer; resume index is unchanged). All 12 reconnect tests pass.

Notes

  • Scoped to @workflow/core; user-facing behavior is unchanged (object streams reconnect) — this hardens the path against the blip it targets.
  • Same sequencing as the stable line ([core] Move stream reconnect logic to getReadable level #1847): the reconnect path only triggers once the coordinated server-side change errors timed-out connections instead of closing them.

🤖 Generated with Claude Code

@changeset-bot

changeset-bot Bot commented Jun 10, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 19a31ce

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

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

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel

vercel Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

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 Jun 11, 2026 7:20am
example-nextjs-workflow-webpack Ready Ready Preview, Comment Jun 11, 2026 7:20am
example-workflow Ready Ready Preview, Comment Jun 11, 2026 7:20am
workbench-astro-workflow Ready Ready Preview, Comment Jun 11, 2026 7:20am
workbench-express-workflow Ready Ready Preview, Comment Jun 11, 2026 7:20am
workbench-fastify-workflow Ready Ready Preview, Comment Jun 11, 2026 7:20am
workbench-hono-workflow Ready Ready Preview, Comment Jun 11, 2026 7:20am
workbench-nitro-workflow Ready Ready Preview, Comment Jun 11, 2026 7:20am
workbench-nuxt-workflow Ready Ready Preview, Comment Jun 11, 2026 7:20am
workbench-sveltekit-workflow Ready Ready Preview, Comment Jun 11, 2026 7:20am
workbench-tanstack-start-workflow Ready Ready Preview, Comment Jun 11, 2026 7:20am
workbench-vite-workflow Ready Ready Preview, Comment Jun 11, 2026 7:20am
workflow-docs Ready Ready Preview, Comment, Open in v0 Jun 11, 2026 7:20am
workflow-swc-playground Ready Ready Preview, Comment Jun 11, 2026 7:20am
workflow-tarballs Ready Ready Preview, Comment Jun 11, 2026 7:20am
workflow-web Ready Ready Preview, Comment Jun 11, 2026 7:20am

Addresses review feedback on #2318: a transient failure of the reopen
itself (`connect()` throwing inside `reconnect()`) was fatal — only
`reader.read()` errors were retried. A brief server unavailability during
the reconnect window is exactly the blip this wrapper exists to survive,
so count it against the reconnect budget and retry rather than erroring
the stream. Budget exhaustion (a server that stays down) still terminates.

Adds a test: a reopen that throws once then succeeds recovers transparently.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@VaguelySerious VaguelySerious force-pushed the peter/reconnect-budgeted-reopen branch from 1ec49b1 to 19a31ce Compare June 11, 2026 07:15
@github-actions

github-actions Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

All tests passed

Summary

Passed Failed Skipped Total
✅ ▲ Vercel Production 1266 0 219 1485
✅ 💻 Local Development 1671 0 219 1890
✅ 📦 Local Production 1671 0 219 1890
✅ 🐘 Local Postgres 1671 0 219 1890
✅ 🪟 Windows 135 0 0 135
✅ 📋 Other 769 0 176 945
Total 7183 0 1052 8235

Details by Category

✅ ▲ Vercel Production
App Passed Failed Skipped
✅ astro 109 0 26
✅ example 109 0 26
✅ express 109 0 26
✅ fastify 109 0 26
✅ hono 109 0 26
✅ nextjs-turbopack 133 0 2
✅ nextjs-webpack 133 0 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 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 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 109 0 26

📋 View full workflow run

@github-actions

github-actions Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

📊 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 🥇 Nitro 0.043s (+0.9%) 1.006s (~) 0.963s 10 1.00x
💻 Local Express 0.045s (+3.2%) 1.007s (~) 0.962s 10 1.03x
🐘 Postgres Nitro 0.058s (-7.9% 🟢) 1.013s (~) 0.955s 10 1.35x
💻 Local Next.js (Turbopack) 0.064s (+15.5% 🔺) 1.006s (~) 0.942s 10 1.47x
🐘 Postgres Express 0.064s (-3.8%) 1.012s (~) 0.949s 10 1.48x
🐘 Postgres Next.js (Turbopack) 0.069s (-1.9%) 1.012s (~) 0.943s 10 1.59x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 0.251s (-8.0% 🟢) 1.949s (-28.2% 🟢) 1.698s 10 1.00x
▲ Vercel Nitro 0.277s (+6.1% 🔺) 2.137s (-12.3% 🟢) 1.859s 10 1.11x
▲ 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.092s (~) 2.006s (~) 0.914s 10 1.00x
💻 Local Express 1.097s (~) 2.006s (~) 0.909s 10 1.00x
🐘 Postgres Express 1.110s (+1.6%) 2.010s (~) 0.900s 10 1.02x
🐘 Postgres Nitro 1.121s (+0.6%) 2.010s (~) 0.890s 10 1.03x
💻 Local Next.js (Turbopack) 1.136s (+2.5%) 2.007s (~) 0.870s 10 1.04x
🐘 Postgres Next.js (Turbopack) 1.149s (+0.7%) 2.011s (~) 0.862s 10 1.05x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 1.748s (+11.6% 🔺) 3.872s (+9.7% 🔺) 2.124s 10 1.00x
▲ Vercel Express 1.762s (+11.3% 🔺) 4.072s (+14.0% 🔺) 2.309s 10 1.01x
▲ 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 🥇 Nitro 10.526s (~) 11.023s (~) 0.497s 3 1.00x
💻 Local Express 10.528s (~) 11.021s (~) 0.492s 3 1.00x
🐘 Postgres Express 10.543s (-1.6%) 11.020s (-2.9%) 0.477s 3 1.00x
🐘 Postgres Nitro 10.583s (~) 11.021s (~) 0.438s 3 1.01x
💻 Local Next.js (Turbopack) 10.824s (+2.0%) 11.022s (~) 0.198s 3 1.03x
🐘 Postgres Next.js (Turbopack) 10.837s (~) 11.021s (~) 0.185s 3 1.03x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 13.631s (+2.3%) 16.003s (+2.6%) 2.372s 2 1.00x
▲ Vercel Express 13.683s (+4.0%) 15.871s (+2.7%) 2.188s 2 1.00x
▲ 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
💻 Local 🥇 Nitro 13.713s (~) 14.027s (~) 0.314s 5 1.00x
🐘 Postgres Express 13.733s (-0.7%) 14.021s (-1.5%) 0.289s 5 1.00x
💻 Local Express 13.780s (-0.9%) 14.027s (-1.4%) 0.247s 5 1.00x
🐘 Postgres Nitro 13.794s (~) 14.019s (~) 0.225s 5 1.01x
💻 Local Next.js (Turbopack) 14.394s (+2.6%) 15.029s (+2.8%) 0.635s 4 1.05x
🐘 Postgres Next.js (Turbopack) 14.466s (-0.9%) 15.019s (~) 0.553s 4 1.05x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 21.762s (-14.7% 🟢) 24.783s (-10.2% 🟢) 3.021s 3 1.00x
▲ Vercel Express 22.298s (-12.5% 🟢) 24.631s (-9.6% 🟢) 2.332s 3 1.02x
▲ 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 🥇 Express 12.393s (-2.7%) 13.018s (-2.2%) 0.626s 7 1.00x
💻 Local Nitro 12.539s (+1.0%) 13.025s (~) 0.486s 7 1.01x
💻 Local Express 12.559s (~) 13.025s (~) 0.467s 7 1.01x
🐘 Postgres Nitro 12.607s (-1.1%) 13.022s (~) 0.416s 7 1.02x
🐘 Postgres Next.js (Turbopack) 13.755s (~) 14.018s (~) 0.263s 7 1.11x
💻 Local Next.js (Turbopack) 13.833s (+6.8% 🔺) 14.169s (+6.5% 🔺) 0.336s 7 1.12x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 33.742s (+5.2% 🔺) 36.184s (+5.7% 🔺) 2.442s 3 1.00x
▲ Vercel Nitro 34.588s (+19.1% 🔺) 37.154s (+18.4% 🔺) 2.566s 3 1.03x
▲ 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.177s (-1.9%) 2.008s (-0.7%) 0.831s 15 1.00x
🐘 Postgres Nitro 1.191s (-0.6%) 2.008s (~) 0.817s 15 1.01x
💻 Local Express 1.198s (-5.2% 🟢) 2.006s (~) 0.808s 15 1.02x
💻 Local Nitro 1.219s (+0.5%) 2.006s (~) 0.787s 15 1.04x
🐘 Postgres Next.js (Turbopack) 1.236s (-1.3%) 2.008s (~) 0.772s 15 1.05x
💻 Local Next.js (Turbopack) 1.326s (+8.4% 🔺) 2.006s (~) 0.680s 15 1.13x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.462s (-11.1% 🟢) 4.327s (-8.3% 🟢) 1.865s 7 1.00x
▲ Vercel Nitro 2.710s (-2.2%) 4.838s (+11.4% 🔺) 2.127s 7 1.10x
▲ 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.238s (-6.7% 🟢) 2.007s (~) 0.769s 15 1.00x
🐘 Postgres Nitro 1.282s (+1.8%) 2.007s (~) 0.726s 15 1.04x
🐘 Postgres Next.js (Turbopack) 1.397s (-0.8%) 2.007s (~) 0.610s 15 1.13x
💻 Local Express 1.630s (-13.4% 🟢) 2.005s (-9.7% 🟢) 0.375s 15 1.32x
💻 Local Next.js (Turbopack) 1.812s (+5.0%) 2.073s (+3.4%) 0.261s 15 1.46x
💻 Local Nitro 1.966s (+15.4% 🔺) 2.315s (+11.7% 🔺) 0.348s 13 1.59x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 3.429s (-15.8% 🟢) 5.433s (-12.5% 🟢) 2.004s 6 1.00x
▲ Vercel Express 3.531s (-13.6% 🟢) 5.834s (-5.4% 🟢) 2.303s 6 1.03x
▲ 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 🥇 Nitro 1.383s (-1.7%) 2.009s (~) 0.626s 15 1.00x
🐘 Postgres Express 1.390s (~) 2.007s (~) 0.617s 15 1.01x
🐘 Postgres Next.js (Turbopack) 1.851s (+5.2% 🔺) 2.592s (+12.9% 🔺) 0.741s 12 1.34x
💻 Local Express 4.164s (-21.4% 🟢) 4.725s (-21.4% 🟢) 0.561s 7 3.01x
💻 Local Next.js (Turbopack) 5.503s (+25.2% 🔺) 6.014s (+20.0% 🔺) 0.510s 5 3.98x
💻 Local Nitro 5.606s (+18.8% 🔺) 6.415s (+28.0% 🔺) 0.808s 5 4.05x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 5.087s (-24.5% 🟢) 7.809s (-10.3% 🟢) 2.723s 4 1.00x
▲ Vercel Express 6.099s (+3.3%) 9.054s (+14.7% 🔺) 2.955s 4 1.20x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Nitro | Express

Promise.race with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 1.183s (-1.6%) 2.008s (~) 0.824s 15 1.00x
🐘 Postgres Nitro 1.195s (~) 2.010s (~) 0.814s 15 1.01x
🐘 Postgres Next.js (Turbopack) 1.281s (+1.2%) 2.008s (~) 0.726s 15 1.08x
💻 Local Next.js (Turbopack) 1.409s (+7.9% 🔺) 2.007s (~) 0.598s 15 1.19x
💻 Local Nitro 1.550s (~) 2.007s (~) 0.457s 15 1.31x
💻 Local Express 1.603s (-3.2%) 2.006s (-3.3%) 0.403s 15 1.35x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 2.393s (-10.4% 🟢) 4.194s (-3.2%) 1.801s 8 1.00x
▲ Vercel Express 2.802s (+9.1% 🔺) 5.065s (+20.6% 🔺) 2.263s 7 1.17x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Nitro | Express

Promise.race with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 1.263s (+1.6%) 2.008s (~) 0.745s 15 1.00x
🐘 Postgres Nitro 1.265s (-0.8%) 2.009s (~) 0.744s 15 1.00x
🐘 Postgres Next.js (Turbopack) 1.396s (~) 2.008s (~) 0.613s 15 1.10x
💻 Local Express 1.789s (-15.8% 🟢) 2.075s (-19.9% 🟢) 0.286s 15 1.42x
💻 Local Next.js (Turbopack) 1.960s (-3.0%) 2.293s (-8.5% 🟢) 0.332s 14 1.55x
💻 Local Nitro 2.048s (+16.6% 🔺) 2.509s (+21.1% 🔺) 0.461s 12 1.62x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 3.354s (-8.8% 🟢) 5.412s (-3.6%) 2.058s 6 1.00x
▲ Vercel Nitro 65.143s (+1490.9% 🔺) 67.578s (+1025.8% 🔺) 2.435s 5 19.42x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Express | Nitro

Promise.race with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.358s (-7.1% 🟢) 2.008s (~) 0.651s 15 1.00x
🐘 Postgres Express 1.404s (-6.4% 🟢) 2.007s (-16.3% 🟢) 0.603s 15 1.03x
🐘 Postgres Next.js (Turbopack) 1.673s (+1.1%) 2.075s (~) 0.402s 15 1.23x
💻 Local Express 4.991s (-14.9% 🟢) 5.512s (-11.3% 🟢) 0.521s 6 3.68x
💻 Local Nitro 5.753s (+21.3% 🔺) 6.416s (+20.1% 🔺) 0.663s 5 4.24x
💻 Local Next.js (Turbopack) 6.089s (+18.0% 🔺) 6.617s (+10.0% 🔺) 0.528s 5 4.48x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 5.481s (+8.0% 🔺) 7.794s (+17.6% 🔺) 2.313s 5 1.00x
▲ Vercel Nitro 9.306s (+88.8% 🔺) 11.398s (+69.2% 🔺) 2.092s 3 1.70x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Express | Nitro

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 0.547s (-17.9% 🟢) 1.007s (-3.9%) 0.459s 60 1.00x
💻 Local Nitro 0.589s (-26.7% 🟢) 1.005s (-16.6% 🟢) 0.415s 60 1.08x
💻 Local Express 0.601s (-8.4% 🟢) 1.005s (-3.4%) 0.404s 60 1.10x
🐘 Postgres Nitro 0.611s (~) 1.007s (~) 0.396s 60 1.12x
🐘 Postgres Next.js (Turbopack) 0.826s (+1.7%) 1.024s (+1.7%) 0.198s 59 1.51x
💻 Local Next.js (Turbopack) 0.885s (+27.2% 🔺) 1.005s (~) 0.119s 60 1.62x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 6.267s (-16.0% 🟢) 8.147s (-14.4% 🟢) 1.880s 8 1.00x
▲ Vercel Express 6.650s (+20.9% 🔺) 8.577s (+20.6% 🔺) 1.927s 8 1.06x
▲ 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.360s (-11.5% 🟢) 2.053s (-4.6%) 0.692s 45 1.00x
💻 Local Nitro 1.488s (+1.7%) 2.006s (~) 0.518s 45 1.09x
🐘 Postgres Nitro 1.491s (+5.2% 🔺) 2.053s (+2.3%) 0.562s 45 1.10x
💻 Local Express 1.539s (-3.3%) 2.028s (~) 0.489s 45 1.13x
🐘 Postgres Next.js (Turbopack) 1.979s (+1.9%) 2.283s (+5.0% 🔺) 0.304s 40 1.46x
💻 Local Next.js (Turbopack) 2.170s (+25.5% 🔺) 3.008s (+48.4% 🔺) 0.838s 30 1.60x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 14.389s (+8.9% 🔺) 16.583s (+7.1% 🔺) 2.194s 6 1.00x
▲ Vercel Express 16.033s (-2.1%) 19.063s (+4.1%) 3.030s 5 1.11x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Nitro | Express

workflow with 50 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 2.650s (-9.0% 🟢) 3.086s (-12.8% 🟢) 0.436s 39 1.00x
🐘 Postgres Nitro 2.810s (-3.5%) 3.112s (-5.1% 🟢) 0.302s 39 1.06x
💻 Local Nitro 3.241s (+1.1%) 4.009s (~) 0.768s 30 1.22x
💻 Local Express 3.248s (-5.0% 🟢) 4.009s (~) 0.761s 30 1.23x
🐘 Postgres Next.js (Turbopack) 3.881s (+0.5%) 4.148s (+1.7%) 0.267s 29 1.46x
💻 Local Next.js (Turbopack) 4.445s (+19.2% 🔺) 5.011s (+21.9% 🔺) 0.566s 24 1.68x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 26.945s (-9.5% 🟢) 29.065s (-9.1% 🟢) 2.119s 5 1.00x
▲ Vercel Express 31.336s (+8.6% 🔺) 34.168s (+10.6% 🔺) 2.833s 4 1.16x
▲ 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 🥇 Express 0.216s (-14.2% 🟢) 1.006s (~) 0.790s 60 1.00x
🐘 Postgres Nitro 0.223s (-5.1% 🟢) 1.007s (~) 0.784s 60 1.03x
🐘 Postgres Next.js (Turbopack) 0.286s (+1.5%) 1.006s (~) 0.720s 60 1.32x
💻 Local Nitro 0.431s (+1.4%) 1.005s (~) 0.574s 60 1.99x
💻 Local Express 0.454s (-2.3%) 1.004s (~) 0.550s 60 2.10x
💻 Local Next.js (Turbopack) 0.632s (+3.5%) 1.039s (~) 0.407s 59 2.92x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 2.613s (+11.4% 🔺) 4.718s (+8.9% 🔺) 2.105s 13 1.00x
▲ Vercel Express 2.804s (+26.7% 🔺) 4.754s (+16.0% 🔺) 1.950s 13 1.07x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Nitro | Express

workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 0.329s (-11.4% 🟢) 1.007s (~) 0.678s 90 1.00x
🐘 Postgres Express 0.351s (+3.6%) 1.018s (+1.1%) 0.667s 89 1.07x
🐘 Postgres Next.js (Turbopack) 0.503s (+4.2%) 1.007s (~) 0.504s 90 1.53x
💻 Local Express 2.126s (-3.0%) 2.609s (-7.6% 🟢) 0.483s 35 6.47x
💻 Local Nitro 2.128s (+3.1%) 2.714s (+2.9%) 0.586s 34 6.47x
💻 Local Next.js (Turbopack) 2.492s (+1.7%) 3.150s (+1.3%) 0.658s 29 7.58x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 5.498s (-87.3% 🟢) 7.300s (-83.9% 🟢) 1.802s 13 1.00x
▲ Vercel Nitro 6.163s (-85.9% 🟢) 8.375s (-81.8% 🟢) 2.212s 11 1.12x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Express | Nitro

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 0.657s (+5.0%) 1.006s (-4.6%) 0.350s 120 1.00x
🐘 Postgres Nitro 0.668s (-5.5% 🟢) 1.015s (+0.8%) 0.347s 119 1.02x
🐘 Postgres Next.js (Turbopack) 0.977s (~) 1.622s (+0.9%) 0.645s 75 1.49x
💻 Local Express 9.175s (-11.1% 🟢) 9.716s (-10.6% 🟢) 0.541s 13 13.97x
💻 Local Nitro 9.721s (+11.6% 🔺) 10.196s (+9.3% 🔺) 0.475s 12 14.80x
💻 Local Next.js (Turbopack) 10.789s (+4.6%) 11.486s (+1.6%) 0.698s 11 16.43x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 14.998s (-95.2% 🟢) 17.464s (-94.4% 🟢) 2.466s 7 1.00x
▲ Vercel Express 16.706s (+9.5% 🔺) 19.415s (+11.0% 🔺) 2.709s 7 1.11x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Nitro | Express

Stream Benchmarks (includes TTFB metrics)
workflow with stream

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Express 1.157s (-1.0%) 2.004s (~) 0.010s (-24.2% 🟢) 2.017s (~) 0.859s 10 1.00x
🐘 Postgres Express 1.163s (-2.6%) 2.002s (~) 0.001s (-97.1% 🟢) 2.009s (-1.7%) 0.846s 10 1.01x
💻 Local Nitro 1.163s (+1.1%) 2.005s (~) 0.012s (+24.0% 🔺) 2.020s (~) 0.856s 10 1.01x
🐘 Postgres Nitro 1.167s (-1.2%) 2.001s (~) 0.001s (-21.4% 🟢) 2.011s (~) 0.844s 10 1.01x
💻 Local Next.js (Turbopack) 1.209s (+3.5%) 2.004s (~) 0.012s (+21.8% 🔺) 2.020s (~) 0.811s 10 1.05x
🐘 Postgres Next.js (Turbopack) 1.228s (~) 2.003s (~) 0.001s (-33.3% 🟢) 2.012s (~) 0.784s 10 1.06x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 2.355s (+8.8% 🔺) 3.548s (+3.8%) 0.891s (+72.8% 🔺) 4.976s (+11.4% 🔺) 2.621s 10 1.00x
▲ Vercel Express 2.507s (+16.9% 🔺) 3.691s (+8.3% 🔺) 0.885s (+68.3% 🔺) 5.295s (+19.1% 🔺) 2.788s 10 1.06x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - - -

🔍 Observability: Nitro | Express

stream pipeline with 5 transform steps (1MB)

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 1.568s (-9.7% 🟢) 2.006s (-6.4% 🟢) 0.005s (+66.5% 🔺) 2.027s (-6.2% 🟢) 0.459s 30 1.00x
💻 Local Nitro 1.582s (-9.2% 🟢) 2.012s (~) 0.013s (+37.6% 🔺) 2.026s (-7.9% 🟢) 0.444s 30 1.01x
💻 Local Express 1.583s (-3.3%) 2.010s (~) 0.014s (+25.7% 🔺) 2.025s (~) 0.442s 30 1.01x
🐘 Postgres Nitro 1.644s (-1.2%) 2.009s (~) 0.005s (+29.9% 🔺) 2.028s (~) 0.384s 30 1.05x
🐘 Postgres Next.js (Turbopack) 1.763s (~) 2.011s (~) 0.005s (+27.3% 🔺) 2.028s (~) 0.265s 30 1.12x
💻 Local Next.js (Turbopack) 1.763s (+7.5% 🔺) 2.009s (~) 0.014s (+35.6% 🔺) 2.026s (~) 0.263s 30 1.12x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 5.940s (+3.4%) 7.822s (+3.0%) 0.227s (-32.9% 🟢) 8.625s (+1.7%) 2.685s 7 1.00x
▲ Vercel Express 6.850s (+19.0% 🔺) 8.544s (+15.0% 🔺) 0.266s (-24.8% 🟢) 9.369s (+11.5% 🔺) 2.518s 7 1.15x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - - -

🔍 Observability: Nitro | Express

10 parallel streams (1MB each)

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 0.699s (-28.5% 🟢) 1.032s (-27.7% 🟢) 0.000s (-50.9% 🟢) 1.060s (-26.8% 🟢) 0.360s 57 1.00x
🐘 Postgres Nitro 0.755s (+4.4%) 1.052s (+2.0%) 0.000s (-66.1% 🟢) 1.060s (+1.2%) 0.305s 57 1.08x
🐘 Postgres Next.js (Turbopack) 0.843s (+1.3%) 1.092s (+1.9%) 0.000s (-49.1% 🟢) 1.099s (+1.8%) 0.256s 55 1.21x
💻 Local Nitro 1.367s (+1.0%) 2.014s (~) 0.000s (-26.7% 🟢) 2.016s (~) 0.649s 30 1.95x
💻 Local Express 1.393s (-6.1% 🟢) 2.012s (~) 0.000s (-46.7% 🟢) 2.014s (~) 0.622s 30 1.99x
💻 Local Next.js (Turbopack) 1.541s (+6.5% 🔺) 2.014s (~) 0.001s (+162.5% 🔺) 2.017s (~) 0.476s 30 2.20x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 3.030s (-15.9% 🟢) 4.686s (-7.6% 🟢) 0.000s (+Infinity% 🔺) 5.262s (-6.5% 🟢) 2.232s 12 1.00x
▲ Vercel Express 3.258s (-19.7% 🟢) 4.647s (-13.0% 🟢) 0.000s (-100.0% 🟢) 5.274s (-14.5% 🟢) 2.016s 12 1.08x
▲ 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 🥇 Express 1.289s (-20.2% 🟢) 1.997s (-11.4% 🟢) 0.000s (+Infinity% 🔺) 2.041s (-10.5% 🟢) 0.752s 30 1.00x
🐘 Postgres Nitro 1.557s (+10.4% 🔺) 2.142s (+7.3% 🔺) 0.000s (NaN%) 2.152s (+7.0% 🔺) 0.595s 28 1.21x
🐘 Postgres Next.js (Turbopack) 1.719s (-0.5%) 2.224s (-1.7%) 0.000s (+Infinity% 🔺) 2.232s (-1.6%) 0.513s 27 1.33x
💻 Local Next.js (Turbopack) 3.019s (-6.0% 🟢) 3.525s (-9.5% 🟢) 0.000s (+6.7% 🔺) 3.534s (-9.4% 🟢) 0.515s 18 2.34x
💻 Local Nitro 3.080s (-1.1%) 3.836s (-1.5%) 0.001s (+275.0% 🔺) 3.841s (-1.5%) 0.761s 16 2.39x
💻 Local Express 3.163s (-5.1% 🟢) 3.881s (+1.1%) 0.001s (+100.0% 🔺) 3.901s (+1.5%) 0.738s 16 2.45x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 4.783s (-24.3% 🟢) 6.324s (-17.1% 🟢) 0.000s (-100.0% 🟢) 6.820s (-16.7% 🟢) 2.037s 9 1.00x
▲ Vercel Nitro 5.029s (-28.6% 🟢) 6.673s (-22.1% 🟢) 0.000s (+Infinity% 🔺) 7.182s (-21.0% 🟢) 2.153s 9 1.05x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - - -

🔍 Observability: Express | Nitro

Summary

Fastest Framework by World

Winner determined by most benchmark wins

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

Winner determined by most benchmark wins

Framework 🥇 Fastest World Wins
Express 🐘 Postgres 17/21
Next.js (Turbopack) 🐘 Postgres 16/21
Nitro 🐘 Postgres 12/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.

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