Skip to content

[core] Bound event pagination against non-progressing pages#2187

Open
VaguelySerious wants to merge 2 commits into
mainfrom
peter/harden-event-pagination-progress
Open

[core] Bound event pagination against non-progressing pages#2187
VaguelySerious wants to merge 2 commits into
mainfrom
peter/harden-event-pagination-progress

Conversation

@VaguelySerious
Copy link
Copy Markdown
Member

@VaguelySerious VaguelySerious commented May 31, 2026

Follow-up to #2179 (comment) which hardened event list cursor parsing, to further protect it against cursor llops.

These changes specifically protect against a backend that restarts the read at the beginning (it re-issues a cursor we already requested). It does not bound the loop against a backend that keeps returning fresh cursors with empty or fully-overlapping pages while reporting hasMore: true: no cursor ever repeats, appendUniqueEvents keeps the result flat, and while (hasMore) spins forever.

The change is to treat a non-final page that adds zero new events as a WORLD_CONTRACT_ERROR. A legitimate non-final page over an ascending cursor must surface at least one event after the cursor, so this can't false-positive on large runs — and it needs no arbitrary page-count cap (avoids a magic number that would need sizing above the largest legitimate run).

A backend that keeps returning fresh cursors with empty or
fully-overlapping pages while reporting `hasMore: true` would spin the
`loadWorkflowRunEvents` loop forever — the existing cursor guards only
catch a cursor that repeats a previously requested value, and
`appendUniqueEvents` keeps the result flat instead of growing.

Treat a non-final page that adds zero new events as a world contract
error. This fully closes the non-progression hole without an arbitrary
page-count cap.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@VaguelySerious VaguelySerious requested a review from a team as a code owner May 31, 2026 09:14
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 31, 2026

🦋 Changeset detected

Latest commit: 94ab785

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

This PR includes changesets to release 16 packages
Name Type
@workflow/core Patch
@workflow/builders Patch
@workflow/cli Patch
@workflow/next Patch
@workflow/nitro Patch
@workflow/vitest Patch
@workflow/web-shared Patch
@workflow/web Patch
workflow Patch
@workflow/world-testing Patch
@workflow/astro Patch
@workflow/nest Patch
@workflow/rollup Patch
@workflow/sveltekit Patch
@workflow/vite Patch
@workflow/nuxt Patch

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

@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 🥇 Nitro 0.038s (-11.6% 🟢) 1.005s (~) 0.967s 10 1.00x
💻 Local Express 0.043s (-1.8%) 1.006s (~) 0.962s 10 1.14x
💻 Local Next.js (Turbopack) 0.063s 1.006s 0.943s 10 1.65x
🐘 Postgres Express 0.067s (+16.2% 🔺) 1.011s (~) 0.944s 10 1.77x
🐘 Postgres Next.js (Turbopack) 0.070s 1.012s 0.943s 10 1.83x
🐘 Postgres Nitro ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 0.245s (+4.3%) 3.677s (+72.2% 🔺) 3.432s 10 1.00x
▲ Vercel Nitro 0.285s (-30.5% 🟢) 3.582s (+42.7% 🔺) 3.297s 10 1.16x
▲ Vercel Next.js (Turbopack) 0.363s (+44.4% 🔺) 3.975s (+70.4% 🔺) 3.612s 10 1.48x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 1.085s (-4.1%) 2.007s (~) 0.922s 10 1.00x
💻 Local Express 1.097s (-2.6%) 2.006s (~) 0.910s 10 1.01x
🐘 Postgres Express 1.126s (-1.8%) 2.010s (~) 0.884s 10 1.04x
💻 Local Next.js (Turbopack) 1.147s 2.006s 0.859s 10 1.06x
🐘 Postgres Next.js (Turbopack) 1.149s 2.010s 0.861s 10 1.06x
🐘 Postgres Nitro ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 1.617s (-20.6% 🟢) 3.678s (-4.0%) 2.062s 10 1.00x
▲ Vercel Nitro 1.639s (-57.9% 🟢) 3.786s (-35.9% 🟢) 2.147s 10 1.01x
▲ Vercel Express 1.686s (-10.1% 🟢) 3.755s (-1.4%) 2.069s 10 1.04x

