Skip to content

[world-vercel] Retry transient response-body parse failures in the HTTP client#2204

Merged
pranaygp merged 3 commits into
mainfrom
peter/world-vercel-retry-parse-failures
Jun 1, 2026
Merged

[world-vercel] Retry transient response-body parse failures in the HTTP client#2204
pranaygp merged 3 commits into
mainfrom
peter/world-vercel-retry-parse-failures

Conversation

@VaguelySerious
Copy link
Copy Markdown
Member

@VaguelySerious VaguelySerious commented Jun 1, 2026

Problem

A sporadic failure reading or decoding a successful (2xx) response body - for example, a truncated or terminated stream, a connection reset mid-body, or a gateway returning a non-CBOR/JSON body - surfaces as a PARSE_ERROR.

The shared RetryAgent in http-client.ts retries connection and 5xx failures, but body consumption happens after it has handed back the response, so transient response-body failures do not reach that retry logic.

Approach

@workflow/world-vercel now retries response-body read/decode failures directly in makeRequest with bounded exponential backoff:

  • MAX_BODY_PARSE_RETRIES = 2
  • BODY_PARSE_RETRY_BASE_MS = 100
  • retries are limited to idempotent requests (GET/HEAD)

This covers the reported events.list failure path while avoiding retries for writes that may already have been applied. Schema-validation failures remain non-retryable because retrying the same decoded payload would not make it valid.

If an idempotent request continues to fail after the retry budget is exhausted, or if a non-idempotent request encounters a body-parse failure, makeRequest continues to surface a PARSE_ERROR.

Tests

  • packages/world-vercel/src/utils.test.ts: a GET retries a transient body-read failure and then succeeds.
  • packages/world-vercel/src/utils.test.ts: a GET exhausts the retry budget and throws PARSE_ERROR.
  • packages/world-vercel/src/utils.test.ts: a POST body-parse failure is not retried.

…e HTTP client

A sporadic failure reading/decoding a 2xx response body (truncated or
terminated stream, connection reset mid-body, or a gateway returning a
non-CBOR/JSON body) was surfaced immediately as a PARSE_ERROR. The
shared RetryAgent only retries connection/5xx failures — body
consumption happens after it returns the response, so these escape its
retry logic.

Retry such failures inside `makeRequest` with bounded exponential
backoff, scoped to idempotent methods (GET/HEAD) so writes are never
replayed. This fixes the reported `events.list` parse failure at the
adapter layer.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@VaguelySerious VaguelySerious requested a review from a team as a code owner June 1, 2026 19:18
@vercel
Copy link
Copy Markdown
Contributor

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

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Jun 1, 2026

🦋 Changeset detected

Latest commit: 1706a5e

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

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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 1, 2026

🧪 E2E Test Results

All tests passed

Summary

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

Details by Category

