Skip to content

[core] Combine initial run fetch, event fetch, and run_started event creation#1569

Open
VaguelySerious wants to merge 2 commits intomainfrom
peter/skip-runs-get
Open

[core] Combine initial run fetch, event fetch, and run_started event creation#1569
VaguelySerious wants to merge 2 commits intomainfrom
peter/skip-runs-get

Conversation

@VaguelySerious
Copy link
Copy Markdown
Member

@VaguelySerious VaguelySerious commented Mar 31, 2026

This PR extracts some of the safer performance improvements originally added as part of #1537

…creation

Signed-off-by: Peter Wielander <mittgfu@gmail.com>
@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Mar 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 Apr 1, 2026 3:35pm
example-nextjs-workflow-webpack Ready Ready Preview, Comment Apr 1, 2026 3:35pm
example-workflow Ready Ready Preview, Comment Apr 1, 2026 3:35pm
workbench-astro-workflow Ready Ready Preview, Comment Apr 1, 2026 3:35pm
workbench-express-workflow Ready Ready Preview, Comment Apr 1, 2026 3:35pm
workbench-fastify-workflow Ready Ready Preview, Comment Apr 1, 2026 3:35pm
workbench-hono-workflow Ready Ready Preview, Comment Apr 1, 2026 3:35pm
workbench-nitro-workflow Ready Ready Preview, Comment Apr 1, 2026 3:35pm
workbench-nuxt-workflow Ready Ready Preview, Comment Apr 1, 2026 3:35pm
workbench-sveltekit-workflow Ready Ready Preview, Comment Apr 1, 2026 3:35pm
workbench-vite-workflow Ready Ready Preview, Comment Apr 1, 2026 3:35pm
workflow-docs Ready Ready Preview, Comment, Open in v0 Apr 1, 2026 3:35pm
workflow-swc-playground Ready Ready Preview, Comment Apr 1, 2026 3:35pm

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 31, 2026

🦋 Changeset detected

Latest commit: 42ffc92

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

This PR includes changesets to release 20 packages
Name Type
@workflow/world Patch
@workflow/core Patch
@workflow/world-local Patch
@workflow/world-postgres Patch
@workflow/cli Patch
@workflow/vitest Patch
@workflow/web-shared Patch
@workflow/world-testing Patch
@workflow/world-vercel Patch
@workflow/builders Patch
@workflow/next Patch
@workflow/nitro Patch
workflow Patch
@workflow/astro Patch
@workflow/nest Patch
@workflow/rollup Patch
@workflow/sveltekit Patch
@workflow/vite Patch
@workflow/nuxt Patch
@workflow/ai 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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 31, 2026

🧪 E2E Test Results

Some tests failed

Summary

Passed Failed Skipped Total
✅ ▲ Vercel Production 857 0 67 924
✅ 💻 Local Development 830 0 178 1008
✅ 📦 Local Production 830 0 178 1008
✅ 🐘 Local Postgres 830 0 178 1008
✅ 🪟 Windows 76 0 8 84
❌ 🌍 Community Worlds 133 59 24 216
✅ 📋 Other 210 0 42 252
Total 3766 59 675 4500

❌ Failed Tests

🌍 Community Worlds (59 failed)

mongodb (2 failed):

  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KN4TZAHTQQKXEQMHSNW67ZN6
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KN4V7NKF2SY1C5HCMD397ZAR

redis (2 failed):

  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KN4TZAHTQQKXEQMHSNW67ZN6
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KN4V7NKF2SY1C5HCMD397ZAR