🔍 Observability: Next.js (Turbopack) | Nitro | Express

workflow with 10 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 10.485s (-4.2%) 11.020s (~) 0.536s 3 1.00x
💻 Local Express 10.546s (-3.4%) 11.022s (~) 0.476s 3 1.01x
🐘 Postgres Express 10.574s (-3.6%) 11.020s (~) 0.446s 3 1.01x
💻 Local Next.js (Turbopack) 10.779s 11.023s 0.244s 3 1.03x
🐘 Postgres Next.js (Turbopack) 10.862s 11.020s 0.158s 3 1.04x
🐘 Postgres Nitro ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 13.602s (-19.9% 🟢) 18.431s (-7.9% 🟢) 4.829s 2 1.00x
▲ Vercel Nitro 13.786s (-41.9% 🟢) 16.298s (-35.1% 🟢) 2.512s 2 1.01x
▲ Vercel Next.js (Turbopack) 14.226s (-17.9% 🟢) 16.533s (-14.8% 🟢) 2.307s 2 1.05x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 25 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 13.693s (-9.1% 🟢) 14.026s (-12.5% 🟢) 0.333s 5 1.00x
💻 Local Express 13.729s (-8.3% 🟢) 14.027s (-6.7% 🟢) 0.298s 5 1.00x
🐘 Postgres Express 13.771s (-5.6% 🟢) 14.019s (-6.7% 🟢) 0.248s 5 1.01x
💻 Local Next.js (Turbopack) 14.318s 15.030s 0.712s 4 1.05x
🐘 Postgres Next.js (Turbopack) 14.517s 15.024s 0.507s 4 1.06x
🐘 Postgres Nitro ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 21.970s (-65.9% 🟢) 25.966s (-61.0% 🟢) 3.996s 3 1.00x
▲ Vercel Next.js (Turbopack) 22.671s (-56.9% 🟢) 24.249s (-55.6% 🟢) 1.578s 3 1.03x
▲ Vercel Express 23.815s (-52.7% 🟢) 25.289s (-51.9% 🟢) 1.474s 3 1.08x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

workflow with 50 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Express 12.463s (-24.9% 🟢) 13.024s (-23.5% 🟢) 0.561s 7 1.00x
💻 Local Nitro 12.515s (-25.4% 🟢) 13.168s (-22.7% 🟢) 0.653s 7 1.00x
🐘 Postgres Express 12.629s (-9.8% 🟢) 13.021s (-10.8% 🟢) 0.392s 7 1.01x
💻 Local Next.js (Turbopack) 13.601s 14.027s 0.427s 7 1.09x
🐘 Postgres Next.js (Turbopack) 13.703s 14.021s 0.318s 7 1.10x
🐘 Postgres Nitro ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 32.025s (-91.9% 🟢) 36.370s (-90.8% 🟢) 4.345s 3 1.00x
▲ Vercel Nitro 34.726s (-91.8% 🟢) 36.883s (-91.3% 🟢) 2.157s 3 1.08x
▲ Vercel Express 36.236s (-70.1% 🟢) 38.302s (-69.0% 🟢) 2.066s 3 1.13x

🔍 Observability: Next.js (Turbopack) | Nitro | Express