✅ ▲ Vercel Production
App Passed Failed Skipped
✅ astro 109 0 26
✅ example 109 0 26
✅ express 109 0 26
✅ fastify 109 0 26
✅ hono 109 0 26
✅ nextjs-turbopack 133 0 2
✅ nextjs-webpack 133 0 2
✅ nitro 109 0 26
✅ nuxt 109 0 26
✅ sveltekit 128 0 7
✅ vite 109 0 26
✅ 💻 Local Development
App Passed Failed Skipped
✅ astro-stable 110 0 25
✅ express-stable 110 0 25
✅ fastify-stable 110 0 25
✅ hono-stable 110 0 25
✅ nextjs-turbopack-canary 116 0 19
✅ nextjs-turbopack-stable-lazy-discovery-disabled 135 0 0
✅ nextjs-turbopack-stable-lazy-discovery-enabled 135 0 0
✅ nextjs-webpack-canary 116 0 19
✅ nextjs-webpack-stable-lazy-discovery-disabled 135 0 0
✅ nextjs-webpack-stable-lazy-discovery-enabled 135 0 0
✅ nitro-stable 110 0 25
✅ nuxt-stable 110 0 25
✅ sveltekit-stable 129 0 6
✅ vite-stable 110 0 25
✅ 📦 Local Production
App Passed Failed Skipped
✅ astro-stable 110 0 25
✅ express-stable 110 0 25
✅ fastify-stable 110 0 25
✅ hono-stable 110 0 25
✅ nextjs-turbopack-canary 116 0 19
✅ nextjs-turbopack-stable-lazy-discovery-disabled 135 0 0
✅ nextjs-turbopack-stable-lazy-discovery-enabled 135 0 0
✅ nextjs-webpack-canary 116 0 19
✅ nextjs-webpack-stable-lazy-discovery-disabled 135 0 0
✅ nextjs-webpack-stable-lazy-discovery-enabled 135 0 0
✅ nitro-stable 110 0 25
✅ nuxt-stable 110 0 25
✅ sveltekit-stable 129 0 6
✅ vite-stable 110 0 25
✅ 🐘 Local Postgres
App Passed Failed Skipped
✅ astro-stable 110 0 25
✅ express-stable 110 0 25
✅ fastify-stable 110 0 25
✅ hono-stable 110 0 25
✅ nextjs-turbopack-canary 116 0 19
✅ nextjs-turbopack-stable-lazy-discovery-disabled 135 0 0
✅ nextjs-turbopack-stable-lazy-discovery-enabled 135 0 0
✅ nextjs-webpack-canary 116 0 19
✅ nextjs-webpack-stable-lazy-discovery-disabled 135 0 0
✅ nextjs-webpack-stable-lazy-discovery-enabled 135 0 0
✅ nitro-stable 110 0 25
✅ nuxt-stable 110 0 25
✅ sveltekit-stable 129 0 6
✅ vite-stable 110 0 25
✅ 🪟 Windows
App Passed Failed Skipped
✅ nextjs-turbopack 135 0 0
✅ 📋 Other
App Passed Failed Skipped
✅ e2e-local-dev-nest-stable 110 0 25
✅ e2e-local-dev-tanstack-start- 110 0 25
✅ e2e-local-postgres-nest-stable 110 0 25
✅ e2e-local-postgres-tanstack-start- 110 0 25
✅ e2e-local-prod-nest-stable 110 0 25
✅ e2e-local-prod-tanstack-start- 110 0 25
✅ e2e-vercel-prod-tanstack-start 109 0 26

📋 View full workflow run

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 1, 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.032s (-28.7% 🟢) 1.004s (~) 0.973s 10 1.00x
💻 Local Nitro 0.041s (-4.4%) 1.006s (~) 0.965s 10 1.30x
🐘 Postgres Express 0.061s (+4.5%) 1.013s (~) 0.953s 10 1.92x
💻 Local Next.js (Turbopack) 0.061s 1.006s 0.945s 10 1.92x
🐘 Postgres Nitro 0.061s (-36.1% 🟢) 1.012s (-3.0%) 0.951s 10 1.92x
🐘 Postgres Next.js (Turbopack) 0.073s 1.012s 0.939s 10 2.30x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 0.322s (+36.7% 🔺) 2.162s (+1.2%) 1.840s 10 1.00x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express

workflow with 1 step

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Express 1.080s (-4.0%) 2.005s (~) 0.925s 10 1.00x
💻 Local Nitro 1.093s (-3.4%) 2.007s (~) 0.914s 10 1.01x
🐘 Postgres Nitro 1.109s (-2.7%) 2.012s (~) 0.903s 10 1.03x
🐘 Postgres Express 1.110s (-3.2%) 2.010s (~) 0.900s 10 1.03x
💻 Local Next.js (Turbopack) 1.125s 2.006s 0.881s 10 1.04x
🐘 Postgres Next.js (Turbopack) 1.150s 2.011s 0.861s 10 1.06x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 1.625s (-13.3% 🟢) 3.269s (-14.1% 🟢) 1.644s 10 1.00x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express