turso (55 failed):

  • addTenWorkflow | wrun_01KN4TY0X5375T16FM4Q6CY143
  • addTenWorkflow | wrun_01KN4TY0X5375T16FM4Q6CY143
  • wellKnownAgentWorkflow (.well-known/agent) | wrun_01KN4TZ9K97J0ZZDSWTEBEJ6EK
  • should work with react rendering in step
  • promiseAllWorkflow | wrun_01KN4TY9BSEPM9R37PA4QKQR6W
  • promiseRaceWorkflow | wrun_01KN4TYF6A99E6846TYHK0A907
  • promiseAnyWorkflow | wrun_01KN4TYJMJZH2S3XFVQ7HH00N8
  • importedStepOnlyWorkflow | wrun_01KN4TZQE3BF4PDFHN46W2GHAV
  • hookWorkflow | wrun_01KN4TYYZ4Z8V7K7QCMATCC7P1
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KN4TZAHTQQKXEQMHSNW67ZN6
  • webhookWorkflow | wrun_01KN4TZKWDVY5EDYCABKVHQ29X
  • sleepingWorkflow | wrun_01KN4TZT91YVF6JG4XB6VW07D4
  • parallelSleepWorkflow | wrun_01KN4V088R4GTNZ5CV7FSWD60A
  • nullByteWorkflow | wrun_01KN4V0BQVYEBCZ07HAP6E11XP
  • workflowAndStepMetadataWorkflow | wrun_01KN4V0E78ADH1R57GXTRFD73X
  • fetchWorkflow | wrun_01KN4V3AZSCEX39KXW0HQV1JTT
  • promiseRaceStressTestWorkflow | wrun_01KN4V3EK2CBW6JQPW5P8H65C8
  • error handling error propagation workflow errors nested function calls preserve message and stack trace
  • error handling error propagation workflow errors cross-file imports preserve message and stack trace
  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack
  • error handling retry behavior regular Error retries until success
  • error handling retry behavior FatalError fails immediately without retries
  • error handling retry behavior RetryableError respects custom retryAfter delay
  • error handling retry behavior maxRetries=0 disables retries
  • error handling catchability FatalError can be caught and detected with FatalError.is()
  • error handling not registered WorkflowNotRegisteredError fails the run when workflow does not exist
  • error handling not registered StepNotRegisteredError fails the step but workflow can catch it
  • error handling not registered StepNotRegisteredError fails the run when not caught in workflow
  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_01KN4V6ZXDMW5ZYC08XQ7RPA8F
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KN4V7NKF2SY1C5HCMD397ZAR
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KN4V8BR9YQ17320ZP436R7Y9
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KN4V90B0BH5NN6YSDQTTWQ6Z
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_01KN4V99H236SXFAY6NP6S6ZAA
  • closureVariableWorkflow - nested step functions with closure variables | wrun_01KN4V9G6R5Q7C64SZF0H9QZFR
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_01KN4V9JNFQ7X5GJ6WC7N9G8SR
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_01KN4VA2TYPKQEHS871PV0YSR2
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_01KN4VA8VT18ATSWFWWFA1EJD9
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_01KN4VAFQ7BEQH4DV5CEQP47MZ
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_01KN4VAPKJYAP24GJ1FVNX9FT5
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_01KN4VAXDQTXX8EQDM750ZBDDR
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_01KN4VB55AJPE1NYWVDKVFVYC0
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_01KN4VBC2YNJ5FKBF1R6G7YWPG
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_01KN4VBQFS8ZV0GBJKQ2YVPFBT
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_01KN4VC12RWF8JB9C63JC1C8XK
  • cancelRun - cancelling a running workflow | wrun_01KN4VC85P3S5VAAWG4ZV6FEPS
  • cancelRun via CLI - cancelling a running workflow | wrun_01KN4VCHHY43MGG16RZACEYPRX
  • pages router addTenWorkflow via pages router
  • pages router promiseAllWorkflow via pages router
  • pages router sleepingWorkflow via pages router
  • hookWithSleepWorkflow - hook payloads delivered correctly with concurrent sleep | wrun_01KN4VCY865F63EJ8BC25EJJ7A
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KN4VDK2XGS09C48QCW200A4R
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KN4VDZ1PX4RPG14K8QXRF7N4
  • importMetaUrlWorkflow - import.meta.url is available in step bundles | wrun_01KN4VE6664F6VKY9B8QN6R9J0

Details by Category

✅ ▲ Vercel Production
App Passed Failed Skipped
✅ astro 77 0 7
✅ example 77 0 7
✅ express 77 0 7
✅ fastify 77 0 7
✅ hono 77 0 7
✅ nextjs-turbopack 82 0 2
✅ nextjs-webpack 82 0 2
✅ nitro 77 0 7
✅ nuxt 77 0 7
✅ sveltekit 77 0 7
✅ vite 77 0 7
✅ 💻 Local Development
App Passed Failed Skipped
✅ astro-stable 70 0 14
✅ express-stable 70 0 14
✅ fastify-stable 70 0 14
✅ hono-stable 70 0 14
✅ nextjs-turbopack-canary 59 0 25
✅ nextjs-turbopack-stable 76 0 8
✅ nextjs-webpack-canary 59 0 25
✅ nextjs-webpack-stable 76 0 8
✅ nitro-stable 70 0 14
✅ nuxt-stable 70 0 14
✅ sveltekit-stable 70 0 14
✅ vite-stable 70 0 14
✅ 📦 Local Production
App Passed Failed Skipped
✅ astro-stable 70 0 14
✅ express-stable 70 0 14
✅ fastify-stable 70 0 14
✅ hono-stable 70 0 14
✅ nextjs-turbopack-canary 59 0 25
✅ nextjs-turbopack-stable 76 0 8
✅ nextjs-webpack-canary 59 0 25
✅ nextjs-webpack-stable 76 0 8
✅ nitro-stable 70 0 14
✅ nuxt-stable 70 0 14
✅ sveltekit-stable 70 0 14
✅ vite-stable 70 0 14
✅ 🐘 Local Postgres
App Passed Failed Skipped
✅ astro-stable 70 0 14
✅ express-stable 70 0 14
✅ fastify-stable 70 0 14
✅ hono-stable 70 0 14
✅ nextjs-turbopack-canary 59 0 25
✅ nextjs-turbopack-stable 76 0 8
✅ nextjs-webpack-canary 59 0 25
✅ nextjs-webpack-stable 76 0 8
✅ nitro-stable 70 0 14
✅ nuxt-stable 70 0 14
✅ sveltekit-stable 70 0 14
✅ vite-stable 70 0 14
✅ 🪟 Windows
App Passed Failed Skipped
✅ nextjs-turbopack 76 0 8
❌ 🌍 Community Worlds
App Passed Failed Skipped
✅ mongodb-dev 5 0 0
❌ mongodb 57 2 8
✅ redis-dev 5 0 0
❌ redis 57 2 8
✅ turso-dev 5 0 0
❌ turso 4 55 8
✅ 📋 Other
App Passed Failed Skipped
✅ e2e-local-dev-nest-stable 70 0 14
✅ e2e-local-postgres-nest-stable 70 0 14
✅ e2e-local-prod-nest-stable 70 0 14