Promise.all with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 1.174s (-28.0% 🟢) 2.006s (-3.3%) 0.832s 15 1.00x
💻 Local Express 1.209s (-18.8% 🟢) 2.006s (~) 0.797s 15 1.03x
🐘 Postgres Express 1.212s (-3.9%) 2.008s (~) 0.796s 15 1.03x
🐘 Postgres Next.js (Turbopack) 1.237s 2.007s 0.770s 15 1.05x
💻 Local Next.js (Turbopack) 1.317s 2.006s 0.689s 15 1.12x
🐘 Postgres Nitro ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 2.572s (-24.3% 🟢) 4.103s (-16.8% 🟢) 1.532s 8 1.00x
▲ Vercel Express 46.045s (+1510.0% 🔺) 47.387s (+925.0% 🔺) 1.343s 7 17.90x
▲ Vercel Nitro 46.151s (+1537.6% 🔺) 47.602s (+1001.3% 🔺) 1.451s 7 17.95x

🔍 Observability: Next.js (Turbopack) | Express | Nitro

Promise.all with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 1.263s (-46.5% 🟢) 2.007s (-33.3% 🟢) 0.743s 15 1.00x
🐘 Postgres Next.js (Turbopack) 1.414s 2.074s 0.660s 15 1.12x
💻 Local Nitro 1.694s (-46.1% 🟢) 2.005s (-48.4% 🟢) 0.311s 15 1.34x
💻 Local Express 1.859s (-37.0% 🟢) 2.150s (-37.7% 🟢) 0.292s 14 1.47x
💻 Local Next.js (Turbopack) 2.050s 2.736s 0.685s 11 1.62x
🐘 Postgres Nitro ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 4.090s (+13.0% 🔺) 11.164s (+118.5% 🔺) 7.074s 4 1.00x
▲ Vercel Next.js (Turbopack) 4.196s (-40.9% 🟢) 11.799s (+32.5% 🔺) 7.602s 3 1.03x
▲ Vercel Nitro 4.886s (+20.6% 🔺) 8.736s (+47.6% 🔺) 3.850s 5 1.19x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

Promise.all with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 1.374s (-60.6% 🟢) 2.007s (-49.9% 🟢) 0.633s 15 1.00x
🐘 Postgres Next.js (Turbopack) 1.687s 2.151s 0.464s 14 1.23x
💻 Local Nitro 4.345s (-48.0% 🟢) 5.012s (-44.4% 🟢) 0.667s 6 3.16x
💻 Local Express 5.278s (-36.7% 🟢) 5.847s (-35.2% 🟢) 0.569s 6 3.84x
💻 Local Next.js (Turbopack) 5.615s 6.349s 0.733s 6 4.09x
🐘 Postgres Nitro ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 4.868s (+14.8% 🔺) 15.058s (+145.8% 🔺) 10.190s 3 1.00x
▲ Vercel Next.js (Turbopack) 6.074s (-31.9% 🟢) 12.780s (+16.6% 🔺) 6.706s 3 1.25x
▲ Vercel Nitro 6.907s (+95.9% 🔺) 11.861s (+114.3% 🔺) 4.953s 3 1.42x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

Promise.race with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 1.185s (-5.7% 🟢) 2.008s (~) 0.823s 15 1.00x
🐘 Postgres Next.js (Turbopack) 1.259s 2.008s 0.749s 15 1.06x
💻 Local Next.js (Turbopack) 1.360s 2.006s 0.646s 15 1.15x
💻 Local Nitro 1.496s (-19.8% 🟢) 2.006s (-14.3% 🟢) 0.510s 15 1.26x
💻 Local Express 1.581s (-16.5% 🟢) 2.006s (-15.1% 🟢) 0.425s 15 1.33x
🐘 Postgres Nitro ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 2.325s (-20.7% 🟢) 5.635s (+21.4% 🔺) 3.310s 6 1.00x
▲ Vercel Express 2.723s (+5.5% 🔺) 6.048s (+39.0% 🔺) 3.324s 5 1.17x
▲ Vercel Nitro 4.711s (+91.6% 🔺) 8.277s (+98.5% 🔺) 3.566s 4 2.03x

🔍 Observability: Next.js (Turbopack) | Express | Nitro