workflow with 10 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Express 10.422s (-4.6%) 11.020s (~) 0.598s 3 1.00x
🐘 Postgres Nitro 10.516s (-3.3%) 11.019s (~) 0.503s 3 1.01x
🐘 Postgres Express 10.522s (-4.0%) 11.020s (~) 0.498s 3 1.01x
💻 Local Nitro 10.533s (-3.8%) 11.022s (~) 0.489s 3 1.01x
💻 Local Next.js (Turbopack) 10.782s 11.022s 0.240s 3 1.03x
🐘 Postgres Next.js (Turbopack) 11.017s 11.351s 0.334s 3 1.06x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 13.921s (-18.0% 🟢) 15.589s (-22.1% 🟢) 1.668s 2 1.00x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express

workflow with 25 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Express 13.499s (-9.8% 🟢) 14.026s (-6.7% 🟢) 0.527s 5 1.00x
🐘 Postgres Nitro 13.724s (-6.0% 🟢) 14.020s (-6.7% 🟢) 0.296s 5 1.02x
💻 Local Nitro 13.726s (-8.9% 🟢) 14.026s (-12.5% 🟢) 0.300s 5 1.02x
🐘 Postgres Express 13.759s (-5.7% 🟢) 14.022s (-6.7% 🟢) 0.263s 5 1.02x
💻 Local Next.js (Turbopack) 14.266s 15.030s 0.764s 4 1.06x
🐘 Postgres Next.js (Turbopack) 14.520s 15.023s 0.502s 4 1.08x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 23.725s (-52.8% 🟢) 25.550s (-51.4% 🟢) 1.825s 3 1.00x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express

workflow with 50 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Express 11.936s (-28.1% 🟢) 12.146s (-28.7% 🟢) 0.210s 8 1.00x
💻 Local Nitro 12.404s (-26.1% 🟢) 13.024s (-23.5% 🟢) 0.619s 7 1.04x
🐘 Postgres Nitro 12.423s (-11.1% 🟢) 13.015s (-9.0% 🟢) 0.592s 7 1.04x
🐘 Postgres Express 12.455s (-11.1% 🟢) 13.018s (-10.8% 🟢) 0.563s 7 1.04x
💻 Local Next.js (Turbopack) 13.624s 14.027s 0.403s 7 1.14x
🐘 Postgres Next.js (Turbopack) 14.026s 14.450s 0.423s 7 1.18x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 32.073s (-73.5% 🟢) 33.644s (-72.8% 🟢) 1.571s 3 1.00x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express

Promise.all with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 1.175s (-6.8% 🟢) 2.008s (~) 0.833s 15 1.00x
🐘 Postgres Nitro 1.190s (-6.7% 🟢) 2.008s (~) 0.818s 15 1.01x
💻 Local Express 1.239s (-16.8% 🟢) 2.006s (~) 0.767s 15 1.05x
💻 Local Nitro 1.261s (-22.7% 🟢) 2.007s (-3.3%) 0.745s 15 1.07x
🐘 Postgres Next.js (Turbopack) 1.265s 2.009s 0.743s 15 1.08x
💻 Local Next.js (Turbopack) 1.334s 2.006s 0.671s 15 1.14x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 3.085s (+7.9% 🔺) 4.749s (+2.7%) 1.664s 7 1.00x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express

Promise.all with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.261s (-46.4% 🟢) 2.007s (-33.3% 🟢) 0.746s 15 1.00x
🐘 Postgres Express 1.277s (-45.9% 🟢) 2.007s (-33.3% 🟢) 0.729s 15 1.01x
🐘 Postgres Next.js (Turbopack) 1.416s 2.007s 0.591s 15 1.12x
💻 Local Express 1.611s (-45.4% 🟢) 2.005s (-42.0% 🟢) 0.394s 15 1.28x
💻 Local Next.js (Turbopack) 1.715s 2.075s 0.360s 15 1.36x
💻 Local Nitro 1.827s (-41.9% 🟢) 2.074s (-46.6% 🟢) 0.247s 15 1.45x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 3.533s (-2.4%) 5.137s (+0.5%) 1.605s 6 1.00x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express