📋 View full workflow run

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 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 (-7.8% 🟢) 1.005s (~) 0.963s 10 1.00x
💻 Local Next.js (Turbopack) 0.044s (-15.6% 🟢) 1.005s (~) 0.961s 10 1.06x
💻 Local Nitro 0.046s (+3.4%) 1.006s (~) 0.960s 10 1.10x
🌐 Redis Next.js (Turbopack) 0.057s (+28.7% 🔺) 1.005s (~) 0.948s 10 1.37x
🐘 Postgres Express 0.060s (-13.5% 🟢) 1.012s (~) 0.952s 10 1.44x
🐘 Postgres Next.js (Turbopack) 0.060s (-10.6% 🟢) 1.011s (~) 0.952s 10 1.44x
🐘 Postgres Nitro 0.060s (-13.6% 🟢) 1.012s (~) 0.952s 10 1.45x
🌐 MongoDB Next.js (Turbopack) 0.107s (-15.2% 🟢) 1.008s (~) 0.901s 10 2.57x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 0.447s (-11.2% 🟢) 2.472s (-8.2% 🟢) 2.025s 10 1.00x
▲ Vercel Next.js (Turbopack) 0.577s (-2.8%) 2.705s (+9.8% 🔺) 2.129s 10 1.29x
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Next.js (Turbopack) 1.114s (~) 2.007s (~) 0.893s 10 1.00x
💻 Local Express 1.124s (~) 2.006s (~) 0.882s 10 1.01x
🌐 Redis Next.js (Turbopack) 1.125s (+1.2%) 2.007s (~) 0.881s 10 1.01x
💻 Local Nitro 1.137s (~) 2.006s (~) 0.870s 10 1.02x
🐘 Postgres Next.js (Turbopack) 1.139s (~) 2.010s (~) 0.871s 10 1.02x
🐘 Postgres Nitro 1.149s (~) 2.009s (~) 0.860s 10 1.03x
🐘 Postgres Express 1.150s (~) 2.012s (~) 0.862s 10 1.03x
🌐 MongoDB Next.js (Turbopack) 1.312s (-1.0%) 2.009s (~) 0.698s 10 1.18x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.135s (-5.7% 🟢) 3.663s (-7.4% 🟢) 1.527s 10 1.00x
▲ Vercel Next.js (Turbopack) 2.204s (+5.3% 🔺) 3.972s (+1.8%) 1.768s 10 1.03x
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express | Next.js (Turbopack)

workflow with 10 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Next.js (Turbopack) 10.695s (-1.1%) 11.025s (~) 0.330s 3 1.00x
🌐 Redis Next.js (Turbopack) 10.742s (+1.4%) 11.023s (~) 0.282s 3 1.00x
🐘 Postgres Next.js (Turbopack) 10.846s (-0.8%) 11.025s (~) 0.179s 3 1.01x
🐘 Postgres Nitro 10.866s (-0.5%) 11.023s (~) 0.157s 3 1.02x
💻 Local Express 10.915s (~) 11.023s (~) 0.109s 3 1.02x
💻 Local Nitro 10.944s (+0.5%) 11.024s (~) 0.081s 3 1.02x
🐘 Postgres Express 10.963s (~) 11.025s (~) 0.062s 3 1.03x
🌐 MongoDB Next.js (Turbopack) 12.175s (-0.8%) 13.026s (~) 0.851s 3 1.14x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 17.199s (-1.9%) 19.147s (-2.6%) 1.948s 2 1.00x
▲ Vercel Next.js (Turbopack) 17.474s (+2.3%) 18.879s (-1.3%) 1.405s 2 1.02x
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express | Next.js (Turbopack)

workflow with 25 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 14.232s (+2.5%) 15.029s (+5.6% 🔺) 0.797s 4 1.00x
💻 Local Next.js (Turbopack) 14.299s (-2.4%) 15.031s (~) 0.732s 4 1.00x
🐘 Postgres Next.js (Turbopack) 14.451s (~) 15.021s (~) 0.570s 4 1.02x
🐘 Postgres Nitro 14.525s (-0.6%) 15.024s (~) 0.499s 4 1.02x
🐘 Postgres Express 14.527s (-0.5%) 15.028s (~) 0.501s 4 1.02x
💻 Local Express 14.995s (~) 15.280s (+1.7%) 0.284s 4 1.05x
💻 Local Nitro 15.085s (+0.6%) 16.032s (+6.7% 🔺) 0.947s 4 1.06x
🌐 MongoDB Next.js (Turbopack) 17.865s (~) 18.025s (~) 0.160s 4 1.26x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 32.065s (-8.4% 🟢) 33.418s (-9.3% 🟢) 1.353s 2 1.00x
▲ Vercel Next.js (Turbopack) 34.571s (+4.3%) 35.995s (+2.7%) 1.424s 2 1.08x
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express | Next.js (Turbopack)

workflow with 50 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 13.407s (+6.3% 🔺) 14.027s (+7.7% 🔺) 0.620s 7 1.00x
🐘 Postgres Next.js (Turbopack) 13.937s (~) 14.312s (+1.0%) 0.375s 7 1.04x
🐘 Postgres Express 14.067s (-2.3%) 14.737s (-1.9%) 0.670s 7 1.05x
🐘 Postgres Nitro 14.068s (~) 14.598s (-0.9%) 0.531s 7 1.05x
💻 Local Next.js (Turbopack) 15.159s (-6.8% 🟢) 16.031s (-5.9% 🟢) 0.871s 6 1.13x
💻 Local Express 16.742s (+0.7%) 17.031s (~) 0.289s 6 1.25x
💻 Local Nitro 16.852s (+1.8%) 17.031s (~) 0.178s 6 1.26x
🌐 MongoDB Next.js (Turbopack) 20.441s (~) 21.032s (~) 0.591s 5 1.52x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 54.453s (-3.0%) 56.249s (-3.3%) 1.796s 2 1.00x
▲ Vercel Next.js (Turbopack) 59.026s (-1.4%) 60.907s (-1.1%) 1.881s 2 1.08x
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express | Next.js (Turbopack)

