Skip to content

feat(core): experimental start-hook admission for start()#2762

Draft
NathanColosimo wants to merge 1 commit into
mainfrom
nathan/start-hooks-01-core
Draft

feat(core): experimental start-hook admission for start()#2762
NathanColosimo wants to merge 1 commit into
mainfrom
nathan/start-hooks-01-core

Conversation

@NathanColosimo

@NathanColosimo NathanColosimo commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Stack 1/4 · this PR → #2763#2764#2765 · Replaces the monolithic #2684

Adds the experimental experimentalStartHook option to start() (refs #2376, gaps 1 and 2): Worlds that declare experimentalStartHookAdmission reserve the hook token atomically with run admission, so duplicate starts are rejected before any duplicate workflow code can run.

const run = await start(processOrder, [orderId], {
  experimentalStartHook: {
    token: `order:${orderId}`,
    experimental_ttl: '30 days',
  },
});

What's in this PR

  • start() option + validation, and both admission orchestrations:
    • event-first Worlds: create (run + run_created + claim in one transaction) → queue; queue failure cancels the run, which releases the unmaterialized claim so retry can reuse the token.
    • queue-first Worlds: enqueue → admission; failures surface as the new WorkflowStartError (runId / stage / queued / retryable) since the queued run may still execute. HookConflictError passes through.
  • Runtime handling for queued runs that lost their claim: acknowledged without running user code; turbo mode disabled for start-hook runs. Gated cross-deployment by the new experimentalStartHookLoserAck capability (cutoff 5.0.0-beta.27).
  • @workflow/world: World.experimentalStartHookAdmission declaration, ExperimentalStartHook schema/type on run_created / resilient-start run_started / queue runInput (with a compile-time guard keeping the zod/v4 queue copy in sync).
  • WorkflowStartError serialization end-to-end (core reducers/revivers, web-shared + CLI hydration).
  • world-vercel v4 wire routing only for the new eventData field — its compile-time wire-contract exhaustiveness guard requires schema fields to be routed in the same change. Vercel admission behavior lands in PR 4.
  • Docs: Idempotency foundations section, start() API notes, WorkflowStartError reference page.

No World in this PR implements admission yet — using the option against an unsupporting World throws a clear error. Implementations land in the stacked follow-ups.

Docs Preview

Preview links will resolve once the docs deployment builds for this branch: /v5/docs/foundations/idempotency#atomic-start-hook-idempotency, /v5/docs/api-reference/workflow-api/start, /v5/docs/api-reference/workflow-errors/workflow-start-error.

@changeset-bot

changeset-bot Bot commented Jul 2, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 8438b93

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

This PR includes changesets to release 21 packages
Name Type
workflow Minor
@workflow/core Minor
@workflow/errors Minor
@workflow/world Minor
@workflow/web-shared Patch
@workflow/cli Patch
@workflow/world-vercel Patch
@workflow/world-testing Patch
@workflow/builders Patch
@workflow/next Patch
@workflow/nitro Patch
@workflow/vitest Patch
@workflow/web Patch
@workflow/world-local Patch
@workflow/world-postgres 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

vercel Bot commented Jul 2, 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 Jul 3, 2026 12:00am
example-nextjs-workflow-webpack Ready Ready Preview, Comment Jul 3, 2026 12:00am
example-workflow Ready Ready Preview, Comment Jul 3, 2026 12:00am
workbench-astro-workflow Ready Ready Preview, Comment Jul 3, 2026 12:00am
workbench-express-workflow Ready Ready Preview, Comment Jul 3, 2026 12:00am
workbench-fastify-workflow Ready Ready Preview, Comment Jul 3, 2026 12:00am
workbench-hono-workflow Ready Ready Preview, Comment Jul 3, 2026 12:00am
workbench-nitro-workflow Ready Ready Preview, Comment Jul 3, 2026 12:00am
workbench-nuxt-workflow Ready Ready Preview, Comment Jul 3, 2026 12:00am
workbench-sveltekit-workflow Ready Ready Preview, Comment Jul 3, 2026 12:00am
workbench-tanstack-start-workflow Ready Ready Preview, Comment Jul 3, 2026 12:00am
workbench-vite-workflow Ready Ready Preview, Comment Jul 3, 2026 12:00am
workflow-docs Ready Ready Preview, Comment, Open in v0 Jul 3, 2026 12:00am
workflow-swc-playground Ready Ready Preview, Comment Jul 3, 2026 12:00am
workflow-tarballs Ready Ready Preview, Comment Jul 3, 2026 12:00am
workflow-web Ready Ready Preview, Comment Jul 3, 2026 12:00am

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

All tests passed

Summary

Passed Failed Skipped Total
✅ ▲ Vercel Production 1442 0 230 1672
✅ 💻 Local Development 1605 0 219 1824
✅ 📦 Local Production 1605 0 219 1824
✅ 🐘 Local Postgres 1605 0 219 1824
✅ 🪟 Windows 152 0 0 152
✅ 📋 Other 887 0 177 1064
Total 7296 0 1064 8360

Details by Category

✅ ▲ Vercel Production
App Passed Failed Skipped
✅ astro 125 0 27
✅ example 125 0 27
✅ express 125 0 27
✅ fastify 125 0 27
✅ hono 125 0 27
✅ nextjs-turbopack 149 0 3
✅ nextjs-webpack 149 0 3
✅ nitro 125 0 27
✅ nuxt 125 0 27
✅ sveltekit 144 0 8
✅ vite 125 0 27
✅ 💻 Local Development
App Passed Failed Skipped
✅ astro-stable 127 0 25
✅ express-stable 127 0 25
✅ fastify-stable 127 0 25
✅ hono-stable 127 0 25
✅ nextjs-turbopack-canary 133 0 19
✅ nextjs-turbopack-stable 152 0 0
✅ nextjs-webpack-canary 133 0 19
✅ nextjs-webpack-stable 152 0 0
✅ nitro-stable 127 0 25
✅ nuxt-stable 127 0 25
✅ sveltekit-stable 146 0 6
✅ vite-stable 127 0 25
✅ 📦 Local Production
App Passed Failed Skipped
✅ astro-stable 127 0 25
✅ express-stable 127 0 25
✅ fastify-stable 127 0 25
✅ hono-stable 127 0 25
✅ nextjs-turbopack-canary 133 0 19
✅ nextjs-turbopack-stable 152 0 0
✅ nextjs-webpack-canary 133 0 19
✅ nextjs-webpack-stable 152 0 0
✅ nitro-stable 127 0 25
✅ nuxt-stable 127 0 25
✅ sveltekit-stable 146 0 6
✅ vite-stable 127 0 25
✅ 🐘 Local Postgres
App Passed Failed Skipped
✅ astro-stable 127 0 25
✅ express-stable 127 0 25
✅ fastify-stable 127 0 25
✅ hono-stable 127 0 25
✅ nextjs-turbopack-canary 133 0 19
✅ nextjs-turbopack-stable 152 0 0
✅ nextjs-webpack-canary 133 0 19
✅ nextjs-webpack-stable 152 0 0
✅ nitro-stable 127 0 25
✅ nuxt-stable 127 0 25
✅ sveltekit-stable 146 0 6
✅ vite-stable 127 0 25
✅ 🪟 Windows
App Passed Failed Skipped
✅ nextjs-turbopack 152 0 0
✅ 📋 Other
App Passed Failed Skipped
✅ e2e-local-dev-nest-stable 127 0 25
✅ e2e-local-dev-tanstack-start- 127 0 25
✅ e2e-local-postgres-nest-stable 127 0 25
✅ e2e-local-postgres-tanstack-start- 127 0 25
✅ e2e-local-prod-nest-stable 127 0 25
✅ e2e-local-prod-tanstack-start- 127 0 25
✅ e2e-vercel-prod-tanstack-start 125 0 27

📋 View full workflow run

@github-actions

github-actions Bot commented Jul 2, 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 🥇 Express 0.047s (-1.3%) 1.006s (~) 0.959s 10 1.00x
💻 Local Nitro 0.050s (-14.2% 🟢) 1.008s (-1.1%) 0.958s 10 1.05x
💻 Local Next.js (Turbopack) 0.055s (-2.2%) 1.006s (~) 0.951s 10 1.15x
🐘 Postgres Express 0.063s (-1.9%) 1.013s (~) 0.950s 10 1.33x
🐘 Postgres Next.js (Turbopack) 0.065s (+3.9%) 1.012s (~) 0.948s 10 1.37x
🐘 Postgres Nitro 0.070s (+4.6%) 1.010s (~) 0.940s 10 1.49x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 0.196s (-12.6% 🟢) 1.652s (-7.4% 🟢) 1.456s 10 1.00x
▲ Vercel Nitro 0.208s (+15.4% 🔺) 1.815s (+11.5% 🔺) 1.607s 10 1.06x
▲ Vercel Next.js (Turbopack) 0.546s (-26.9% 🟢) 2.347s (-4.8%) 1.801s 10 2.79x

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

workflow with 1 step

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Express 1.079s (~) 2.007s (~) 0.928s 10 1.00x
💻 Local Nitro 1.085s (~) 2.007s (~) 0.921s 10 1.01x
💻 Local Next.js (Turbopack) 1.089s (~) 2.006s (~) 0.917s 10 1.01x
🐘 Postgres Express 1.095s (~) 2.010s (~) 0.916s 10 1.01x
🐘 Postgres Next.js (Turbopack) 1.103s (~) 2.010s (~) 0.907s 10 1.02x
🐘 Postgres Nitro 1.104s (+0.9%) 2.010s (~) 0.906s 10 1.02x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 1.385s (+0.5%) 2.876s (-13.0% 🟢) 1.491s 10 1.00x
▲ Vercel Express 1.550s (+4.7%) 2.989s (-10.5% 🟢) 1.439s 10 1.12x
▲ Vercel Next.js (Turbopack) 1.870s (-9.1% 🟢) 3.725s (+2.5%) 1.855s 10 1.35x

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

workflow with 10 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Express 10.439s (~) 11.022s (~) 0.583s 3 1.00x
💻 Local Nitro 10.466s (~) 11.022s (~) 0.556s 3 1.00x
🐘 Postgres Express 10.500s (~) 11.023s (~) 0.523s 3 1.01x
💻 Local Next.js (Turbopack) 10.534s (~) 11.021s (~) 0.487s 3 1.01x
🐘 Postgres Nitro 10.539s (~) 11.015s (~) 0.476s 3 1.01x
🐘 Postgres Next.js (Turbopack) 10.564s (~) 11.021s (~) 0.457s 3 1.01x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 11.642s (~) 14.182s (+7.3% 🔺) 2.540s 3 1.00x
▲ Vercel Nitro 11.705s (+1.1%) 14.044s (+9.9% 🔺) 2.339s 3 1.01x
▲ Vercel Next.js (Turbopack) 12.528s (+6.5% 🔺) 13.952s (+0.8%) 1.424s 3 1.08x

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

workflow with 25 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 13.612s (~) 14.021s (~) 0.409s 5 1.00x
💻 Local Express 13.626s (~) 14.027s (~) 0.401s 5 1.00x
💻 Local Nitro 13.691s (~) 14.027s (~) 0.336s 5 1.01x
🐘 Postgres Next.js (Turbopack) 13.699s (~) 14.022s (~) 0.324s 5 1.01x
🐘 Postgres Express 13.724s (~) 14.017s (~) 0.293s 5 1.01x
💻 Local Next.js (Turbopack) 13.870s (+0.8%) 14.026s (~) 0.155s 5 1.02x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 16.116s (-2.1%) 17.693s (-1.7%) 1.577s 4 1.00x
▲ Vercel Express 16.530s (-1.4%) 18.781s (+1.6%) 2.251s 4 1.03x
▲ Vercel Next.js (Turbopack) 18.141s (+4.3%) 19.556s (+1.4%) 1.415s 4 1.13x

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

workflow with 50 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Express 12.133s (~) 13.026s (~) 0.893s 7 1.00x
🐘 Postgres Nitro 12.239s (-0.7%) 13.017s (~) 0.778s 7 1.01x
💻 Local Nitro 12.280s (~) 13.026s (~) 0.746s 7 1.01x
🐘 Postgres Express 12.288s (~) 13.021s (~) 0.733s 7 1.01x
💻 Local Next.js (Turbopack) 12.318s (-0.8%) 13.023s (~) 0.706s 7 1.02x
🐘 Postgres Next.js (Turbopack) 12.417s (~) 13.014s (~) 0.597s 7 1.02x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 17.533s (-5.4% 🟢) 19.544s (-2.5%) 2.011s 5 1.00x
▲ Vercel Express 17.964s (+2.3%) 20.228s (+7.4% 🔺) 2.264s 5 1.02x
▲ Vercel Next.js (Turbopack) 20.290s (+4.3%) 21.649s (~) 1.359s 5 1.16x

🔍 Observability: Nitro | 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.194s (-0.7%) 2.008s (~) 0.814s 15 1.00x
🐘 Postgres Nitro 1.195s (~) 2.007s (~) 0.812s 15 1.00x
🐘 Postgres Express 1.196s (-1.0%) 2.008s (~) 0.812s 15 1.00x
💻 Local Express 1.373s (-0.5%) 2.006s (~) 0.634s 15 1.15x
💻 Local Next.js (Turbopack) 1.461s (+2.0%) 2.006s (~) 0.545s 15 1.22x
💻 Local Nitro 1.479s (+5.4% 🔺) 2.007s (~) 0.527s 15 1.24x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.170s (+2.8%) 4.128s (+16.3% 🔺) 1.957s 8 1.00x
▲ Vercel Nitro 2.348s (+4.5%) 4.271s (+16.6% 🔺) 1.924s 8 1.08x
▲ Vercel Next.js (Turbopack) 3.883s (+22.9% 🔺) 5.354s (+2.7%) 1.471s 6 1.79x

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

Promise.all with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 1.318s (-3.8%) 2.295s (-8.6% 🟢) 0.977s 14 1.00x
🐘 Postgres Nitro 1.321s (-2.4%) 2.509s (+1.6%) 1.189s 12 1.00x
🐘 Postgres Next.js (Turbopack) 1.321s (~) 3.009s (~) 1.688s 10 1.00x
💻 Local Next.js (Turbopack) 2.202s (-7.9% 🟢) 2.826s (-6.1% 🟢) 0.624s 11 1.67x
💻 Local Express 2.350s (-5.2% 🟢) 3.009s (-3.2%) 0.659s 10 1.78x
💻 Local Nitro 2.513s (+4.0%) 3.110s (+3.4%) 0.597s 10 1.91x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.478s (+2.1%) 4.096s (+2.8%) 1.618s 8 1.00x
▲ Vercel Nitro 2.742s (+13.2% 🔺) 4.511s (+20.2% 🔺) 1.769s 7 1.11x
▲ Vercel Next.js (Turbopack) 4.147s (+20.9% 🔺) 5.828s (+10.9% 🔺) 1.681s 6 1.67x

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

Promise.all with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.582s (-1.5%) 4.015s (-6.7% 🟢) 2.433s 8 1.00x
🐘 Postgres Express 1.606s (-5.0%) 4.298s (-3.3%) 2.692s 7 1.02x
🐘 Postgres Next.js (Turbopack) 3.154s (-1.0%) 6.015s (+2.9%) 2.861s 5 1.99x
💻 Local Next.js (Turbopack) 3.709s (-2.0%) 4.728s (-2.9%) 1.019s 7 2.35x
💻 Local Express 3.967s (+12.2% 🔺) 4.726s (~) 0.759s 7 2.51x
💻 Local Nitro 4.760s (+24.0% 🔺) 5.345s (+16.6% 🔺) 0.586s 6 3.01x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.942s (-1.2%) 4.727s (+5.4% 🔺) 1.785s 7 1.00x
▲ Vercel Nitro 3.190s (+3.0%) 5.359s (+13.2% 🔺) 2.170s 6 1.08x
▲ Vercel Next.js (Turbopack) 4.290s (-4.7%) 5.785s (-8.9% 🟢) 1.495s 6 1.46x

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

Promise.race with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.190s (~) 2.008s (~) 0.818s 15 1.00x
🐘 Postgres Express 1.191s (-3.2%) 2.008s (-3.2%) 0.817s 15 1.00x
🐘 Postgres Next.js (Turbopack) 1.225s (-2.2%) 2.076s (~) 0.851s 15 1.03x
💻 Local Nitro 1.441s (+0.6%) 2.007s (~) 0.565s 15 1.21x
💻 Local Next.js (Turbopack) 1.451s (~) 2.006s (~) 0.555s 15 1.22x
💻 Local Express 1.457s (+1.9%) 2.006s (~) 0.549s 15 1.22x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 1.950s (-8.1% 🟢) 3.931s (+9.6% 🔺) 1.981s 8 1.00x
▲ Vercel Nitro 2.168s (-12.6% 🟢) 3.949s (+2.6%) 1.780s 8 1.11x
▲ Vercel Next.js (Turbopack) 3.609s (+6.8% 🔺) 5.036s (-5.1% 🟢) 1.427s 6 1.85x

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

Promise.race with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Next.js (Turbopack) 1.310s (-2.1%) 2.919s (-3.0%) 1.609s 11 1.00x
🐘 Postgres Nitro 1.334s (+1.3%) 2.470s (+3.2%) 1.136s 13 1.02x
🐘 Postgres Express 1.386s (+1.5%) 2.223s (-14.3% 🟢) 0.837s 14 1.06x
💻 Local Express 2.436s (-0.8%) 3.009s (~) 0.573s 10 1.86x
💻 Local Next.js (Turbopack) 2.571s (-2.5%) 3.109s (+3.3%) 0.538s 10 1.96x
💻 Local Nitro 2.663s (+7.4% 🔺) 3.110s (+3.4%) 0.447s 10 2.03x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.213s (-2.0%) 3.967s (+10.9% 🔺) 1.754s 8 1.00x
▲ Vercel Nitro 2.396s (+1.9%) 4.087s (+8.3% 🔺) 1.691s 8 1.08x
▲ Vercel Next.js (Turbopack) 3.701s (+9.1% 🔺) 5.167s (-3.1%) 1.466s 6 1.67x

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

Promise.race with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.591s (-1.1%) 4.010s (-3.0%) 2.419s 8 1.00x
🐘 Postgres Express 1.652s (~) 4.302s (~) 2.651s 7 1.04x
🐘 Postgres Next.js (Turbopack) 3.131s (-5.0%) 6.014s (-3.2%) 2.883s 5 1.97x
💻 Local Next.js (Turbopack) 5.520s (-1.5%) 6.013s (~) 0.494s 5 3.47x
💻 Local Nitro 5.544s (-1.6%) 6.217s (+3.4%) 0.673s 5 3.48x
💻 Local Express 5.617s (+2.2%) 6.216s (+3.4%) 0.599s 5 3.53x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 2.760s (-3.8%) 4.549s (+3.2%) 1.789s 7 1.00x
▲ Vercel Express 2.886s (+8.0% 🔺) 4.733s (+9.9% 🔺) 1.847s 7 1.05x
▲ Vercel Next.js (Turbopack) 4.395s (-12.5% 🟢) 5.903s (-13.6% 🟢) 1.508s 6 1.59x

🔍 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 🥇 Express 0.576s (+1.5%) 1.005s (~) 0.429s 60 1.00x
🐘 Postgres Express 0.591s (-1.6%) 1.023s (~) 0.432s 59 1.03x
🐘 Postgres Nitro 0.595s (+1.8%) 1.041s (~) 0.446s 58 1.03x
💻 Local Nitro 0.605s (+0.8%) 1.005s (~) 0.400s 60 1.05x
🐘 Postgres Next.js (Turbopack) 0.610s (+8.3% 🔺) 1.023s (+1.7%) 0.414s 59 1.06x
💻 Local Next.js (Turbopack) 0.649s (+2.9%) 1.022s (+1.6%) 0.373s 59 1.13x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.445s (-5.8% 🟢) 4.020s (+6.2% 🔺) 1.575s 15 1.00x
▲ Vercel Nitro 2.474s (-4.1%) 4.139s (+1.6%) 1.665s 15 1.01x
▲ Vercel Next.js (Turbopack) 3.482s (+2.3%) 5.105s (-1.9%) 1.622s 12 1.42x

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

workflow with 25 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.259s (-7.0% 🟢) 2.007s (~) 0.748s 45 1.00x
🐘 Postgres Next.js (Turbopack) 1.411s (-2.1%) 2.008s (-1.1%) 0.597s 45 1.12x
🐘 Postgres Express 1.430s (+0.9%) 2.054s (~) 0.624s 44 1.14x
💻 Local Express 1.507s (+1.8%) 2.028s (~) 0.521s 45 1.20x
💻 Local Nitro 1.518s (~) 2.006s (~) 0.488s 45 1.21x
💻 Local Next.js (Turbopack) 1.596s (-3.6%) 2.006s (-1.1%) 0.410s 45 1.27x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 5.561s (-10.2% 🟢) 7.677s (+1.1%) 2.116s 12 1.00x
▲ Vercel Nitro 5.918s (-1.5%) 7.826s (+3.5%) 1.908s 12 1.06x
▲ Vercel Next.js (Turbopack) 8.521s (-5.5% 🟢) 9.967s (-10.2% 🟢) 1.446s 10 1.53x

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

workflow with 50 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 2.739s (+1.3%) 3.111s (+0.8%) 0.372s 39 1.00x
🐘 Postgres Express 2.767s (+4.0%) 3.137s (+3.4%) 0.370s 39 1.01x
🐘 Postgres Next.js (Turbopack) 2.969s (+7.1% 🔺) 3.343s (+11.1% 🔺) 0.374s 36 1.08x
💻 Local Express 3.178s (~) 3.945s (+1.7%) 0.766s 31 1.16x
💻 Local Nitro 3.318s (+2.2%) 4.009s (~) 0.691s 30 1.21x
💻 Local Next.js (Turbopack) 3.385s (-5.6% 🟢) 4.009s (-1.7%) 0.624s 30 1.24x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 11.040s (-7.9% 🟢) 13.068s (-2.1%) 2.027s 10 1.00x
▲ Vercel Express 11.509s (-8.3% 🟢) 13.650s (-3.0%) 2.141s 9 1.04x
▲ Vercel Next.js (Turbopack) 17.366s (-0.8%) 18.893s (-4.7%) 1.527s 7 1.57x

🔍 Observability: Nitro | 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 🥇 Nitro 0.215s (-2.9%) 1.006s (~) 0.791s 60 1.00x
🐘 Postgres Next.js (Turbopack) 0.220s (+4.8%) 1.023s (~) 0.804s 59 1.02x
🐘 Postgres Express 0.225s (+5.2% 🔺) 1.006s (~) 0.781s 60 1.04x
💻 Local Nitro 0.533s (+7.0% 🔺) 1.022s (+1.7%) 0.488s 59 2.48x
💻 Local Express 0.554s (+13.6% 🔺) 1.005s (~) 0.450s 60 2.57x
💻 Local Next.js (Turbopack) 0.613s (-6.2% 🟢) 1.022s (~) 0.409s 59 2.84x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 0.985s (-6.8% 🟢) 2.756s (+21.0% 🔺) 1.771s 22 1.00x
▲ Vercel Nitro 1.101s (+12.0% 🔺) 2.754s (+24.3% 🔺) 1.653s 23 1.12x
▲ Vercel Next.js (Turbopack) 2.277s (+14.1% 🔺) 3.423s (-11.3% 🟢) 1.146s 18 2.31x

🔍 Observability: Express | Nitro | 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.339s (+4.8%) 1.006s (~) 0.667s 90 1.00x
🐘 Postgres Nitro 0.347s (+3.6%) 1.006s (~) 0.659s 90 1.02x
🐘 Postgres Next.js (Turbopack) 0.357s (+20.6% 🔺) 1.053s (+4.7%) 0.696s 86 1.05x
💻 Local Express 2.495s (+0.8%) 3.010s (~) 0.515s 30 7.35x
💻 Local Nitro 2.499s (-1.9%) 3.010s (~) 0.511s 30 7.37x
💻 Local Next.js (Turbopack) 2.637s (-1.0%) 3.042s (+1.1%) 0.405s 30 7.77x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 1.770s (+33.4% 🔺) 3.369s (+36.2% 🔺) 1.599s 27 1.00x
▲ Vercel Next.js (Turbopack) 3.029s (+18.5% 🔺) 4.639s (+9.2% 🔺) 1.610s 20 1.71x
▲ Vercel Nitro 37.414s (+2601.8% 🔺) 39.050s (+1321.0% 🔺) 1.636s 25 21.14x

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

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 0.565s (+8.2% 🔺) 1.172s (+8.7% 🔺) 0.607s 103 1.00x
🐘 Postgres Nitro 0.579s (+14.6% 🔺) 1.118s (+8.3% 🔺) 0.538s 108 1.03x
🐘 Postgres Next.js (Turbopack) 0.605s (+13.4% 🔺) 3.283s (+9.1% 🔺) 2.678s 37 1.07x
💻 Local Express 5.452s (-6.3% 🟢) 9.028s (+1.6%) 3.576s 14 9.65x
💻 Local Next.js (Turbopack) 5.865s (-2.9%) 8.667s (-3.2%) 2.803s 14 10.38x
💻 Local Nitro 5.965s (+11.2% 🔺) 8.565s (+2.5%) 2.599s 15 10.56x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.120s (+15.8% 🔺) 4.266s (+16.6% 🔺) 2.145s 29 1.00x
▲ Vercel Nitro 2.825s (+56.0% 🔺) 4.910s (+44.6% 🔺) 2.085s 25 1.33x
▲ Vercel Next.js (Turbopack) 4.133s (~) 5.925s (-0.5%) 1.792s 21 1.95x

🔍 Observability: Express | Nitro | 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) 1.155s (+0.6%) 1.964s (~) 0.012s (-8.5% 🟢) 2.019s (~) 0.864s 10 1.00x
🐘 Postgres Nitro 1.159s (~) 2.000s (~) 0.001s (-15.4% 🟢) 2.012s (~) 0.853s 10 1.00x
💻 Local Express 1.160s (+0.6%) 2.004s (~) 0.010s (-1.9%) 2.017s (~) 0.858s 10 1.00x
💻 Local Nitro 1.160s (~) 2.005s (~) 0.012s (+3.3%) 2.020s (~) 0.860s 10 1.00x
🐘 Postgres Express 1.163s (~) 1.996s (~) 0.001s (+20.0% 🔺) 2.011s (~) 0.848s 10 1.01x
🐘 Postgres Next.js (Turbopack) 1.169s (~) 2.001s (~) 0.001s (+8.3% 🔺) 2.011s (~) 0.841s 10 1.01x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 1.941s (-8.4% 🟢) 3.506s (+10.2% 🔺) 1.343s (-27.4% 🟢) 5.369s (-2.0%) 3.428s 10 1.00x
▲ Vercel Express 1.989s (-8.5% 🟢) 3.442s (+0.6%) 1.716s (-8.3% 🟢) 5.674s (-0.6%) 3.686s 10 1.02x
▲ Vercel Next.js (Turbopack) 3.915s (+15.6% 🔺) 3.979s (-8.9% 🟢) 1.084s (+14.5% 🔺) 6.546s (-0.5%) 2.631s 10 2.02x