Promise.all with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.395s (-59.9% 🟢) 2.008s (-49.9% 🟢) 0.613s 15 1.00x
🐘 Postgres Express 1.440s (-58.7% 🟢) 2.008s (-49.9% 🟢) 0.568s 15 1.03x
🐘 Postgres Next.js (Turbopack) 1.750s 2.395s 0.645s 13 1.25x
💻 Local Express 3.884s (-53.4% 🟢) 4.585s (-49.2% 🟢) 0.700s 7 2.78x
💻 Local Next.js (Turbopack) 4.471s 5.180s 0.709s 6 3.21x
💻 Local Nitro 5.170s (-38.1% 🟢) 5.678s (-37.1% 🟢) 0.508s 6 3.71x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 5.264s (+24.2% 🔺) 6.754s (+10.2% 🔺) 1.490s 5 1.00x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express

Promise.race with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.179s (-6.2% 🟢) 2.009s (~) 0.830s 15 1.00x
🐘 Postgres Express 1.199s (-4.7%) 2.009s (~) 0.810s 15 1.02x
🐘 Postgres Next.js (Turbopack) 1.277s 2.009s 0.732s 15 1.08x
💻 Local Next.js (Turbopack) 1.379s 2.006s 0.627s 15 1.17x
💻 Local Express 1.420s (-25.0% 🟢) 2.005s (-15.2% 🟢) 0.584s 15 1.20x
💻 Local Nitro 1.605s (-13.9% 🟢) 2.007s (-14.3% 🟢) 0.401s 15 1.36x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.809s (+8.8% 🔺) 4.384s (+0.8%) 1.576s 7 1.00x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express

Promise.race with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.241s (-47.0% 🟢) 2.008s (-33.3% 🟢) 0.768s 15 1.00x
🐘 Postgres Express 1.244s (-46.9% 🟢) 2.008s (-33.3% 🟢) 0.764s 15 1.00x
🐘 Postgres Next.js (Turbopack) 1.454s 2.076s 0.622s 15 1.17x
💻 Local Express 1.603s (-48.8% 🟢) 2.005s (-46.7% 🟢) 0.402s 15 1.29x
💻 Local Next.js (Turbopack) 1.948s 2.392s 0.444s 13 1.57x
💻 Local Nitro 2.066s (-32.6% 🟢) 2.507s (-35.5% 🟢) 0.441s 12 1.67x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 4.027s (+26.2% 🔺) 5.316s (+10.9% 🔺) 1.288s 6 1.00x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express

Promise.race with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 1.373s (-60.8% 🟢) 2.008s (-49.9% 🟢) 0.635s 15 1.00x
🐘 Postgres Nitro 1.381s (-60.3% 🟢) 2.008s (-49.9% 🟢) 0.627s 15 1.01x
🐘 Postgres Next.js (Turbopack) 1.763s 2.741s 0.978s 11 1.28x
💻 Local Express 4.181s (-52.5% 🟢) 4.727s (-49.0% 🟢) 0.546s 7 3.05x
💻 Local Next.js (Turbopack) 5.429s 6.019s 0.590s 5 3.95x
💻 Local Nitro 6.071s (-33.6% 🟢) 6.416s (-36.0% 🟢) 0.344s 5 4.42x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 6.699s (+4.4%) 8.283s (+1.3%) 1.584s 4 1.00x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Express 0.506s (-48.5% 🟢) 1.003s (-6.7% 🟢) 0.497s 60 1.00x
🐘 Postgres Express 0.550s (-34.4% 🟢) 1.007s (-1.6%) 0.456s 60 1.09x
🐘 Postgres Nitro 0.560s (-31.7% 🟢) 1.007s (~) 0.447s 60 1.11x
💻 Local Nitro 0.593s (-39.5% 🟢) 1.005s (-8.2% 🟢) 0.411s 60 1.17x
💻 Local Next.js (Turbopack) 0.848s 1.004s 0.156s 60 1.67x
🐘 Postgres Next.js (Turbopack) 0.881s 1.079s 0.198s 56 1.74x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 6.235s (-67.2% 🟢) 7.880s (-63.1% 🟢) 1.645s 8 1.00x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express