Promise.all with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Next.js (Turbopack) 1.241s (~) 2.011s (~) 0.770s 15 1.00x
🐘 Postgres Express 1.255s (-1.5%) 2.012s (~) 0.757s 15 1.01x
🐘 Postgres Nitro 1.269s (~) 2.011s (~) 0.742s 15 1.02x
🌐 Redis Next.js (Turbopack) 1.295s (+5.8% 🔺) 2.006s (~) 0.712s 15 1.04x
💻 Local Express 1.522s (-1.2%) 2.007s (~) 0.485s 15 1.23x
💻 Local Next.js (Turbopack) 1.524s (-3.1%) 2.006s (~) 0.482s 15 1.23x
💻 Local Nitro 1.554s (+1.3%) 2.007s (~) 0.453s 15 1.25x
🌐 MongoDB Next.js (Turbopack) 2.992s (+38.5% 🔺) 3.454s (+14.8% 🔺) 0.462s 9 2.41x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 2.846s (+9.4% 🔺) 4.410s (+8.6% 🔺) 1.563s 7 1.00x
▲ Vercel Express 3.026s (+16.8% 🔺) 4.519s (+0.8%) 1.493s 7 1.06x
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Next.js (Turbopack) | Express

Promise.all with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 2.343s (~) 3.010s (~) 0.667s 10 1.00x
🐘 Postgres Express 2.344s (-1.0%) 3.010s (~) 0.667s 10 1.00x
🐘 Postgres Next.js (Turbopack) 2.377s (-2.7%) 3.011s (~) 0.634s 10 1.01x
🌐 Redis Next.js (Turbopack) 2.536s (+5.4% 🔺) 3.008s (~) 0.472s 10 1.08x
💻 Local Next.js (Turbopack) 2.704s (-3.5%) 3.008s (-12.9% 🟢) 0.303s 10 1.15x
💻 Local Express 3.006s (+2.7%) 3.455s (+14.8% 🔺) 0.448s 9 1.28x
💻 Local Nitro 3.122s (+5.3% 🔺) 4.010s (+16.1% 🔺) 0.889s 8 1.33x
🌐 MongoDB Next.js (Turbopack) 9.486s (+99.2% 🔺) 10.019s (+93.5% 🔺) 0.533s 3 4.05x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 3.276s (+24.6% 🔺) 4.969s (+13.9% 🔺) 1.693s 7 1.00x
▲ Vercel Next.js (Turbopack) 3.630s (~) 5.086s (~) 1.456s 6 1.11x
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express | Next.js (Turbopack)

Promise.all with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 3.459s (-0.5%) 4.012s (~) 0.552s 8 1.00x
🐘 Postgres Express 3.460s (-0.9%) 4.012s (~) 0.552s 8 1.00x
🐘 Postgres Next.js (Turbopack) 3.642s (~) 4.012s (~) 0.369s 8 1.05x
🌐 Redis Next.js (Turbopack) 4.178s (+6.9% 🔺) 4.869s (+17.8% 🔺) 0.691s 7 1.21x
💻 Local Next.js (Turbopack) 6.729s (-13.9% 🟢) 7.420s (-12.9% 🟢) 0.691s 5 1.95x
💻 Local Nitro 8.403s (+4.6%) 9.024s (+5.9% 🔺) 0.621s 4 2.43x
💻 Local Express 8.611s (+5.5% 🔺) 9.024s (~) 0.413s 4 2.49x
🌐 MongoDB Next.js (Turbopack) 19.706s (+95.9% 🔺) 20.520s (+92.1% 🔺) 0.814s 2 5.70x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 3.655s (-4.4%) 5.495s (-6.1% 🟢) 1.839s 6 1.00x
▲ Vercel Express 3.773s (+3.2%) 5.458s (-4.0%) 1.685s 6 1.03x
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Next.js (Turbopack) | Express

Promise.race with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Next.js (Turbopack) 1.216s (-1.5%) 2.010s (~) 0.794s 15 1.00x
🐘 Postgres Nitro 1.247s (-1.7%) 2.010s (~) 0.764s 15 1.03x
🐘 Postgres Express 1.249s (~) 2.009s (~) 0.760s 15 1.03x
🌐 Redis Next.js (Turbopack) 1.303s (+5.8% 🔺) 2.006s (~) 0.703s 15 1.07x
💻 Local Next.js (Turbopack) 1.519s (+0.9%) 2.007s (~) 0.488s 15 1.25x
💻 Local Nitro 1.527s (-3.1%) 2.005s (~) 0.479s 15 1.26x
💻 Local Express 1.575s (+1.2%) 2.073s (+3.4%) 0.499s 15 1.30x
🌐 MongoDB Next.js (Turbopack) 3.240s (+50.1% 🔺) 3.885s (+29.1% 🔺) 0.645s 8 2.66x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.246s (-3.2%) 3.901s (-2.7%) 1.655s 8 1.00x
▲ Vercel Next.js (Turbopack) 2.761s (+16.6% 🔺) 4.228s (+6.0% 🔺) 1.467s 8 1.23x
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express | Next.js (Turbopack)