Promise.race with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 1.256s (-46.4% 🟢) 2.008s (-33.3% 🟢) 0.752s 15 1.00x
🐘 Postgres Next.js (Turbopack) 1.380s 2.007s 0.627s 15 1.10x
💻 Local Nitro 1.903s (-37.9% 🟢) 2.221s (-42.9% 🟢) 0.318s 14 1.52x
💻 Local Express 2.064s (-34.1% 🟢) 2.509s (-33.3% 🟢) 0.444s 12 1.64x
💻 Local Next.js (Turbopack) 2.118s 2.827s 0.709s 11 1.69x
🐘 Postgres Nitro ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 3.129s (-3.2%) 8.487s (+67.2% 🔺) 5.358s 4 1.00x
▲ Vercel Next.js (Turbopack) 3.401s (+8.2% 🔺) 8.589s (+89.9% 🔺) 5.187s 4 1.09x
▲ Vercel Express 3.461s (+8.4% 🔺) 9.033s (+88.5% 🔺) 5.572s 4 1.11x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

Promise.race with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 1.370s (-60.9% 🟢) 2.007s (-50.0% 🟢) 0.638s 15 1.00x
🐘 Postgres Next.js (Turbopack) 1.777s 2.151s 0.374s 14 1.30x
💻 Local Express 5.530s (-37.2% 🟢) 6.013s (-35.2% 🟢) 0.483s 5 4.04x
💻 Local Nitro 5.566s (-39.1% 🟢) 6.016s (-40.0% 🟢) 0.450s 6 4.06x
💻 Local Next.js (Turbopack) 6.213s 6.613s 0.400s 5 4.54x
🐘 Postgres Nitro ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 4.602s (-9.6% 🟢) 12.081s (+77.2% 🔺) 7.479s 3 1.00x
▲ Vercel Express 5.245s (-18.3% 🟢) 7.140s (-12.7% 🟢) 1.895s 5 1.14x
▲ Vercel Next.js (Turbopack) 158.248s (+2242.0% 🔺) 160.812s (+1782.1% 🔺) 2.564s 2 34.38x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 0.568s (-42.1% 🟢) 1.004s (-8.2% 🟢) 0.437s 60 1.00x
🐘 Postgres Express 0.569s (-32.2% 🟢) 1.006s (-1.6%) 0.437s 60 1.00x
💻 Local Express 0.622s (-36.8% 🟢) 1.039s (-3.4%) 0.418s 58 1.09x
🐘 Postgres Next.js (Turbopack) 0.807s 1.024s 0.217s 59 1.42x
💻 Local Next.js (Turbopack) 0.867s 1.021s 0.155s 59 1.53x
🐘 Postgres Nitro ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 4.631s (-68.1% 🟢) 13.234s (-17.7% 🟢) 8.603s 5 1.00x
▲ Vercel Nitro 4.676s (-78.8% 🟢) 6.555s (-72.7% 🟢) 1.879s 10 1.01x
▲ Vercel Express 4.920s (-74.1% 🟢) 6.395s (-70.0% 🟢) 1.475s 10 1.06x

🔍 Observability: Next.js (Turbopack) | 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.362s (-31.1% 🟢) 2.030s (-10.1% 🟢) 0.668s 45 1.00x
💻 Local Nitro 1.465s (-51.7% 🟢) 2.006s (-46.6% 🟢) 0.541s 45 1.08x
💻 Local Express 1.520s (-49.6% 🟢) 2.006s (-44.1% 🟢) 0.486s 45 1.12x
🐘 Postgres Next.js (Turbopack) 1.918s 2.054s 0.136s 44 1.41x
💻 Local Next.js (Turbopack) 2.106s 2.976s 0.869s 31 1.55x
🐘 Postgres Nitro ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 12.447s (-75.0% 🟢) 15.051s (-70.9% 🟢) 2.604s 7 1.00x
▲ Vercel Nitro 14.025s (-64.5% 🟢) 16.359s (-60.4% 🟢) 2.333s 6 1.13x
▲ Vercel Express 15.482s (-55.2% 🟢) 18.764s (-49.0% 🟢) 3.282s 5 1.24x