🔍 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
💻 Local 🥇 Express 1.556s (-1.6%) 2.010s (~) 0.013s (+3.4%) 2.026s (~) 0.470s 30 1.00x
🐘 Postgres Nitro 1.570s (~) 2.005s (~) 0.005s (+10.2% 🔺) 2.026s (~) 0.456s 30 1.01x
🐘 Postgres Express 1.589s (~) 2.002s (~) 0.005s (+1.3%) 2.026s (~) 0.437s 30 1.02x
💻 Local Next.js (Turbopack) 1.604s (~) 1.967s (~) 0.013s (-5.9% 🟢) 2.025s (~) 0.421s 30 1.03x
💻 Local Nitro 1.608s (+2.0%) 2.011s (~) 0.013s (+0.5%) 2.027s (~) 0.418s 30 1.03x
🐘 Postgres Next.js (Turbopack) 1.727s (+2.2%) 2.043s (~) 0.005s (+0.6%) 2.060s (~) 0.333s 30 1.11x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 5.391s (~) 7.417s (+11.6% 🔺) 0.287s (+27.5% 🔺) 8.345s (+13.5% 🔺) 2.953s 8 1.00x
▲ Vercel Nitro 5.394s (-0.9%) 7.308s (+11.5% 🔺) 0.267s (+39.6% 🔺) 8.089s (+12.6% 🔺) 2.695s 8 1.00x
▲ Vercel Next.js (Turbopack) 9.831s (+8.2% 🔺) 11.104s (+5.4% 🔺) 0.225s (-17.9% 🟢) 11.766s (~) 1.936s 6 1.82x

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