Promise.race with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 2.371s (+2.3%) 3.012s (~) 0.641s 10 1.00x
🐘 Postgres Next.js (Turbopack) 2.377s (-0.8%) 3.010s (~) 0.633s 10 1.00x
🐘 Postgres Nitro 2.379s (+0.9%) 3.012s (~) 0.632s 10 1.00x
🌐 Redis Next.js (Turbopack) 2.573s (+6.6% 🔺) 3.008s (~) 0.435s 10 1.09x
💻 Local Next.js (Turbopack) 2.872s (-5.3% 🟢) 3.309s (-4.2%) 0.437s 10 1.21x
💻 Local Express 2.937s (-5.9% 🟢) 3.760s (-3.3%) 0.823s 8 1.24x
💻 Local Nitro 3.325s (+9.1% 🔺) 4.135s (+6.5% 🔺) 0.810s 8 1.40x
🌐 MongoDB Next.js (Turbopack) 9.603s (+101.6% 🔺) 10.016s (+93.5% 🔺) 0.413s 3 4.05x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.634s (-9.9% 🟢) 4.110s (-9.5% 🟢) 1.476s 8 1.00x
▲ Vercel Next.js (Turbopack) 2.910s (-6.5% 🟢) 4.721s (+1.0%) 1.811s 7 1.10x
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express | Next.js (Turbopack)

Promise.race with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 3.472s (~) 4.013s (~) 0.541s 8 1.00x
🐘 Postgres Nitro 3.483s (~) 4.011s (~) 0.528s 8 1.00x
🐘 Postgres Next.js (Turbopack) 3.648s (-1.1%) 4.013s (~) 0.365s 8 1.05x
🌐 Redis Next.js (Turbopack) 4.143s (+5.8% 🔺) 5.011s (+12.9% 🔺) 0.868s 6 1.19x
💻 Local Next.js (Turbopack) 7.176s (-13.1% 🟢) 7.767s (-8.8% 🟢) 0.592s 4 2.07x
💻 Local Express 8.942s (+1.0%) 9.272s (~) 0.330s 4 2.58x
💻 Local Nitro 10.005s (+16.1% 🔺) 10.356s (+14.8% 🔺) 0.351s 3 2.88x
🌐 MongoDB Next.js (Turbopack) 19.400s (+93.0% 🔺) 20.030s (+87.5% 🔺) 0.630s 2 5.59x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 3.380s (+14.6% 🔺) 4.926s (+10.4% 🔺) 1.546s 7 1.00x
▲ Vercel Next.js (Turbopack) 3.882s (+2.2%) 5.781s (+1.6%) 1.899s 6 1.15x
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express | Next.js (Turbopack)

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 0.702s (+22.5% 🔺) 1.005s (-1.6%) 0.303s 60 1.00x
💻 Local Next.js (Turbopack) 0.762s (-10.7% 🟢) 1.021s (~) 0.260s 59 1.09x
🐘 Postgres Next.js (Turbopack) 0.772s (-4.3%) 1.007s (~) 0.235s 60 1.10x
🐘 Postgres Nitro 0.835s (-1.2%) 1.008s (~) 0.173s 60 1.19x
🐘 Postgres Express 0.853s (+1.4%) 1.024s (+1.7%) 0.171s 59 1.22x
💻 Local Express 0.992s (+1.0%) 1.281s (+8.5% 🔺) 0.289s 47 1.41x
💻 Local Nitro 0.993s (~) 1.282s (+8.6% 🔺) 0.289s 47 1.42x
🌐 MongoDB Next.js (Turbopack) 2.151s (+0.7%) 3.009s (~) 0.858s 20 3.07x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 10.002s (-12.3% 🟢) 11.702s (-12.8% 🟢) 1.701s 6 1.00x
▲ Vercel Express 10.371s (+3.3%) 12.103s (~) 1.732s 5 1.04x
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Next.js (Turbopack) | Express

workflow with 25 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 1.723s (+33.0% 🔺) 2.006s (~) 0.283s 45 1.00x
🐘 Postgres Next.js (Turbopack) 1.885s (-4.3%) 2.031s (-10.1% 🟢) 0.146s 45 1.09x
🐘 Postgres Nitro 1.962s (-3.4%) 2.317s (-14.7% 🟢) 0.354s 39 1.14x
🐘 Postgres Express 1.994s (-1.3%) 2.442s (-7.5% 🟢) 0.448s 37 1.16x
💻 Local Next.js (Turbopack) 2.405s (-11.7% 🟢) 3.008s (-1.1%) 0.603s 30 1.40x
💻 Local Express 3.037s (~) 3.759s (+4.8%) 0.722s 24 1.76x
💻 Local Nitro 3.049s (+1.1%) 3.649s (+1.1%) 0.600s 25 1.77x
🌐 MongoDB Next.js (Turbopack) 5.345s (+2.5%) 6.015s (~) 0.670s 15 3.10x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 31.095s (-8.4% 🟢) 33.025s (-7.3% 🟢) 1.930s 3 1.00x
▲ Vercel Next.js (Turbopack) 31.150s (-9.3% 🟢) 33.297s (-7.6% 🟢) 2.147s 3 1.00x
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express | Next.js (Turbopack)

workflow with 50 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 3.384s (+29.2% 🔺) 4.008s (+31.1% 🔺) 0.624s 30 1.00x
🐘 Postgres Next.js (Turbopack) 3.849s (-2.1%) 4.044s (-4.9%) 0.195s 30 1.14x
🐘 Postgres Nitro 4.009s (-2.3%) 4.403s (-8.5% 🟢) 0.394s 28 1.18x
🐘 Postgres Express 4.033s (-2.2%) 4.607s (-5.1% 🟢) 0.574s 27 1.19x
💻 Local Next.js (Turbopack) 7.708s (-11.7% 🟢) 8.217s (-8.9% 🟢) 0.509s 15 2.28x
💻 Local Express 9.254s (+0.6%) 10.019s (~) 0.765s 12 2.73x
💻 Local Nitro 9.333s (+1.9%) 10.019s (+2.4%) 0.686s 12 2.76x
🌐 MongoDB Next.js (Turbopack) 10.804s (+0.5%) 11.111s (~) 0.307s 11 3.19x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 76.659s (-11.4% 🟢) 78.788s (-11.0% 🟢) 2.129s 2 1.00x
▲ Vercel Next.js (Turbopack) 81.659s (-11.3% 🟢) 83.621s (-10.9% 🟢) 1.963s 2 1.07x
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express | Next.js (Turbopack)

workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Next.js (Turbopack) 0.251s (-4.7%) 1.008s (~) 0.758s 60 1.00x
🐘 Postgres Express 0.284s (-4.1%) 1.008s (~) 0.725s 60 1.13x
🐘 Postgres Nitro 0.285s (-3.4%) 1.008s (~) 0.722s 60 1.14x
🌐 Redis Next.js (Turbopack) 0.303s (+13.8% 🔺) 1.004s (~) 0.701s 60 1.21x
💻 Local Nitro 0.575s (-0.9%) 1.004s (~) 0.430s 60 2.29x
💻 Local Express 0.578s (-5.2% 🟢) 1.004s (-1.7%) 0.426s 60 2.31x
💻 Local Next.js (Turbopack) 0.627s (+7.8% 🔺) 1.005s (~) 0.378s 60 2.50x
🌐 MongoDB Next.js (Turbopack) 3.212s (+89.4% 🔺) 3.948s (+83.6% 🔺) 0.736s 16 12.81x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 2.038s (+1.7%) 4.010s (+9.6% 🔺) 1.973s 15 1.00x
▲ Vercel Express 2.116s (+21.4% 🔺) 3.624s (+9.3% 🔺) 1.508s 17 1.04x
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Next.js (Turbopack) | Express

workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Next.js (Turbopack) 0.498s (~) 1.008s (~) 0.510s 90 1.00x
🐘 Postgres Nitro 0.499s (-3.4%) 1.008s (~) 0.509s 90 1.00x
🐘 Postgres Express 0.504s (-3.9%) 1.008s (~) 0.505s 90 1.01x
🌐 Redis Next.js (Turbopack) 1.177s (+9.1% 🔺) 2.006s (+7.7% 🔺) 0.829s 45 2.36x
💻 Local Express 2.537s (~) 3.009s (~) 0.473s 30 5.09x
💻 Local Nitro 2.594s (+1.6%) 3.009s (~) 0.416s 30 5.21x
💻 Local Next.js (Turbopack) 2.745s (+3.8%) 3.042s (+1.1%) 0.297s 30 5.51x
🌐 MongoDB Next.js (Turbopack) 9.488s (+99.5% 🔺) 10.016s (+91.4% 🔺) 0.528s 9 19.05x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 3.085s (-1.7%) 4.763s (-2.4%) 1.678s 19 1.00x
▲ Vercel Next.js (Turbopack) 4.088s (-92.7% 🟢) 5.890s (-89.8% 🟢) 1.802s 16 1.33x
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: 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 🥇 Next.js (Turbopack) 0.773s (+1.0%) 1.009s (~) 0.235s 119 1.00x
🐘 Postgres Nitro 0.786s (-2.0%) 1.009s (~) 0.222s 119 1.02x
🐘 Postgres Express 0.793s (-3.6%) 1.009s (~) 0.216s 119 1.02x
🌐 Redis Next.js (Turbopack) 2.682s (+3.4%) 3.007s (~) 0.325s 40 3.47x
💻 Local Next.js (Turbopack) 10.483s (-3.9%) 11.025s (-4.0%) 0.542s 11 13.56x
💻 Local Express 11.199s (-0.5%) 11.937s (+0.8%) 0.738s 11 14.48x
💻 Local Nitro 11.597s (+3.8%) 12.128s (+3.2%) 0.531s 10 15.00x
🌐 MongoDB Next.js (Turbopack) 19.827s (+98.3% 🔺) 20.524s (+95.2% 🔺) 0.697s 6 25.64x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 8.334s (+7.1% 🔺) 10.205s (+9.5% 🔺) 1.871s 12 1.00x
▲ Vercel Next.js (Turbopack) 8.809s (+11.6% 🔺) 10.703s (+11.2% 🔺) 1.894s 12 1.06x
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express | Next.js (Turbopack)

Stream Benchmarks (includes TTFB metrics)
workflow with stream

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Next.js (Turbopack) 0.150s (-14.2% 🟢) 1.002s (~) 0.011s (-5.1% 🟢) 1.018s (~) 0.867s 10 1.00x
🌐 Redis Next.js (Turbopack) 0.183s (+30.1% 🔺) 1.001s (~) 0.002s (+23.1% 🔺) 1.008s (~) 0.825s 10 1.22x
🐘 Postgres Next.js (Turbopack) 0.198s (~) 1.001s (~) 0.002s (+25.0% 🔺) 1.012s (~) 0.814s 10 1.31x
💻 Local Express 0.205s (-1.2%) 1.004s (~) 0.012s (-4.1%) 1.018s (~) 0.813s 10 1.36x
🐘 Postgres Nitro 0.206s (-3.1%) 0.998s (~) 0.002s (+25.0% 🔺) 1.012s (~) 0.807s 10 1.37x
💻 Local Nitro 0.209s (+3.0%) 1.004s (~) 0.012s (+11.0% 🔺) 1.019s (~) 0.810s 10 1.39x
🐘 Postgres Express 0.213s (-3.6%) 0.993s (~) 0.002s (+21.4% 🔺) 1.013s (~) 0.800s 10 1.41x
🌐 MongoDB Next.js (Turbopack) 0.506s (+0.9%) 0.947s (-1.1%) 0.001s (-29.4% 🟢) 1.009s (~) 0.503s 10 3.36x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 1.872s (+7.8% 🔺) 3.322s (+6.7% 🔺) 0.342s (-46.4% 🟢) 4.256s (-6.8% 🟢) 2.385s 10 1.00x
▲ Vercel Next.js (Turbopack) 1.942s (+16.6% 🔺) 3.375s (+18.6% 🔺) 0.321s (-48.3% 🟢) 4.310s (+3.5%) 2.368s 10 1.04x
▲ Vercel Nitro ⚠️ missing - - - - -