🔍 Observability: Next.js (Turbopack) | 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.706s (-32.2% 🟢) 3.083s (-29.4% 🟢) 0.377s 40 1.00x
💻 Local Nitro 3.186s (-65.7% 🟢) 3.852s (-61.6% 🟢) 0.666s 32 1.18x
💻 Local Express 3.231s (-64.9% 🟢) 4.009s (-60.0% 🟢) 0.777s 30 1.19x
🐘 Postgres Next.js (Turbopack) 3.805s 4.077s 0.272s 30 1.41x
💻 Local Next.js (Turbopack) 4.299s 5.010s 0.711s 24 1.59x
🐘 Postgres Nitro ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 24.628s (-81.1% 🟢) 30.145s (-77.2% 🟢) 5.517s 4 1.00x
▲ Vercel Nitro 24.635s (-74.6% 🟢) 29.732s (-69.8% 🟢) 5.096s 5 1.00x
▲ Vercel Next.js (Turbopack) 25.826s (-75.9% 🟢) 29.982s (-72.5% 🟢) 4.156s 5 1.05x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 0.220s (-22.2% 🟢) 1.006s (~) 0.786s 60 1.00x
🐘 Postgres Next.js (Turbopack) 0.270s 1.006s 0.737s 60 1.23x
💻 Local Express 0.430s (-23.3% 🟢) 1.004s (~) 0.575s 60 1.96x
💻 Local Nitro 0.434s (-28.3% 🟢) 1.004s (-1.7%) 0.571s 60 1.97x
💻 Local Next.js (Turbopack) 0.602s 1.022s 0.420s 59 2.74x
🐘 Postgres Nitro ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 2.643s (+59.1% 🔺) 7.581s (+126.2% 🔺) 4.938s 8 1.00x
▲ Vercel Express 36.107s (+1747.6% 🔺) 40.124s (+1003.2% 🔺) 4.017s 9 13.66x
▲ Vercel Next.js (Turbopack) 52.947s (+2517.9% 🔺) 58.043s (+1430.1% 🔺) 5.096s 6 20.03x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 0.344s (-32.6% 🟢) 1.006s (~) 0.663s 90 1.00x
🐘 Postgres Next.js (Turbopack) 0.478s 1.006s 0.528s 90 1.39x
💻 Local Nitro 2.122s (-16.4% 🟢) 2.685s (-10.8% 🟢) 0.563s 34 6.18x
💻 Local Express 2.135s (-15.0% 🟢) 2.685s (-10.8% 🟢) 0.550s 34 6.22x
💻 Local Next.js (Turbopack) 2.407s 3.045s 0.638s 30 7.01x
🐘 Postgres Nitro ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 4.883s (+51.4% 🔺) 10.713s (+122.2% 🔺) 5.830s 9 1.00x
▲ Vercel Express 4.910s (+61.2% 🔺) 8.939s (+86.0% 🔺) 4.029s 11 1.01x
▲ Vercel Next.js (Turbopack) 5.588s (+58.1% 🔺) 10.760s (+107.2% 🔺) 5.172s 9 1.14x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 0.695s (-15.1% 🟢) 1.015s (~) 0.320s 119 1.00x
🐘 Postgres Next.js (Turbopack) 0.969s 1.540s 0.571s 79 1.39x
💻 Local Nitro 9.292s (-17.0% 🟢) 9.952s (-14.7% 🟢) 0.660s 13 13.36x
💻 Local Express 9.656s (-13.7% 🟢) 10.196s (-14.6% 🟢) 0.540s 12 13.89x
💻 Local Next.js (Turbopack) 10.588s 11.391s 0.804s 11 15.22x
🐘 Postgres Nitro ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 13.516s (+30.9% 🔺) 16.288s (+32.6% 🔺) 2.773s 8 1.00x
▲ Vercel Express 16.108s (+117.1% 🔺) 20.674s (+123.6% 🔺) 4.565s 6 1.19x
▲ Vercel Nitro 313.959s (+3965.4% 🔺) 317.417s (+3276.6% 🔺) 3.458s 1 23.23x