10 parallel streams (1MB each)

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 0.800s (+2.2%) 1.044s (-0.5%) 0.000s (+Infinity% 🔺) 1.072s (-0.8%) 0.272s 56 1.00x
🐘 Postgres Nitro 0.801s (+2.7%) 1.082s (+1.7%) 0.000s (-32.1% 🟢) 1.107s (+1.8%) 0.306s 55 1.00x
🐘 Postgres Next.js (Turbopack) 1.001s (+3.4%) 1.395s (-3.1%) 0.000s (-4.7%) 1.404s (-4.2%) 0.403s 43 1.25x
💻 Local Express 1.251s (-9.4% 🟢) 1.981s (+1.6%) 0.001s (+112.5% 🔺) 1.984s (+1.6%) 0.733s 31 1.56x
💻 Local Next.js (Turbopack) 1.301s (-2.8%) 1.976s (~) 0.000s (+33.3% 🔺) 2.016s (~) 0.716s 30 1.63x
💻 Local Nitro 1.353s (-1.7%) 1.949s (-1.6%) 0.001s (+45.5% 🔺) 1.952s (-1.6%) 0.599s 31 1.69x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.956s (+2.2%) 4.662s (+14.6% 🔺) 0.000s (-100.0% 🟢) 5.210s (+17.1% 🔺) 2.254s 12 1.00x
▲ Vercel Nitro 3.101s (+2.0%) 4.685s (+12.3% 🔺) 0.000s (+Infinity% 🔺) 5.210s (+13.0% 🔺) 2.109s 12 1.05x
▲ Vercel Next.js (Turbopack) 5.170s (+6.1% 🔺) 5.605s (-2.5%) 0.000s (+100.0% 🔺) 6.779s (-1.1%) 1.610s 9 1.75x