🔍 Observability: 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
🌐 Redis 🥇 Next.js (Turbopack) 0.483s (+27.1% 🔺) 1.001s (~) 0.003s (+5.5% 🔺) 1.011s (~) 0.528s 60 1.00x
🐘 Postgres Nitro 0.615s (-1.3%) 1.003s (~) 0.004s (-5.7% 🟢) 1.026s (~) 0.410s 59 1.28x
🐘 Postgres Express 0.622s (~) 1.005s (~) 0.004s (~) 1.026s (~) 0.404s 59 1.29x
💻 Local Next.js (Turbopack) 0.624s (-7.6% 🟢) 1.009s (-1.6%) 0.009s (+2.2%) 1.024s (-1.5%) 0.400s 59 1.29x
🐘 Postgres Next.js (Turbopack) 0.646s (+5.5% 🔺) 1.009s (~) 0.005s (+30.3% 🔺) 1.025s (~) 0.379s 59 1.34x
💻 Local Express 0.728s (~) 1.010s (~) 0.009s (+11.6% 🔺) 1.022s (~) 0.294s 59 1.51x
💻 Local Nitro 0.755s (+3.8%) 1.011s (~) 0.010s (+16.3% 🔺) 1.024s (~) 0.269s 59 1.57x
🌐 MongoDB Next.js (Turbopack) 1.331s (+0.7%) 1.948s (~) 0.003s (+4.2%) 2.014s (~) 0.684s 30 2.76x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 4.659s (-23.5% 🟢) 5.834s (-23.9% 🟢) 0.273s (+19.3% 🔺) 6.732s (-21.9% 🟢) 2.073s 9 1.00x
▲ Vercel Express 4.900s (+16.3% 🔺) 6.003s (+9.3% 🔺) 0.311s (-37.1% 🟢) 6.951s (+4.9%) 2.051s 9 1.05x
▲ Vercel Nitro ⚠️ missing - - - - -

🔍 Observability: Next.js (Turbopack) | Express

10 parallel streams (1MB each)

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 0.914s (+8.7% 🔺) 1.017s (+1.7%) 0.000s (+52.5% 🔺) 1.021s (+1.7%) 0.108s 59 1.00x
🐘 Postgres Express 0.953s (-1.5%) 1.170s (-4.3%) 0.000s (+88.2% 🔺) 1.186s (-5.3% 🟢) 0.232s 51 1.04x
🐘 Postgres Nitro 0.966s (-3.5%) 1.243s (-8.3% 🟢) 0.000s (-100.0% 🟢) 1.260s (-8.7% 🟢) 0.294s 48 1.06x
🐘 Postgres Next.js (Turbopack) 0.973s (-0.7%) 1.305s (~) 0.000s (-100.0% 🟢) 1.313s (~) 0.341s 46 1.06x
💻 Local Express 1.242s (~) 2.020s (~) 0.001s (+114.3% 🔺) 2.023s (~) 0.781s 30 1.36x
💻 Local Nitro 1.272s (+2.0%) 2.023s (~) 0.000s (-63.6% 🟢) 2.026s (~) 0.754s 30 1.39x
💻 Local Next.js (Turbopack) 1.335s (+3.2%) 2.020s (~) 0.000s (+12.5% 🔺) 2.024s (~) 0.689s 30 1.46x
🌐 MongoDB Next.js (Turbopack) 2.357s (-0.9%) 2.946s (~) 0.000s (+100.0% 🔺) 3.008s (~) 0.651s 20 2.58x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 3.385s (-4.4%) 4.364s (-3.1%) 0.000s (-93.3% 🟢) 5.031s (-3.3%) 1.646s 12 1.00x
▲ Vercel Next.js (Turbopack) 3.520s (+11.5% 🔺) 4.841s (+12.6% 🔺) 0.000s (-80.3% 🟢) 5.544s (+12.2% 🔺) 2.025s 11 1.04x
▲ Vercel Nitro ⚠️ missing - - - - -