🔍 Observability: Next.js (Turbopack) | Express | Nitro

Stream Benchmarks (includes TTFB metrics)
workflow with stream

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 1.153s (+439.5% 🔺) 2.005s (+99.6% 🔺) 0.011s (-16.0% 🟢) 2.018s (+98.0% 🔺) 0.865s 10 1.00x
💻 Local Express 1.163s (+484.3% 🔺) 2.005s (+99.6% 🔺) 0.012s (-3.3%) 2.019s (+98.3% 🔺) 0.856s 10 1.01x
🐘 Postgres Express 1.184s (+477.3% 🔺) 2.000s (+100.3% 🔺) 0.002s (-6.3% 🟢) 2.011s (+98.9% 🔺) 0.827s 10 1.03x
💻 Local Next.js (Turbopack) 1.209s 2.004s 0.013s 2.020s 0.811s 10 1.05x
🐘 Postgres Next.js (Turbopack) 1.225s 2.002s 0.001s 2.011s 0.786s 10 1.06x
🐘 Postgres Nitro ⚠️ missing - - - - -

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 2.147s (-44.0% 🟢) 3.455s (-34.5% 🟢) 1.302s (+75.4% 🔺) 5.210s (-19.6% 🟢) 3.063s 10 1.00x
▲ Vercel Express 2.319s (-7.4% 🟢) 3.167s (-22.6% 🟢) 1.730s (+80.0% 🔺) 5.477s (-2.0%) 3.158s 10 1.08x
▲ Vercel Next.js (Turbopack) 2.344s (-65.8% 🟢) 3.421s (-60.5% 🟢) 1.537s (+143.2% 🔺) 5.492s (-43.9% 🟢) 3.148s 10 1.09x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