🔍 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.621s (-8.6% 🟢) 2.174s (-9.3% 🟢) 0.000s (-55.4% 🟢) 2.213s (-8.1% 🟢) 0.592s 28 1.00x
🐘 Postgres Nitro 1.918s (+4.3%) 2.494s (+4.8%) 0.000s (+Infinity% 🔺) 2.511s (+4.8%) 0.593s 24 1.18x
🐘 Postgres Next.js (Turbopack) 2.204s (-19.8% 🟢) 2.724s (-18.3% 🟢) 0.000s (-100.0% 🟢) 2.738s (-18.2% 🟢) 0.534s 22 1.36x
💻 Local Express 3.252s (-5.6% 🟢) 3.840s (-4.6%) 0.001s (+204.7% 🔺) 3.843s (-4.6%) 0.592s 16 2.01x
💻 Local Nitro 3.296s (+3.7%) 4.028s (+9.6% 🔺) 0.001s (+61.9% 🔺) 4.031s (+9.6% 🔺) 0.735s 15 2.03x
💻 Local Next.js (Turbopack) 3.429s (-1.3%) 3.864s (-3.1%) 0.000s (-73.2% 🟢) 3.905s (-3.1%) 0.476s 16 2.12x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 4.261s (+2.6%) 5.836s (+9.8% 🔺) 0.005s (+2870.0% 🔺) 6.347s (+10.8% 🔺) 2.087s 10 1.00x
▲ Vercel Next.js (Turbopack) 7.287s (+1.9%) 7.960s (-1.2%) 0.000s (-100.0% 🟢) 8.934s (-2.0%) 1.647s 7 1.71x
▲ Vercel Express ⚠️ missing - - - - -