workflow with 25 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Express 1.278s (-57.6% 🟢) 2.005s (-44.1% 🟢) 0.727s 45 1.00x
🐘 Postgres Nitro 1.304s (-32.3% 🟢) 2.008s (-4.4%) 0.704s 45 1.02x
🐘 Postgres Express 1.371s (-30.6% 🟢) 2.007s (-11.1% 🟢) 0.636s 45 1.07x
💻 Local Nitro 1.526s (-49.7% 🟢) 2.029s (-46.0% 🟢) 0.503s 45 1.19x
💻 Local Next.js (Turbopack) 2.079s 2.911s 0.832s 31 1.63x
🐘 Postgres Next.js (Turbopack) 2.177s 3.010s 0.832s 30 1.70x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 17.143s (-50.4% 🟢) 19.252s (-47.7% 🟢) 2.109s 5 1.00x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express

workflow with 50 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 2.639s (-35.7% 🟢) 3.059s (-33.6% 🟢) 0.420s 40 1.00x
🐘 Postgres Express 2.671s (-33.1% 🟢) 3.111s (-28.8% 🟢) 0.440s 39 1.01x
💻 Local Express 2.802s (-69.6% 🟢) 3.164s (-68.4% 🟢) 0.363s 38 1.06x
💻 Local Nitro 3.210s (-65.5% 🟢) 4.010s (-60.0% 🟢) 0.800s 30 1.22x
💻 Local Next.js (Turbopack) 4.329s 5.011s 0.682s 24 1.64x
🐘 Postgres Next.js (Turbopack) 4.382s 5.014s 0.632s 24 1.66x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 29.653s (-77.2% 🟢) 31.923s (-75.8% 🟢) 2.270s 4 1.00x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express

workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 0.209s (-26.3% 🟢) 1.006s (~) 0.797s 60 1.00x
🐘 Postgres Express 0.228s (-19.4% 🟢) 1.007s (~) 0.779s 60 1.09x
🐘 Postgres Next.js (Turbopack) 0.312s 1.008s 0.696s 60 1.49x
💻 Local Nitro 0.436s (-28.0% 🟢) 1.004s (-1.7%) 0.569s 60 2.09x
💻 Local Express 0.471s (-15.9% 🟢) 1.095s (+9.1% 🔺) 0.624s 55 2.26x
💻 Local Next.js (Turbopack) 0.579s 1.004s 0.426s 60 2.77x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.863s (+46.5% 🔺) 4.420s (+21.5% 🔺) 1.557s 14 1.00x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express

workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 0.331s (-33.3% 🟢) 1.007s (~) 0.676s 90 1.00x
🐘 Postgres Express 0.360s (-29.5% 🟢) 1.007s (~) 0.647s 90 1.09x
🐘 Postgres Next.js (Turbopack) 0.547s 1.008s 0.461s 90 1.65x
💻 Local Express 1.933s (-23.1% 🟢) 2.403s (-20.1% 🟢) 0.470s 38 5.84x
💻 Local Nitro 2.152s (-15.2% 🟢) 2.767s (-8.1% 🟢) 0.615s 33 6.50x
💻 Local Next.js (Turbopack) 2.281s 3.043s 0.762s 30 6.89x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 4.764s (+56.4% 🔺) 6.210s (+29.2% 🔺) 1.447s 15 1.00x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 0.659s (-16.6% 🟢) 1.007s (~) 0.348s 120 1.00x
🐘 Postgres Express 0.677s (-17.3% 🟢) 1.007s (-1.1%) 0.330s 120 1.03x
🐘 Postgres Next.js (Turbopack) 1.073s 2.010s 0.937s 60 1.63x
💻 Local Express 8.007s (-28.4% 🟢) 8.666s (-27.4% 🟢) 0.659s 14 12.15x
💻 Local Nitro 9.707s (-13.3% 🟢) 10.358s (-11.2% 🟢) 0.651s 12 14.73x
💻 Local Next.js (Turbopack) 10.108s 10.944s 0.835s 12 15.34x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 15.625s (+110.6% 🔺) 17.296s (+87.1% 🔺) 1.671s 7 1.00x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Express

