Skip to content

[ai] Fix "missing text part" stream crash by repairing UI message framing#2537

Draft
VaguelySerious wants to merge 1 commit into
mainfrom
peter/issue-2422
Draft

[ai] Fix "missing text part" stream crash by repairing UI message framing#2537
VaguelySerious wants to merge 1 commit into
mainfrom
peter/issue-2422

Conversation

@VaguelySerious

Copy link
Copy Markdown
Member

Closes #2422

Problem

A workflow run owns a single shared UI message stream, and the AI SDK's stream consumer (processUIMessageStream, backing useChat/readUIMessageStream) resets its active text/reasoning part maps on every finish-step. Multi-step turns reuse the same part id (commonly "0") in each step. So if a text-start is dropped or a finish-step lands in the middle of a text part, the consumer hits a text-delta/text-end for an id it has no open part for and throws:

Received text-delta for missing text part with ID "0". Ensure a "text-start" chunk is sent before any "text-delta" chunks.

…which kills the whole turn.

That malformed framing is reachable whenever a stream-producing step's output is duplicated or interleaved on the shared stream — e.g. step retry/redelivery, reconnect/replay overlap, or the concurrent-worker duplication tracked in #2331 / #2039 (a finish-step from one execution landing inside another's text part).

Fix

WorkflowChatTransport now passes the stream it hands to the AI SDK through normalizeUIMessageStreamParts, which mirrors the consumer's per-step part-lifetime state machine:

  • resets tracking on finish-step (exactly where the consumer resets);
  • synthesizes a missing *-start when an orphaned *-delta/*-end arrives;
  • drops a re-delivered *-start/*-delta/*-end for a part already open/ended in the current step (reconnect/replay overlap).

It wraps the output of the send/reconnect iterators, so the reconnect chunkIndex/gotFinish accounting is untouched. A well-formed stream passes through unchanged; the worst case degrades to "text begins slightly into the step" or "a duplicated tail is dropped" instead of a dead turn. Applies to both text and reasoning parts.

This addresses the client-visible symptom for all WorkflowChatTransport consumers regardless of the upstream duplication cause. The underlying server-side duplicate-execution races (#2331, #2039) are separate and remain tracked there.

Tests

packages/ai/src/workflow-chat-transport.stream-repair.test.ts drives the real transport (mock fetch returning chunks via the AI SDK's own JsonToSseTransformStream) into the real readUIMessageStream consumer:

  • proves the raw interleaved stream reproduces the exact missing text part error;
  • proves the transport now repairs it with no content lost ("Hello world");
  • proves a reconnect/replay duplicate tail is dropped without erroring;
  • proves a well-formed multi-step stream (id "0" reused across steps) is unchanged.

🤖 Generated with Claude Code

…ming

Duplicated or interleaved durable stream writes (step retry/redelivery or
concurrent-worker duplication) can land a finish-step in the middle of a text
part that reuses id "0", orphaning the rest. The AI SDK consumer then throws
`Received text-delta for missing text part with ID "0"` and kills the turn.

WorkflowChatTransport now normalizes UI message stream part framing — mirroring
the consumer's per-step part-lifetime state machine — so orphaned deltas/ends
get a synthesized start and replayed chunks are dropped. Well-formed streams
pass through unchanged.

Closes #2422

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@changeset-bot

changeset-bot Bot commented Jun 19, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: f4f35c5

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

This PR includes changesets to release 1 package
Name Type
@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

@vercel

vercel Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

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

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

@github-actions

github-actions Bot commented Jun 19, 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 1909 0 219 2128
✅ 📦 Local Production 1909 0 219 2128
✅ 🐘 Local Postgres 1895 0 233 2128
✅ 🪟 Windows 152 0 0 152
✅ 📋 Other 885 0 179 1064
Total 8192 0 1080 9272

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-lazy-discovery-disabled 152 0 0
✅ nextjs-turbopack-stable-lazy-discovery-enabled 152 0 0
✅ nextjs-webpack-canary 133 0 19
✅ nextjs-webpack-stable-lazy-discovery-disabled 152 0 0
✅ nextjs-webpack-stable-lazy-discovery-enabled 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-lazy-discovery-disabled 152 0 0
✅ nextjs-turbopack-stable-lazy-discovery-enabled 152 0 0
✅ nextjs-webpack-canary 133 0 19
✅ nextjs-webpack-stable-lazy-discovery-disabled 152 0 0
✅ nextjs-webpack-stable-lazy-discovery-enabled 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 126 0 26
✅ express-stable 126 0 26
✅ fastify-stable 126 0 26
✅ hono-stable 126 0 26
✅ nextjs-turbopack-canary 132 0 20
✅ nextjs-turbopack-stable-lazy-discovery-disabled 151 0 1
✅ nextjs-turbopack-stable-lazy-discovery-enabled 151 0 1
✅ nextjs-webpack-canary 132 0 20
✅ nextjs-webpack-stable-lazy-discovery-disabled 151 0 1
✅ nextjs-webpack-stable-lazy-discovery-enabled 151 0 1
✅ nitro-stable 126 0 26
✅ nuxt-stable 126 0 26
✅ sveltekit-stable 145 0 7
✅ vite-stable 126 0 26
✅ 🪟 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 126 0 26
✅ e2e-local-postgres-tanstack-start- 126 0 26
✅ 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 Jun 19, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

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

workflow with no steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 0.042s (+2.4%) 1.006s (~) 0.964s 10 1.00x
💻 Local Express 0.044s (+7.8% 🔺) 1.007s (~) 0.962s 10 1.06x
💻 Local Next.js (Turbopack) 0.054s (+11.4% 🔺) 1.007s (~) 0.953s 10 1.28x
🐘 Postgres Express 0.057s (-7.0% 🟢) 1.013s (~) 0.955s 10 1.37x
🐘 Postgres Next.js (Turbopack) 0.058s (-0.7%) 1.011s (~) 0.954s 10 1.37x
🐘 Postgres Nitro 0.061s (-3.3%) 1.022s (+0.9%) 0.960s 10 1.46x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 0.270s (-30.7% 🟢) 1.896s (-25.0% 🟢) 1.626s 10 1.00x
▲ Vercel Express 0.403s (+1.4%) 2.687s (+10.3% 🔺) 2.284s 10 1.49x
▲ Vercel Next.js (Turbopack) 0.422s (+30.4% 🔺) 2.402s (-13.9% 🟢) 1.980s 10 1.56x

🔍 Observability: Nitro | 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.089s (~) 2.007s (~) 0.918s 10 1.00x
💻 Local Express 1.091s (-0.8%) 2.008s (~) 0.917s 10 1.00x
💻 Local Nitro 1.095s (+0.6%) 2.009s (~) 0.915s 10 1.01x
🐘 Postgres Express 1.101s (~) 2.009s (~) 0.908s 10 1.01x
🐘 Postgres Nitro 1.102s (~) 2.010s (~) 0.908s 10 1.01x
🐘 Postgres Next.js (Turbopack) 1.103s (~) 2.009s (~) 0.907s 10 1.01x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 1.658s (+5.0% 🔺) 3.850s (+3.6%) 2.192s 10 1.00x
▲ Vercel Express 1.811s (+19.1% 🔺) 3.717s (+4.1%) 1.905s 10 1.09x
▲ Vercel Nitro 2.141s (+39.0% 🔺) 4.179s (+19.0% 🔺) 2.038s 10 1.29x

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

workflow with 10 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 10.493s (~) 11.018s (~) 0.525s 3 1.00x
💻 Local Nitro 10.506s (~) 11.022s (~) 0.515s 3 1.00x
💻 Local Next.js (Turbopack) 10.526s (~) 11.023s (~) 0.497s 3 1.00x
💻 Local Express 10.545s (~) 11.024s (~) 0.479s 3 1.00x
🐘 Postgres Nitro 10.551s (~) 11.018s (~) 0.467s 3 1.01x
🐘 Postgres Next.js (Turbopack) 10.573s (~) 11.019s (~) 0.446s 3 1.01x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 13.926s (+5.6% 🔺) 15.677s (+2.0%) 1.751s 2 1.00x
▲ Vercel Express 14.147s (+8.0% 🔺) 16.094s (+5.8% 🔺) 1.947s 2 1.02x
▲ Vercel Nitro 14.162s (+10.4% 🔺) 15.585s (+2.1%) 1.423s 2 1.02x

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

workflow with 25 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 13.676s (~) 14.027s (~) 0.351s 5 1.00x
💻 Local Next.js (Turbopack) 13.694s (~) 14.026s (~) 0.332s 5 1.00x
🐘 Postgres Express 13.738s (~) 14.022s (~) 0.284s 5 1.00x
💻 Local Express 13.766s (-1.6%) 14.028s (-1.4%) 0.261s 5 1.01x
🐘 Postgres Next.js (Turbopack) 13.799s (-0.8%) 14.022s (~) 0.222s 5 1.01x
🐘 Postgres Nitro 13.843s (~) 14.018s (~) 0.175s 5 1.01x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 22.711s (+5.6% 🔺) 24.986s (+6.4% 🔺) 2.275s 3 1.00x
▲ Vercel Express 23.267s (+15.4% 🔺) 25.379s (+13.2% 🔺) 2.112s 3 1.02x
▲ Vercel Next.js (Turbopack) 24.475s (+22.7% 🔺) 26.533s (+19.5% 🔺) 2.058s 3 1.08x

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

workflow with 50 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 12.324s (~) 13.024s (~) 0.700s 7 1.00x
💻 Local Express 12.401s (-1.5%) 13.026s (~) 0.624s 7 1.01x
🐘 Postgres Express 12.406s (~) 13.017s (~) 0.611s 7 1.01x
🐘 Postgres Nitro 12.528s (+1.0%) 13.018s (~) 0.490s 7 1.02x
💻 Local Next.js (Turbopack) 12.615s (+1.3%) 13.025s (~) 0.410s 7 1.02x
🐘 Postgres Next.js (Turbopack) 13.013s (+3.8%) 13.444s (+3.3%) 0.432s 7 1.06x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 30.595s (+32.9% 🔺) 32.579s (+29.5% 🔺) 1.984s 3 1.00x
▲ Vercel Nitro 30.878s (+24.9% 🔺) 33.018s (+23.7% 🔺) 2.140s 3 1.01x
▲ Vercel Next.js (Turbopack) 33.056s (+31.4% 🔺) 34.715s (+26.5% 🔺) 1.658s 3 1.08x

🔍 Observability: Express | Nitro | 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.173s (+1.2%) 2.008s (~) 0.835s 15 1.00x
🐘 Postgres Nitro 1.177s (-0.9%) 2.008s (~) 0.830s 15 1.00x
🐘 Postgres Express 1.204s (+0.7%) 2.008s (~) 0.805s 15 1.03x
💻 Local Nitro 1.241s (+3.2%) 2.006s (~) 0.765s 15 1.06x
💻 Local Express 1.242s (+0.9%) 2.006s (~) 0.764s 15 1.06x
💻 Local Next.js (Turbopack) 1.284s (-6.6% 🟢) 2.006s (~) 0.722s 15 1.09x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.484s (-7.8% 🟢) 4.290s (-3.8%) 1.806s 8 1.00x
▲ Vercel Next.js (Turbopack) 2.566s (-1.0%) 4.017s (-9.3% 🟢) 1.450s 8 1.03x
▲ Vercel Nitro 2.805s (+6.0% 🔺) 4.681s (+5.1% 🔺) 1.876s 7 1.13x

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

Promise.all with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.249s (-1.6%) 2.008s (~) 0.759s 15 1.00x
🐘 Postgres Next.js (Turbopack) 1.257s (~) 2.008s (~) 0.751s 15 1.01x
🐘 Postgres Express 1.350s (+3.2%) 2.316s (+11.7% 🔺) 0.967s 13 1.08x
💻 Local Nitro 1.998s (-0.9%) 2.220s (-11.4% 🟢) 0.223s 14 1.60x
💻 Local Express 2.045s (+0.5%) 2.736s (+9.1% 🔺) 0.691s 11 1.64x
💻 Local Next.js (Turbopack) 2.105s (-10.2% 🟢) 2.507s (-14.1% 🟢) 0.403s 12 1.69x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 3.166s (+27.3% 🔺) 5.003s (+23.3% 🔺) 1.837s 6 1.00x
▲ Vercel Next.js (Turbopack) 3.376s (+6.0% 🔺) 5.474s (+6.8% 🔺) 2.097s 6 1.07x
▲ Vercel Express 3.456s (+21.9% 🔺) 5.017s (+9.3% 🔺) 1.561s 6 1.09x

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

Promise.all with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.408s (-2.9%) 3.566s (-3.1%) 2.158s 9 1.00x
🐘 Postgres Express 1.436s (-13.4% 🟢) 3.678s (-2.2%) 2.242s 9 1.02x
🐘 Postgres Next.js (Turbopack) 1.482s (~) 3.886s (~) 2.404s 8 1.05x
💻 Local Nitro 5.550s (+23.8% 🔺) 6.014s (+20.0% 🔺) 0.464s 5 3.94x
💻 Local Express 5.660s (-1.9%) 6.216s (-3.1%) 0.555s 5 4.02x
💻 Local Next.js (Turbopack) 5.896s (-11.9% 🟢) 6.215s (-16.2% 🟢) 0.319s 5 4.19x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 4.262s (+38.7% 🔺) 6.328s (+28.8% 🔺) 2.066s 5 1.00x
▲ Vercel Express 4.290s (+39.6% 🔺) 6.211s (+26.0% 🔺) 1.922s 6 1.01x
▲ Vercel Next.js (Turbopack) 4.633s (+32.3% 🔺) 6.567s (+20.9% 🔺) 1.934s 5 1.09x

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

Promise.race with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Next.js (Turbopack) 1.167s (-0.5%) 2.008s (~) 0.841s 15 1.00x
🐘 Postgres Nitro 1.189s (-0.9%) 2.008s (~) 0.819s 15 1.02x
🐘 Postgres Express 1.198s (~) 2.007s (~) 0.809s 15 1.03x
💻 Local Express 1.222s (-0.7%) 2.007s (~) 0.785s 15 1.05x
💻 Local Nitro 1.236s (+0.6%) 2.006s (~) 0.770s 15 1.06x
💻 Local Next.js (Turbopack) 1.377s (+1.9%) 2.006s (~) 0.629s 15 1.18x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 2.459s (+15.0% 🔺) 4.007s (-1.2%) 1.547s 8 1.00x
▲ Vercel Express 2.502s (+23.6% 🔺) 4.289s (+9.8% 🔺) 1.787s 8 1.02x
▲ Vercel Nitro 2.786s (+28.6% 🔺) 4.454s (+14.9% 🔺) 1.667s 7 1.13x

🔍 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 🥇 Next.js (Turbopack) 1.254s (-0.8%) 2.008s (-3.2%) 0.754s 15 1.00x
🐘 Postgres Nitro 1.265s (-0.8%) 2.008s (~) 0.743s 15 1.01x
🐘 Postgres Express 1.279s (-1.2%) 2.008s (~) 0.728s 15 1.02x
💻 Local Express 2.003s (-1.7%) 2.592s (-5.3% 🟢) 0.590s 12 1.60x
💻 Local Nitro 2.211s (+10.0% 🔺) 2.737s (+18.3% 🔺) 0.526s 11 1.76x
💻 Local Next.js (Turbopack) 2.505s (+3.6%) 2.918s (~) 0.413s 11 2.00x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 2.965s (+8.1% 🔺) 4.907s (+14.2% 🔺) 1.941s 7 1.00x
▲ Vercel Express 3.451s (+33.7% 🔺) 5.436s (+25.0% 🔺) 1.985s 6 1.16x
▲ Vercel Next.js (Turbopack) 3.519s (+32.1% 🔺) 5.486s (+31.8% 🔺) 1.967s 6 1.19x

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

Promise.race with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.427s (-2.0%) 4.260s (+13.3% 🔺) 2.833s 8 1.00x
🐘 Postgres Next.js (Turbopack) 1.454s (-1.1%) 4.135s (+6.4% 🔺) 2.682s 8 1.02x
🐘 Postgres Express 1.504s (+5.1% 🔺) 3.760s (~) 2.255s 8 1.05x
💻 Local Express 5.732s (-3.9%) 6.015s (-11.7% 🟢) 0.284s 5 4.02x
💻 Local Nitro 5.805s (+17.4% 🔺) 6.212s (+12.7% 🔺) 0.408s 5 4.07x
💻 Local Next.js (Turbopack) 6.340s (-6.6% 🟢) 7.015s (-6.7% 🟢) 0.676s 5 4.44x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 3.914s (-11.1% 🟢) 5.684s (-13.5% 🟢) 1.770s 6 1.00x
▲ Vercel Next.js (Turbopack) 4.205s (+27.2% 🔺) 5.888s (+12.0% 🔺) 1.683s 6 1.07x
▲ Vercel Express 4.382s (+3.0%) 6.207s (+1.9%) 1.825s 5 1.12x

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

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 0.553s (-3.1%) 1.005s (-1.7%) 0.452s 60 1.00x
🐘 Postgres Express 0.554s (-3.9%) 1.023s (~) 0.470s 59 1.00x
🐘 Postgres Next.js (Turbopack) 0.560s (-1.0%) 1.023s (~) 0.463s 59 1.01x
💻 Local Next.js (Turbopack) 0.576s (-5.7% 🟢) 1.005s (-1.7%) 0.429s 60 1.04x
💻 Local Express 0.586s (-3.9%) 1.005s (~) 0.419s 60 1.06x
🐘 Postgres Nitro 0.663s (+18.1% 🔺) 1.118s (+9.3% 🔺) 0.454s 54 1.20x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 3.683s (+22.3% 🔺) 5.610s (+11.2% 🔺) 1.927s 11 1.00x
▲ Vercel Express 4.315s (+25.8% 🔺) 6.189s (+14.0% 🔺) 1.874s 10 1.17x
▲ Vercel Next.js (Turbopack) 4.361s (+5.5% 🔺) 6.296s (+0.8%) 1.935s 10 1.18x

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

workflow with 25 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 1.297s (-2.1%) 2.008s (~) 0.711s 45 1.00x
🐘 Postgres Next.js (Turbopack) 1.310s (+2.7%) 2.008s (~) 0.698s 45 1.01x
🐘 Postgres Nitro 1.317s (+3.3%) 2.008s (~) 0.691s 45 1.02x
💻 Local Nitro 1.419s (+2.6%) 2.006s (~) 0.587s 45 1.09x
💻 Local Express 1.478s (-5.2% 🟢) 2.007s (-1.1%) 0.529s 45 1.14x
💻 Local Next.js (Turbopack) 1.481s (~) 2.005s (~) 0.524s 45 1.14x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 9.622s (+26.1% 🔺) 11.486s (+20.9% 🔺) 1.864s 9 1.00x
▲ Vercel Express 10.005s (+16.7% 🔺) 12.161s (+16.6% 🔺) 2.156s 8 1.04x
▲ Vercel Next.js (Turbopack) 10.435s (+27.4% 🔺) 12.496s (+24.9% 🔺) 2.061s 8 1.08x

🔍 Observability: Nitro | Express | 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.503s (-5.7% 🟢) 3.008s (-4.1%) 0.505s 40 1.00x
🐘 Postgres Express 2.522s (-4.3%) 3.058s (~) 0.537s 40 1.01x
🐘 Postgres Next.js (Turbopack) 2.597s (+1.9%) 3.034s (+0.8%) 0.436s 40 1.04x
💻 Local Nitro 3.065s (+2.2%) 3.675s (+6.9% 🔺) 0.611s 33 1.22x
💻 Local Next.js (Turbopack) 3.190s (~) 3.977s (~) 0.787s 31 1.27x
💻 Local Express 3.323s (+2.2%) 4.043s (+0.8%) 0.720s 30 1.33x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 19.626s (+30.5% 🔺) 21.538s (+25.1% 🔺) 1.913s 6 1.00x
▲ Vercel Next.js (Turbopack) 20.214s (+24.8% 🔺) 22.473s (+22.1% 🔺) 2.259s 6 1.03x
▲ Vercel Nitro 20.886s (+25.1% 🔺) 23.365s (+22.8% 🔺) 2.479s 6 1.06x

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

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.191s (+6.5% 🔺) 1.006s (~) 0.816s 60 1.00x
🐘 Postgres Nitro 0.200s (-5.7% 🟢) 1.006s (~) 0.806s 60 1.05x
🐘 Postgres Express 0.217s (-0.9%) 1.006s (~) 0.789s 60 1.14x
💻 Local Nitro 0.318s (-5.7% 🟢) 1.004s (~) 0.686s 60 1.67x
💻 Local Express 0.336s (-1.5%) 1.005s (~) 0.669s 60 1.76x
💻 Local Next.js (Turbopack) 0.600s (-0.8%) 1.005s (~) 0.404s 60 3.15x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 1.521s (+11.2% 🔺) 3.271s (+4.8%) 1.750s 19 1.00x
▲ Vercel Express 1.587s (+25.5% 🔺) 3.206s (+8.4% 🔺) 1.619s 19 1.04x
▲ Vercel Next.js (Turbopack) 1.794s (+36.3% 🔺) 3.408s (+14.6% 🔺) 1.614s 18 1.18x

🔍 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 🥇 Next.js (Turbopack) 0.278s (+3.6%) 1.018s (+1.2%) 0.740s 89 1.00x
🐘 Postgres Nitro 0.298s (-7.8% 🟢) 1.006s (~) 0.709s 90 1.07x
🐘 Postgres Express 0.327s (+1.8%) 1.006s (~) 0.680s 90 1.18x
💻 Local Nitro 1.987s (-1.9%) 2.429s (-1.6%) 0.442s 38 7.15x
💻 Local Express 2.033s (+4.0%) 2.508s (+1.6%) 0.475s 36 7.32x
💻 Local Next.js (Turbopack) 2.655s (~) 3.043s (-1.1%) 0.388s 30 9.56x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.093s (+23.4% 🔺) 3.898s (+10.2% 🔺) 1.805s 24 1.00x
▲ Vercel Nitro 2.207s (+30.2% 🔺) 4.015s (+11.8% 🔺) 1.808s 23 1.05x
▲ Vercel Next.js (Turbopack) 2.497s (+11.4% 🔺) 4.394s (+4.9%) 1.897s 21 1.19x

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

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 0.451s (-13.9% 🟢) 1.128s (+7.5% 🔺) 0.677s 107 1.00x
🐘 Postgres Next.js (Turbopack) 0.498s (+3.3%) 3.009s (-0.8%) 2.511s 40 1.10x
🐘 Postgres Express 0.543s (+10.2% 🔺) 1.088s (+7.3% 🔺) 0.545s 111 1.20x
💻 Local Nitro 9.396s (~) 10.192s (+0.8%) 0.796s 12 20.82x
💻 Local Express 10.129s (+3.5%) 10.940s (+3.1%) 0.812s 11 22.44x
💻 Local Next.js (Turbopack) 10.702s (+6.4% 🔺) 11.847s (+6.6% 🔺) 1.146s 11 23.71x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 3.219s (+46.1% 🔺) 5.016s (+22.1% 🔺) 1.796s 24 1.00x
▲ Vercel Express 3.279s (+35.2% 🔺) 5.080s (+16.1% 🔺) 1.801s 24 1.02x
▲ Vercel Next.js (Turbopack) 4.830s (+36.3% 🔺) 6.685s (+23.4% 🔺) 1.855s 18 1.50x

🔍 Observability: Nitro | 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) 1.153s (~) 2.004s (~) 0.012s (-3.2%) 2.020s (~) 0.867s 10 1.00x
🐘 Postgres Nitro 1.159s (-0.8%) 2.001s (~) 0.001s (-42.1% 🟢) 2.010s (~) 0.851s 10 1.01x
💻 Local Nitro 1.164s (+1.3%) 2.004s (~) 0.012s (+26.1% 🔺) 2.019s (~) 0.854s 10 1.01x
🐘 Postgres Express 1.170s (-0.7%) 1.996s (~) 0.001s (-21.4% 🟢) 2.010s (~) 0.840s 10 1.02x
🐘 Postgres Next.js (Turbopack) 1.174s (~) 2.000s (~) 0.001s (+8.3% 🔺) 2.011s (~) 0.837s 10 1.02x
💻 Local Express 1.175s (~) 2.005s (~) 0.012s (+0.8%) 2.020s (~) 0.845s 10 1.02x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 2.459s (+16.5% 🔺) 3.624s (+7.1% 🔺) 3.327s (+100.5% 🔺) 7.443s (+34.4% 🔺) 4.984s 10 1.00x
▲ Vercel Express 2.529s (+12.0% 🔺) 3.879s (+13.8% 🔺) 2.963s (+9.4% 🔺) 7.352s (+7.9% 🔺) 4.823s 10 1.03x
▲ Vercel Nitro 2.533s (+17.6% 🔺) 3.787s (+11.0% 🔺) 3.498s (+119.8% 🔺) 7.761s (+39.0% 🔺) 5.227s 10 1.03x

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

stream pipeline with 5 transform steps (1MB)

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 1.558s (-1.7%) 2.003s (~) 0.005s (+7.4% 🔺) 2.026s (~) 0.468s 30 1.00x
💻 Local Nitro 1.567s (-0.7%) 2.009s (~) 0.011s (-11.0% 🟢) 2.023s (~) 0.456s 30 1.01x
💻 Local Express 1.591s (~) 2.008s (~) 0.014s (+11.1% 🔺) 2.025s (~) 0.434s 30 1.02x
🐘 Postgres Nitro 1.605s (-2.3%) 2.009s (-1.4%) 0.005s (-8.7% 🟢) 2.025s (-1.6%) 0.420s 30 1.03x
💻 Local Next.js (Turbopack) 1.610s (-0.5%) 2.009s (~) 0.013s (+0.5%) 2.026s (~) 0.416s 30 1.03x
🐘 Postgres Next.js (Turbopack) 1.660s (+3.7%) 2.010s (~) 0.005s (+4.7%) 2.026s (~) 0.366s 30 1.07x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 6.555s (+14.6% 🔺) 8.395s (+10.8% 🔺) 1.024s (+230.2% 🔺) 9.892s (+17.4% 🔺) 3.338s 7 1.00x
▲ Vercel Express 6.746s (+10.0% 🔺) 8.294s (+5.7% 🔺) 0.401s (+41.4% 🔺) 9.156s (+5.6% 🔺) 2.410s 7 1.03x
▲ Vercel Next.js (Turbopack) 6.809s (+14.6% 🔺) 8.330s (+9.6% 🔺) 0.478s (+44.9% 🔺) 9.356s (+10.6% 🔺) 2.547s 7 1.04x

🔍 Observability: Nitro | Express | 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.734s (-3.9%) 1.047s (-1.6%) 0.000s (+Infinity% 🔺) 1.062s (-1.6%) 0.328s 57 1.00x
🐘 Postgres Nitro 0.772s (~) 1.131s (+2.4%) 0.000s (-32.1% 🟢) 1.143s (+2.2%) 0.371s 53 1.05x
🐘 Postgres Next.js (Turbopack) 0.825s (+8.3% 🔺) 1.154s (+6.1% 🔺) 0.000s (+119.2% 🔺) 1.161s (+5.9% 🔺) 0.336s 52 1.12x
💻 Local Nitro 1.335s (-2.2%) 2.013s (~) 0.001s (+25.0% 🔺) 2.015s (~) 0.680s 30 1.82x
💻 Local Express 1.368s (+3.4%) 2.013s (~) 0.000s (+9.1% 🔺) 2.016s (~) 0.649s 30 1.86x
💻 Local Next.js (Turbopack) 1.481s (+2.3%) 2.012s (~) 0.001s (+66.7% 🔺) 2.015s (~) 0.534s 30 2.02x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 3.841s (+13.7% 🔺) 4.976s (-1.4%) 0.000s (-100.0% 🟢) 5.540s (~) 1.700s 11 1.00x
▲ Vercel Nitro 4.069s (-14.4% 🟢) 5.470s (-17.0% 🟢) 0.000s (+Infinity% 🔺) 6.014s (-15.6% 🟢) 1.944s 10 1.06x
▲ Vercel Next.js (Turbopack) 4.095s (-3.2%) 5.514s (-11.3% 🟢) 0.000s (-100.0% 🟢) 6.019s (-11.6% 🟢) 1.924s 10 1.07x

🔍 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.634s (+6.8% 🔺) 2.255s (+7.3% 🔺) 0.000s (-100.0% 🟢) 2.268s (+5.4% 🔺) 0.635s 27 1.00x
🐘 Postgres Nitro 1.641s (-0.8%) 2.260s (+2.0%) 0.000s (-100.0% 🟢) 2.283s (+2.3%) 0.642s 27 1.00x
🐘 Postgres Next.js (Turbopack) 1.920s (+0.6%) 2.545s (~) 0.000s (NaN%) 2.552s (~) 0.632s 24 1.18x
💻 Local Nitro 3.353s (-4.2%) 3.966s (~) 0.001s (-22.2% 🟢) 3.970s (~) 0.616s 16 2.05x
💻 Local Next.js (Turbopack) 3.742s (-9.1% 🟢) 4.312s (-6.3% 🟢) 0.001s (-44.4% 🟢) 4.320s (-6.3% 🟢) 0.578s 14 2.29x
💻 Local Express 3.787s (+4.0%) 4.313s (+2.0%) 0.001s (-3.6%) 4.319s (+2.1%) 0.531s 14 2.32x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 5.508s (-3.2%) 7.375s (+3.3%) 0.001s (+166.7% 🔺) 7.911s (+2.5%) 2.403s 8 1.00x
▲ Vercel Express 5.716s (-30.8% 🟢) 7.036s (-28.7% 🟢) 0.000s (-62.5% 🟢) 7.535s (-27.9% 🟢) 1.820s 8 1.04x
▲ Vercel Next.js (Turbopack) 7.113s (+34.3% 🔺) 8.674s (+27.8% 🔺) 0.000s (NaN%) 9.160s (+25.1% 🔺) 2.047s 7 1.29x

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

Summary

Fastest Framework by World

Winner determined by most benchmark wins

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

Winner determined by most benchmark wins

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

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.

Flight booking app fails with v5 beta release with "received text-delta for missing text part with ID 0"

1 participant