stream pipeline with 5 transform steps (1MB)

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 1.580s (+150.7% 🔺) 2.008s (+99.5% 🔺) 0.004s (+2.7%) 2.027s (+98.1% 🔺) 0.447s 30 1.00x
💻 Local Express 1.589s (+109.9% 🔺) 2.010s (+95.4% 🔺) 0.011s (+13.0% 🔺) 2.023s (+94.5% 🔺) 0.433s 30 1.01x
🐘 Postgres Next.js (Turbopack) 1.734s 2.010s 0.004s 2.026s 0.292s 30 1.10x
💻 Local Next.js (Turbopack) 1.734s 2.008s 0.011s 2.021s 0.287s 30 1.10x
💻 Local Nitro 1.736s (+107.0% 🔺) 2.009s (+98.5% 🔺) 0.009s (-7.3% 🟢) 2.192s (+96.5% 🔺) 0.456s 29 1.10x
🐘 Postgres Nitro ⚠️ missing - - - - -

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 5.855s (-80.1% 🟢) 10.617s (-65.5% 🟢) 0.187s (+67.1% 🔺) 13.218s (-58.4% 🟢) 7.363s 5 1.00x
▲ Vercel Express 5.996s (-7.8% 🟢) 8.099s (+1.1%) 0.129s (-68.4% 🟢) 8.639s (-2.2%) 2.643s 7 1.02x
▲ 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.750s (-21.9% 🟢) 1.046s (-18.1% 🟢) 0.000s (-19.3% 🟢) 1.061s (-18.8% 🟢) 0.311s 57 1.00x
🐘 Postgres Next.js (Turbopack) 0.824s 1.072s 0.000s 1.083s 0.259s 56 1.10x
💻 Local Nitro 1.351s (+10.5% 🔺) 2.014s (~) 0.001s (+466.7% 🔺) 2.016s (~) 0.665s 30 1.80x
💻 Local Express 1.400s (+14.3% 🔺) 2.013s (~) 0.000s (+30.0% 🔺) 2.015s (~) 0.615s 30 1.87x
💻 Local Next.js (Turbopack) 1.475s 2.013s 0.001s 2.017s 0.541s 30 1.97x
🐘 Postgres Nitro ⚠️ missing - - - - -

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 3.353s (-10.4% 🟢) 8.410s (+64.8% 🔺) 0.000s (-100.0% 🟢) 10.373s (+87.6% 🔺) 7.020s 6 1.00x
▲ Vercel Nitro 3.675s (+20.5% 🔺) 8.704s (+98.1% 🔺) 0.000s (+62.5% 🔺) 9.213s (+91.6% 🔺) 5.538s 8 1.10x
▲ Vercel Next.js (Turbopack) 3.721s (-63.5% 🟢) 8.328s (-27.7% 🟢) 0.000s (+Infinity% 🔺) 8.892s (-26.2% 🟢) 5.172s 7 1.11x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

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.458s (-17.7% 🟢) 2.136s (-1.9%) 0.000s (NaN%) 2.190s (~) 0.732s 28 1.00x
🐘 Postgres Next.js (Turbopack) 1.645s 2.180s 0.000s 2.192s 0.546s 28 1.13x
💻 Local Next.js (Turbopack) 2.956s 3.525s 0.001s 3.530s 0.574s 18 2.03x
💻 Local Nitro 3.030s (-10.5% 🟢) 3.776s (-6.3% 🟢) 0.001s (+17.2% 🔺) 3.781s (-6.3% 🟢) 0.751s 16 2.08x
💻 Local Express 3.417s (-1.5%) 3.827s (-5.1% 🟢) 0.001s (+16.7% 🔺) 4.164s (+3.2%) 0.747s 15 2.34x
🐘 Postgres Nitro ⚠️ missing - - - - -

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 5.538s (-1.4%) 11.602s (+66.2% 🔺) 0.000s (-100.0% 🟢) 12.100s (+60.5% 🔺) 6.561s 5 1.00x
▲ Vercel Express 5.783s (+26.1% 🔺) 6.834s (+13.5% 🔺) 0.002s (+Infinity% 🔺) 7.296s (+13.0% 🔺) 1.513s 9 1.04x
▲ Vercel Nitro 6.478s (+58.2% 🔺) 9.249s (+72.1% 🔺) 0.000s (-38.9% 🟢) 10.417s (+79.8% 🔺) 3.939s 6 1.17x

🔍 Observability: Next.js (Turbopack) | Express | Nitro

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World 🥇 Fastest Framework Wins
💻 Local Nitro 15/21
🐘 Postgres Express 21/21
▲ Vercel Next.js (Turbopack) 8/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework 🥇 Fastest World Wins
Express 🐘 Postgres 14/21
Next.js (Turbopack) 🐘 Postgres 15/21
Nitro 💻 Local 20/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: failure
  • Vercel: success

Check the workflow run for details.

@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 1264 2 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 7181 2 1052 8235

❌ Failed Tests

▲ Vercel Production (2 failed)

fastify (2 failed):

  • outputStreamWorkflow positive startIndex (skips first chunk)
  • fibonacciWorkflow - recursive workflow composition via start() | wrun_01KSYNM0CK6C3YK145JA8JDJJA | 🔍 observability

Details by Category

❌ ▲ Vercel Production
App Passed Failed Skipped
✅ astro 109 0 26
✅ example 109 0 26
✅ express 109 0 26
❌ fastify 107 2 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


Some E2E test jobs failed:

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

Check the workflow run for details.

Comment thread .changeset/spotty-pagination-progress.md Outdated
Signed-off-by: Peter Wielander <mittgfu@gmail.com>
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