Stream Benchmarks (includes TTFB metrics)
workflow with stream

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Express 1.130s (+467.4% 🔺) 2.004s (+99.5% 🔺) 0.008s (-30.6% 🟢) 2.015s (+97.9% 🔺) 0.885s 10 1.00x
🐘 Postgres Nitro 1.153s (+462.7% 🔺) 1.999s (+100.0% 🔺) 0.001s (-26.7% 🟢) 2.010s (+98.8% 🔺) 0.857s 10 1.02x
💻 Local Nitro 1.164s (+444.5% 🔺) 2.005s (+99.6% 🔺) 0.013s (+2.4%) 2.020s (+98.2% 🔺) 0.856s 10 1.03x
🐘 Postgres Express 1.169s (+469.7% 🔺) 2.001s (+100.3% 🔺) 0.001s (-37.5% 🟢) 2.010s (+98.8% 🔺) 0.842s 10 1.03x
💻 Local Next.js (Turbopack) 1.204s 2.003s 0.010s 2.017s 0.813s 10 1.07x
🐘 Postgres Next.js (Turbopack) 1.248s 2.002s 0.001s 2.011s 0.763s 10 1.11x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.412s (-3.7%) 3.357s (-17.9% 🟢) 2.045s (+112.9% 🔺) 5.866s (+4.9%) 3.454s 10 1.00x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - - -
▲ Vercel Nitro ⚠️ missing - - - - -

🔍 Observability: Express

stream pipeline with 5 transform steps (1MB)

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Express 1.470s (+94.2% 🔺) 2.008s (+95.1% 🔺) 0.009s (-6.2% 🟢) 2.018s (+94.1% 🔺) 0.548s 30 1.00x
🐘 Postgres Nitro 1.573s (+152.0% 🔺) 2.003s (+99.0% 🔺) 0.004s (-4.9%) 2.025s (+98.0% 🔺) 0.452s 30 1.07x
🐘 Postgres Express 1.575s (+150.1% 🔺) 2.008s (+99.5% 🔺) 0.004s (+4.4%) 2.026s (+98.0% 🔺) 0.450s 30 1.07x
💻 Local Nitro 1.586s (+89.1% 🔺) 2.010s (+98.6% 🔺) 0.010s (+5.3% 🔺) 2.021s (+81.1% 🔺) 0.435s 30 1.08x
💻 Local Next.js (Turbopack) 1.723s 2.008s 0.010s 2.021s 0.297s 30 1.17x
🐘 Postgres Next.js (Turbopack) 1.853s 2.010s 0.004s 2.027s 0.174s 30 1.26x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 6.162s (-5.3% 🟢) 7.400s (-7.6% 🟢) 0.324s (-20.8% 🟢) 8.249s (-6.6% 🟢) 2.087s 8 1.00x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - - -
▲ Vercel Nitro ⚠️ missing - - - - -

🔍 Observability: Express