🔍 Observability: Nitro | Next.js (Turbopack)

Summary

Fastest Framework by World

Winner determined by most benchmark wins

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

Winner determined by most benchmark wins

Framework 🥇 Fastest World Wins
Express 🐘 Postgres 13/21
Next.js (Turbopack) 🐘 Postgres 15/21
Nitro 🐘 Postgres 18/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)
  • 🌐 Platformatic: Community world (local development)

📋 View full workflow run

@NathanColosimo NathanColosimo force-pushed the nathan/start-hooks-01-core branch from 79beb9d to 41bdb5a Compare July 2, 2026 23:45
Adds the experimentalStartHook option to start(): Worlds that declare
experimentalStartHookAdmission (event-first or queue-first) reserve the
hook token atomically with run admission. Duplicate starts throw
HookConflictError; queue-first Worlds throw the new WorkflowStartError
(runId/stage/retryable) when a run was queued but admission could not
be confirmed. Turbo mode is disabled for start-hook runs and a queued
run that lost its claim acknowledges without running user code, gated
by the experimentalStartHookLoserAck capability.

world-vercel's v4 wire routing carries the new run_created /
resilient-start eventData field (its compile-time wire-contract guard
requires schema fields to be routed in the same change); the Vercel
admission behavior itself, and the local/postgres implementations, land
in the stacked follow-ups.
@NathanColosimo NathanColosimo force-pushed the nathan/start-hooks-01-core branch from 41bdb5a to 8438b93 Compare July 2, 2026 23:56
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