🔍 Observability: Express | 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
🌐 Redis 🥇 Next.js (Turbopack) 1.624s (+4.7%) 2.035s (~) 0.000s (+100.0% 🔺) 2.039s (~) 0.416s 30 1.00x
🐘 Postgres Nitro 1.728s (-3.7%) 2.068s (-3.3%) 0.000s (-100.0% 🟢) 2.083s (-3.3%) 0.356s 29 1.06x
🐘 Postgres Express 1.794s (+1.0%) 2.140s (+1.0%) 0.000s (+Infinity% 🔺) 2.154s (-0.6%) 0.360s 28 1.11x
🐘 Postgres Next.js (Turbopack) 1.877s (-2.0%) 2.144s (~) 0.000s (-100.0% 🟢) 2.174s (+0.9%) 0.298s 28 1.16x
💻 Local Express 3.582s (+3.4%) 4.034s (~) 0.000s (-40.0% 🟢) 4.038s (~) 0.456s 15 2.21x
💻 Local Nitro 3.697s (+2.4%) 4.168s (+1.7%) 0.001s (~) 4.172s (+1.7%) 0.475s 15 2.28x
💻 Local Next.js (Turbopack) 3.937s (+6.6% 🔺) 4.389s (+5.4% 🔺) 0.001s (+7.1% 🔺) 4.394s (+5.4% 🔺) 0.457s 14 2.42x
🌐 MongoDB Next.js (Turbopack) 4.395s (-0.9%) 4.950s (~) 0.000s (NaN%) 5.010s (~) 0.616s 12 2.71x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 4.105s (-6.8% 🟢) 5.112s (-7.1% 🟢) 0.001s (+Infinity% 🔺) 5.868s (-4.8%) 1.763s 11 1.00x
▲ Vercel Next.js (Turbopack) 4.776s (~) 6.229s (+5.6% 🔺) 0.000s (-100.0% 🟢) 6.908s (+4.6%) 2.132s 9 1.16x
▲ Vercel Nitro ⚠️ missing - - - - -

🔍 Observability: Express | Next.js (Turbopack)

Summary

Fastest Framework by World

Winner determined by most benchmark wins

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

Winner determined by most benchmark wins

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

📋 View full workflow run


Some benchmark jobs failed:

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

Check the workflow run for details.

Copy link
Copy Markdown
Member

@TooTallNate TooTallNate left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice optimization — combining the run fetch, event fetch, and run_started creation into a single round-trip is a clean TTFB win. The overall approach is sound, but there's a correctness bug in the postgres preloaded events path that needs fixing before merge, plus a couple of non-blocking concerns.

Summary of findings:

  • Blocking: Missing eventData ||= eventDataJson legacy fallback in postgres preloaded events (see inline comment)
  • Blocking: Early return for already-running runs in postgres re-fetches the run but doesn't return preloaded events, creating an asymmetry with the local world (see inline comment)
  • Non-blocking: The (result as any).eventData delete in postgres is redundant after the spread logic already excludes it — minor style nit
  • Non-blocking: world-vercel doesn't surface the events field yet, but since it's optional and the runtime falls back gracefully, this is fine for now

.from(Schema.events)
.where(eq(Schema.events.runId, effectiveRunId))
.orderBy(Schema.events.eventId);
allEvents = eventRows.map((e) => EventSchema.parse(compact(e)));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking: Missing eventData ||= eventDataJson legacy fallback.

Every other read path in this file (events.get, events.list, events.listByCorrelationId) applies v.eventData ||= v.eventDataJson before parsing. This preloaded events path skips it, which means legacy events that only have data in the payload (jsonb) column — and not in payload_cbor — will silently have eventData: undefined during replay, breaking those workflows.

Suggested fix:

allEvents = eventRows.map((e) => {
  e.eventData ||= e.eventDataJson;
  return EventSchema.parse(compact(e));
});

(The Vercel bot comment also suggests applying stripEventDataRefs here. Whether that's needed depends on whether the runtime expects resolved or raw refs — getAllWorkflowRunEvents uses the default resolveData: 'all' so applying it would be consistent, though the runtime would work either way since it resolves everything.)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — added eventData ||= eventDataJson and stripEventDataRefs to match the pattern in events.list and other read paths. Good catch on the legacy fallback.

.limit(1);
if (fullRun) {
return { run: deserializeRunError(compact(fullRun)) };
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking: When the run is already running, this returns { run } with no events field. The runtime will then fall back to getAllWorkflowRunEvents(), which is fine functionally — but it means re-invocations of an already-running workflow get no TTFB benefit from the preloaded events optimization.

More importantly, this early return happens before the event insertion, so it short-circuits the rest of the create method. That means it also skips the requestId idempotency check. If two concurrent invocations race, the first one transitions pending→running and continues, but the second hits this branch and also continues with a valid { run } result. Is that the intended behavior? Normally a duplicate run_started would be guarded by the DB unique constraint on eventId, but here we skip insertion entirely.

If this is intentional (i.e., it's safe for multiple invocations to proceed since replay is deterministic), a comment explaining that would help. If not, this should at minimum return the preloaded events for consistency, or throw an EntityConflictError to signal the duplicate.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a comment explaining the idempotency semantics. The early return is intentional — replay is deterministic so concurrent callers proceeding with the same run is safe. Skipping preloaded events here is acceptable since this is a rare race-condition path and the runtime falls back to getAllWorkflowRunEvents().

// If already running, return the run directly without
// creating a duplicate event.
if (currentRun.status === 'running') {
return { run: currentRun };
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking (same concern as postgres): This early return for already-running also returns { run: currentRun } with no event and no events. The runtime will fall back to getAllWorkflowRunEvents() which is fine, but worth a comment explaining why skipping the preloaded events is acceptable here (presumably because this path is a rare race condition).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the comment — same rationale as the postgres path (rare race condition, runtime falls back to full event fetch).

specVersion: SPEC_VERSION_CURRENT,
},
{ requestId }
);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking observation: Now that runs.get is removed and the runtime always calls events.create(run_started), the behavior changes for runs that are already running. Previously, runs.get would succeed and the if (status === 'pending') guard would skip the run_started creation. Now, every invocation attempts run_started regardless of status.

This works because the world implementations have an early-return for already-running runs — but it's a semantic change worth noting in the PR description. The contract is now: events.create('run_started') must be idempotent for running status (return the run without error), not just for pending → running transitions.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good callout — added a comment documenting this contract: events.create('run_started') must be idempotent for runs already in running status, not just for pending → running transitions.

…ents

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.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.

2 participants