10 parallel streams (1MB each)

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 0.711s (-26.0% 🟢) 1.050s (-17.8% 🟢) 0.000s (+61.4% 🔺) 1.060s (-18.9% 🟢) 0.349s 57 1.00x
🐘 Postgres Nitro 0.712s (-26.5% 🟢) 1.032s (-17.3% 🟢) 0.000s (-100.0% 🟢) 1.053s (-16.3% 🟢) 0.341s 57 1.00x
🐘 Postgres Next.js (Turbopack) 0.919s 1.220s 0.000s 1.236s 0.317s 50 1.29x
💻 Local Express 1.165s (-4.9%) 1.886s (-6.7% 🟢) 0.000s (-34.4% 🟢) 1.888s (-6.7% 🟢) 0.722s 32 1.64x
💻 Local Nitro 1.460s (+19.4% 🔺) 2.013s (~) 0.000s (+266.7% 🔺) 2.016s (~) 0.555s 30 2.05x
💻 Local Next.js (Turbopack) 1.484s 2.012s 0.000s 2.016s 0.532s 30 2.09x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 3.904s (+4.4%) 5.353s (+4.9%) 0.010s (+5300.0% 🔺) 5.807s (+5.0% 🔺) 1.903s 11 1.00x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - - -
▲ Vercel Nitro ⚠️ missing - - - - -

🔍 Observability: Express

fan-out fan-in 10 streams (1MB each)

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.410s (-21.3% 🟢) 2.177s (+1.7%) 0.000s (-100.0% 🟢) 2.195s (+1.0%) 0.785s 28 1.00x
🐘 Postgres Express 1.412s (-20.3% 🟢) 2.066s (-5.1% 🟢) 0.000s (+Infinity% 🔺) 2.111s (-4.0%) 0.699s 29 1.00x
🐘 Postgres Next.js (Turbopack) 1.928s 2.503s 0.000s 2.511s 0.584s 24 1.37x
💻 Local Express 2.337s (-32.6% 🟢) 2.838s (-29.6% 🟢) 0.001s (-26.1% 🟢) 2.843s (-29.6% 🟢) 0.505s 22 1.66x
💻 Local Next.js (Turbopack) 2.887s 3.469s 0.000s 3.473s 0.585s 18 2.05x
💻 Local Nitro 3.439s (+1.5%) 4.027s (~) 0.001s (+62.5% 🔺) 4.030s (~) 0.591s 15 2.44x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 49.701s (+983.4% 🔺) 50.862s (+744.6% 🔺) 0.000s (NaN%) 51.309s (+694.6% 🔺) 1.608s 7 1.00x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - - -
▲ Vercel Nitro ⚠️ missing - - - - -

🔍 Observability: Express

Summary

Fastest Framework by World

Winner determined by most benchmark wins

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

Winner determined by most benchmark wins

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

📋 View full workflow run


Some benchmark jobs failed:

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

Check the workflow run for details.

Pairs with the world-vercel in-adapter retry: when a response-body parse
failure survives the adapter's retries (or comes from a non-idempotent
write that is never retried in-process), it must not fail the run.
Re-throw such transient world errors from the replay loop so they
propagate to the queue handler, which replays the whole run — safe
because replay is idempotent. Schema-validation contract errors stay
fatal.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@pranaygp pranaygp enabled auto-merge (squash) June 1, 2026 20:49
Copy link
Copy Markdown
Contributor

@pranaygp pranaygp left a comment

Choose a reason for hiding this comment

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

Reviewed the current adapter-only diff at 1706a5e61: response-body retries are bounded to idempotent GET/HEAD requests, POST writes are covered as non-retryable, and the PR description now matches the remaining scope. Required checks are green. The non-required Benchmark Vercel (nextjs-turbopack) stream-correctness failure should still be rerun or explicitly accepted before merge.

@pranaygp pranaygp merged commit 7994629 into main Jun 1, 2026
182 of 192 checks passed
@pranaygp pranaygp deleted the peter/world-vercel-retry-parse-failures branch June 1, 2026 20:49
@github-actions github-actions Bot mentioned this pull request Jun 1, 2026
github-actions Bot added a commit that referenced this pull request Jun 1, 2026
…TP client (#2204)

* fix(world-vercel): retry transient response-body parse failures in the HTTP client

A sporadic failure reading/decoding a 2xx response body (truncated or
terminated stream, connection reset mid-body, or a gateway returning a
non-CBOR/JSON body) was surfaced immediately as a PARSE_ERROR. The
shared RetryAgent only retries connection/5xx failures — body
consumption happens after it returns the response, so these escape its
retry logic.

Retry such failures inside `makeRequest` with bounded exponential
backoff, scoped to idempotent methods (GET/HEAD) so writes are never
replayed. This fixes the reported `events.list` parse failure at the
adapter layer.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(core): propagate exhausted transient world errors to the queue

Pairs with the world-vercel in-adapter retry: when a response-body parse
failure survives the adapter's retries (or comes from a non-idempotent
write that is never retried in-process), it must not fail the run.
Re-throw such transient world errors from the replay loop so they
propagate to the queue handler, which replays the whole run — safe
because replay is idempotent. Schema-validation contract errors stay
fatal.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Revert "fix(core): propagate exhausted transient world errors to the queue"

This reverts commit 7bb62e9.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Peter Wielander <mittgfu@gmail.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 1, 2026

Backport PR opened against stable: #2207. Merge conflicts were resolved by AI — please review carefully. (backport job run)

pranaygp added a commit that referenced this pull request Jun 2, 2026
* origin/main:
  [world-vercel] Retry transient response-body parse failures in the HTTP client (#2204)
  Add virtualization to the trace viewer (#2205)
  Trace viewer: scroll-load events past an auto-load cap (#2200)
  fix(core): resolve forwarded stream keys across deployments (#2191)
  [e2e] Improve error labeling in event-log-race-repro CI job (#2190)
  [core] Harden event pagination response parsing (#2180) (#2179)
  Add loading skeleton to the new trace viewer (#2164)
  Add tooltip components + apply on up/down detail pane  (#2163)
  fix(swc-plugin): allow wasm host imports during link (#2174)
  [test] Forward-port reused-sleep replay divergence test (#2172)
  [e2e] Add `event-log-race-repro` label for triggering CI stress-test (#2159)
  Version Packages (beta) (#2162)
  fix(world-local): skip Nov 2025 ghost versions on npm (#2168)
  fix(core,errors): classify SDK encryption failures as RUNTIME_ERROR (#2145)
  [web-shared][web] Fix events tab search (#2107)
  Version Packages (beta) (#2147)
  Allow setting workflow attributes from steps (#2157)
  Better search handling on the trace viewer (#2144)
  [docs] Document experimental attributes feature (#2141)
pranaygp pushed a commit that referenced this pull request Jun 2, 2026
…TP client (#2204) (#2207)

* fix(world-vercel): retry transient response-body parse failures in the HTTP client

A sporadic failure reading/decoding a 2xx response body (truncated or
terminated stream, connection reset mid-body, or a gateway returning a
non-CBOR/JSON body) was surfaced immediately as a PARSE_ERROR. The
shared RetryAgent only retries connection/5xx failures — body
consumption happens after it returns the response, so these escape its
retry logic.

Retry such failures inside `makeRequest` with bounded exponential
backoff, scoped to idempotent methods (GET/HEAD) so writes are never
replayed. This fixes the reported `events.list` parse failure at the
adapter layer.



* fix(core): propagate exhausted transient world errors to the queue

Pairs with the world-vercel in-adapter retry: when a response-body parse
failure survives the adapter's retries (or comes from a non-idempotent
write that is never retried in-process), it must not fail the run.
Re-throw such transient world errors from the replay loop so they
propagate to the queue handler, which replays the whole run — safe
because replay is idempotent. Schema-validation contract errors stay
fatal.



* Revert "fix(core): propagate exhausted transient world errors to the queue"

This reverts commit 7bb62e9.

---------

Signed-off-by: Peter Wielander <mittgfu@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Nathan Rajlich <n@n8.io>
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