Skip to content

Conversation

@pranaygp
Copy link
Collaborator

@pranaygp pranaygp commented Dec 5, 2025

Add new benchmark workflows to reproduce reported issues with Promise.race
and Promise.all falling over when array sizes exceed a few hundred.

New workflows:

  • promiseAllStressTestWorkflow(count) - Tests Promise.all with many concurrent steps
  • promiseRaceStressTestLargeWorkflow(count) - Tests Promise.race with Map pattern

New benchmarks at 100, 500, and 1000 concurrent step scales for both
Promise.all and Promise.race patterns.

🤖 Generated with Claude Code

Co-Authored-By: Claude [email protected]

Copilot AI review requested due to automatic review settings December 5, 2025 00:25
@changeset-bot
Copy link

changeset-bot bot commented Dec 5, 2025

🦋 Changeset detected

Latest commit: 9487c93

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

This PR includes changesets to release 14 packages
Name Type
@workflow/world-local Patch
@workflow/cli Patch
@workflow/core Patch
@workflow/world-postgres Patch
workflow Patch
@workflow/world-testing Patch
@workflow/builders Patch
@workflow/next Patch
@workflow/nitro Patch
@workflow/web-shared Patch
@workflow/ai Patch
@workflow/astro Patch
@workflow/sveltekit Patch
@workflow/nuxt Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link
Contributor

vercel bot commented Dec 5, 2025

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

Project Deployment Preview Comments Updated (UTC)
example-nextjs-workflow-turbopack Ready Ready Preview Comment Dec 5, 2025 6:22am
example-nextjs-workflow-webpack Ready Ready Preview Comment Dec 5, 2025 6:22am
example-workflow Ready Ready Preview Comment Dec 5, 2025 6:22am
workbench-astro-workflow Ready Ready Preview Comment Dec 5, 2025 6:22am
workbench-express-workflow Ready Ready Preview Comment Dec 5, 2025 6:22am
workbench-fastify-workflow Ready Ready Preview Comment Dec 5, 2025 6:22am
workbench-hono-workflow Ready Ready Preview Comment Dec 5, 2025 6:22am
workbench-nitro-workflow Ready Ready Preview Comment Dec 5, 2025 6:22am
workbench-nuxt-workflow Ready Ready Preview Comment Dec 5, 2025 6:22am
workbench-sveltekit-workflow Ready Ready Preview Comment Dec 5, 2025 6:22am
workbench-vite-workflow Ready Ready Preview Comment Dec 5, 2025 6:22am
workflow-docs Ready Ready Preview Comment Dec 5, 2025 6:22am

@github-actions
Copy link
Contributor

github-actions bot commented Dec 5, 2025

📊 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.030s (-31.6% 🟢) 1.007s (~) 0.976s 10 1.00x
🌐 Redis Next.js (Turbopack) 0.037s (-9.0% 🟢) 1.019s (~) 0.983s 10 1.21x
🌐 Starter Next.js (Turbopack) 0.040s (+16.1% 🔺) 1.015s (~) 0.975s 10 1.31x
💻 Local Next.js (Turbopack) 0.041s (+1.5%) 1.016s (~) 0.975s 10 1.36x
💻 Local Express 0.044s (-1.6%) 1.008s (~) 0.964s 10 1.45x
🐘 Postgres Next.js (Turbopack) 0.123s (-46.7% 🟢) 1.018s (~) 0.895s 10 4.06x
🌐 MongoDB Next.js (Turbopack) 0.129s (+99.4% 🔺) 1.016s (~) 0.888s 10 4.24x
🐘 Postgres Nitro 0.248s (+27.6% 🔺) 1.023s (-0.8%) 0.775s 10 8.20x
🐘 Postgres Express 0.378s (+32.5% 🔺) 1.012s (~) 0.634s 10 12.48x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 0.602s (+20.6% 🔺) 1.592s (+11.9% 🔺) 0.991s 10 1.00x
▲ Vercel Express 0.642s (+38.4% 🔺) 1.517s (+8.8% 🔺) 0.875s 10 1.07x
▲ Vercel Next.js (Turbopack) 0.745s (+12.9% 🔺) 1.695s (+0.6%) 0.950s 10 1.24x

workflow with 1 step

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 0.076s (-32.0% 🟢) 1.006s (~) 0.930s 10 1.00x
🌐 Redis Next.js (Turbopack) 0.078s (-20.9% 🟢) 1.013s (~) 0.935s 10 1.03x
🌐 Starter Next.js (Turbopack) 0.081s (+2.1%) 1.011s (~) 0.930s 10 1.07x
💻 Local Next.js (Turbopack) 0.086s (-6.3% 🟢) 1.010s (~) 0.924s 10 1.14x
💻 Local Express 0.113s (~) 1.006s (~) 0.894s 10 1.49x
🌐 MongoDB Next.js (Turbopack) 0.312s (-1.1%) 1.012s (~) 0.699s 10 4.13x
🐘 Postgres Next.js (Turbopack) 0.942s (+8.7% 🔺) 1.115s (+10.0% 🔺) 0.173s 10 12.44x
🐘 Postgres Nitro 1.131s (-22.9% 🟢) 2.012s (~) 0.881s 10 14.94x
🐘 Postgres Express 1.251s (+9.0% 🔺) 2.009s (~) 0.759s 10 16.52x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 1.522s (+8.6% 🔺) 2.603s (+8.1% 🔺) 1.081s 10 1.00x
▲ Vercel Express 1.535s (+8.2% 🔺) 2.462s (+3.6%) 0.927s 10 1.01x
▲ Vercel Nitro 1.599s (+20.5% 🔺) 2.599s (+7.8% 🔺) 1.000s 10 1.05x

workflow with 10 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 0.506s (-34.7% 🟢) 1.005s (~) 0.499s 5 1.00x
🌐 Redis Next.js (Turbopack) 0.514s (-16.2% 🟢) 1.012s (~) 0.499s 5 1.02x
🌐 Starter Next.js (Turbopack) 0.580s (~) 1.010s (~) 0.429s 5 1.15x
💻 Local Next.js (Turbopack) 0.613s (+0.6%) 1.009s (~) 0.396s 5 1.21x
💻 Local Express 0.771s (-0.8%) 1.006s (~) 0.235s 5 1.52x
🌐 MongoDB Next.js (Turbopack) 2.129s (-1.4%) 3.013s (~) 0.884s 5 4.21x
🐘 Postgres Next.js (Turbopack) 5.013s (-4.5%) 5.216s (-13.4% 🟢) 0.203s 5 9.91x
🐘 Postgres Nitro 8.253s (+54.4% 🔺) 8.617s (+43.2% 🔺) 0.364s 5 16.32x
🐘 Postgres Express 9.256s (-11.2% 🟢) 10.018s (-9.1% 🟢) 0.762s 5 18.30x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 10.274s (-38.3% 🟢) 10.904s (-36.0% 🟢) 0.630s 5 1.00x
▲ Vercel Next.js (Turbopack) 10.365s (+6.9% 🔺) 11.236s (+8.0% 🔺) 0.871s 5 1.01x
▲ Vercel Express 10.740s (+6.7% 🔺) 11.328s (+7.3% 🔺) 0.588s 5 1.05x

workflow with 10 parallel steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 0.335s (-15.5% 🟢) 1.005s (~) 0.671s 5 1.00x
🌐 Starter Next.js (Turbopack) 0.365s (+2.2%) 1.008s (~) 0.644s 5 1.09x
💻 Local Next.js (Turbopack) 0.372s (-9.6% 🟢) 1.009s (~) 0.637s 5 1.11x
🌐 Redis Next.js (Turbopack) 0.379s (+6.5% 🔺) 1.011s (~) 0.632s 5 1.13x
💻 Local Express 0.419s (-1.3%) 1.006s (~) 0.588s 5 1.25x
🐘 Postgres Next.js (Turbopack) 0.750s (-9.2% 🟢) 1.013s (-16.5% 🟢) 0.263s 5 2.24x
🐘 Postgres Express 1.106s (-32.4% 🟢) 2.013s (~) 0.907s 5 3.31x
🐘 Postgres Nitro 1.164s (+23.4% 🔺) 1.618s (+14.8% 🔺) 0.454s 5 3.48x
🌐 MongoDB Next.js (Turbopack) 1.592s (+1.1%) 2.009s (~) 0.417s 5 4.76x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.734s (+9.7% 🔺) 3.469s (+1.7%) 0.734s 5 1.00x
▲ Vercel Nitro 2.923s (+7.7% 🔺) 3.679s (+4.0%) 0.756s 5 1.07x
▲ Vercel Next.js (Turbopack) 2.968s (+17.0% 🔺) 3.737s (+9.1% 🔺) 0.769s 5 1.09x

stress test: Promise.all with 100 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🌐 Starter 🥇 Next.js (Turbopack) 1.783s 2.036s 0.253s 15 1.00x
🌐 Redis Next.js (Turbopack) 3.758s 4.073s 0.315s 8 2.11x
🐘 Postgres Next.js (Turbopack) 8.075s 8.403s 0.328s 4 4.53x
💻 Local Nitro 8.217s 8.505s 0.288s 4 4.61x
🐘 Postgres Express 8.232s 8.666s 0.434s 4 4.62x
🐘 Postgres Nitro 8.365s 8.860s 0.495s 4 4.69x
💻 Local Next.js (Turbopack) 10.060s 10.339s 0.279s 3 5.64x
💻 Local Express 11.128s 11.607s 0.480s 3 6.24x
🌐 MongoDB Next.js (Turbopack) 19.788s 20.566s 0.778s 2 11.10x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 17.898s 18.865s 0.967s 2 1.00x
▲ Vercel Nitro 21.856s 22.435s 0.579s 2 1.22x
▲ Vercel Next.js (Turbopack) 23.483s 24.076s 0.594s 2 1.31x

stress test: Promise.race with 100 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🌐 Starter 🥇 Next.js (Turbopack) 2.029s 2.094s 0.065s 15 1.00x
🌐 Redis Next.js (Turbopack) 3.906s 4.362s 0.456s 7 1.93x
🐘 Postgres Next.js (Turbopack) 8.845s 9.083s 0.237s 4 4.36x
🐘 Postgres Nitro 9.212s 9.497s 0.285s 4 4.54x
🐘 Postgres Express 9.417s 9.854s 0.437s 4 4.64x
💻 Local Express 9.762s 10.286s 0.524s 4 4.81x
💻 Local Nitro 10.275s 10.653s 0.378s 3 5.06x
💻 Local Next.js (Turbopack) 11.230s 11.739s 0.509s 3 5.54x
🌐 MongoDB Next.js (Turbopack) 20.093s 20.520s 0.427s 2 9.90x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 15.370s 16.098s 0.728s 2 1.00x
▲ Vercel Nitro 15.832s 16.430s 0.598s 2 1.03x
▲ Vercel Express 16.401s 16.779s 0.377s 2 1.07x

Stream Benchmarks

Stream benchmarks include Time to First Byte (TTFB) metrics.

workflow with stream

💻 Local Development

World Framework Workflow Time TTFB Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 0.114s (-37.0% 🟢) 0.998s (+0.7%) 1.008s (~) 0.894s 10 1.00x
🌐 Redis Next.js (Turbopack) 0.115s (-19.8% 🟢) 1.003s (~) 1.011s (~) 0.896s 10 1.02x
🌐 Starter Next.js (Turbopack) 0.127s (-3.5%) 1.004s (~) 1.008s (~) 0.881s 10 1.12x
💻 Local Next.js (Turbopack) 0.138s (-3.8%) 1.002s (~) 1.013s (~) 0.875s 10 1.22x
💻 Local Express 0.179s (-1.3%) 0.992s (~) 1.009s (~) 0.830s 10 1.58x
🌐 MongoDB Next.js (Turbopack) 0.466s (-2.5%) 0.978s (+0.8%) 1.011s (~) 0.545s 10 4.10x
🐘 Postgres Next.js (Turbopack) 0.662s (-20.4% 🟢) 0.956s (-30.1% 🟢) 1.012s (-28.4% 🟢) 0.350s 10 5.84x
🐘 Postgres Nitro 1.206s (+3.9%) 1.833s (-2.4%) 2.011s (~) 0.805s 10 10.63x
🐘 Postgres Express 1.453s (-31.0% 🟢) 1.587s (-34.8% 🟢) 2.011s (-25.9% 🟢) 0.558s 10 12.80x

▲ Production (Vercel)

World Framework Workflow Time TTFB Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.424s (+7.5% 🔺) 2.842s (+13.3% 🔺) 3.254s (+13.9% 🔺) 0.830s 10 1.00x
▲ Vercel Next.js (Turbopack) 2.555s (+9.7% 🔺) 2.982s (+25.6% 🔺) 3.420s (+22.7% 🔺) 0.865s 10 1.05x
▲ Vercel Nitro 2.558s (+11.2% 🔺) 3.024s (+13.1% 🔺) 3.467s (+11.4% 🔺) 0.909s 10 1.06x

Summary: Fastest Framework by World

Winner determined by most benchmark wins

World 🥇 Fastest Framework Wins
💻 Local Nitro 6/7
🐘 Postgres Next.js (Turbopack) 7/7
▲ Vercel Express 3/7

Summary: Fastest World by Framework

Winner determined by most benchmark wins

Framework 🥇 Fastest World Wins
Express 💻 Local 5/7
Next.js (Turbopack) 🌐 Redis 4/7
Nitro 💻 Local 6/7
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)
  • 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
  • 🌐 Starter: Community world (local development)
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

@github-actions
Copy link
Contributor

github-actions bot commented Dec 5, 2025

🧪 E2E Test Results

Some tests failed

Summary

Passed Failed Skipped Total
⚠️ ▲ Vercel Production 250 0 10 260
✅ 🪟 Windows 26 0 0 26
❌ 🌍 Community Worlds 82 34 0 116
❌ 📋 Other 24 1 1 26
Total 382 35 11 428

❌ Failed Tests

mongodb (🌍 Community Worlds): e2e webhookWorkflow

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

AssertionError: expected 404 to be 202 // Object.is equality
    at /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts:255:24
    at processTicksAndRejections (node:internal/process/tas
redis (🌍 Community Worlds): e2e webhookWorkflow

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

AssertionError: expected 404 to be 200 // Object.is equality
    at /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts:285:25
    at processTicksAndRejections (node:internal/process/tas
starter (🌍 Community Worlds): e2e addTenWorkflow

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

AssertionError: expected {} to match object { …(5) }
    at Proxy.<anonymous> (file:///home/runner/work/workflow/workflow/node_modules/.pnpm/@[email protected]/node_modules/@vitest/expect/dist/index
starter (🌍 Community Worlds): e2e addTenWorkflow

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

AssertionError: expected {} to match object { …(5) }
    at Proxy.<anonymous> (file:///home/runner/work/workflow/workflow/node_modules/.pnpm/@[email protected]/node_modules/@vitest/expect/dist/index
starter (🌍 Community Worlds): e2e retryAttemptCounterWorkflow

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

AssertionError: expected {} to match object { …(3) }
    at Proxy.<anonymous> (file:///home/runner/work/workflow/workflow/node_modules/.pnpm/@[email protected]/node_modules/@vitest/expect/dist/index
starter (🌍 Community Worlds): e2e crossFileErrorWorkflow - stack traces work across imported modules

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

AssertionError: expected undefined to be 'failed' // Object.is equality
    at /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts:647:30
    at processTicksAndRejections (node:internal/
starter (🌍 Community Worlds): e2e hookCleanupTestWorkflow - hook token reuse after workflow completion

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

AssertionError: expected undefined to be 'completed' // Object.is equality
    at /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts:725:31
    at processTicksAndRejections (node:intern
starter (🌍 Community Worlds): e2e stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars)

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

AssertionError: expected undefined to be 'completed' // Object.is equality
    at /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts:748:30
    at processTicksAndRejections (node:intern
starter (🌍 Community Worlds): e2e stepFunctionWithClosureWorkflow - step function with closure variables passed as argument

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

AssertionError: expected undefined to be 'completed' // Object.is equality
    at /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts:784:30
    at processTicksAndRejections (node:intern
starter (🌍 Community Worlds): e2e spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

AssertionError: expected undefined to be 'completed' // Object.is equality
    at /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts:835:36
    at processTicksAndRejections (node:intern
turso (🌍 Community Worlds): e2e addTenWorkflow

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

Error: Failed to trigger workflow: http://localhost:3000/api/trigger?workflowFile=workflows%2F99_e2e.ts&workflowFn=addTenWorkflow 500: 
    at triggerWorkflow (/home/runner/work/workflow/workflow/pack
turso (🌍 Community Worlds): e2e addTenWorkflow

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

Error: Failed to trigger workflow: http://localhost:3000/api/trigger?workflowFile=workflows%2F98_duplicate_case.ts&workflowFn=addTenWorkflow 500: 
    at triggerWorkflow (/home/runner/work/workflow/wo
turso (🌍 Community Worlds): e2e should work with react rendering in step

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

Error: Failed to trigger workflow: http://localhost:3000/api/trigger?workflowFile=workflows%2F8_react_render.tsx&workflowFn=reactWorkflow 500: 
    at triggerWorkflow (/home/runner/work/workflow/workf
turso (🌍 Community Worlds): e2e promiseAllWorkflow

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

Error: Failed to trigger workflow: http://localhost:3000/api/trigger?workflowFile=workflows%2F99_e2e.ts&workflowFn=promiseAllWorkflow 500: 
    at triggerWorkflow (/home/runner/work/workflow/workflow/
turso (🌍 Community Worlds): e2e promiseRaceWorkflow

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

Error: Failed to trigger workflow: http://localhost:3000/api/trigger?workflowFile=workflows%2F99_e2e.ts&workflowFn=promiseRaceWorkflow 500: 
    at triggerWorkflow (/home/runner/work/workflow/workflow
turso (🌍 Community Worlds): e2e promiseAnyWorkflow

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

Error: Failed to trigger workflow: http://localhost:3000/api/trigger?workflowFile=workflows%2F99_e2e.ts&workflowFn=promiseAnyWorkflow 500: 
    at triggerWorkflow (/home/runner/work/workflow/workflow/
turso (🌍 Community Worlds): e2e readableStreamWorkflow

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

Error: Failed to trigger workflow: http://localhost:3000/api/trigger?workflowFile=workflows%2F99_e2e.ts&workflowFn=readableStreamWorkflow 500: 
    at triggerWorkflow (/home/runner/work/workflow/workf
turso (🌍 Community Worlds): e2e hookWorkflow

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

Error: Failed to trigger workflow: http://localhost:3000/api/trigger?workflowFile=workflows%2F99_e2e.ts&workflowFn=hookWorkflow 500: 
    at triggerWorkflow (/home/runner/work/workflow/workflow/packag
turso (🌍 Community Worlds): e2e webhookWorkflow

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

Error: Failed to trigger workflow: http://localhost:3000/api/trigger?workflowFile=workflows%2F99_e2e.ts&workflowFn=webhookWorkflow 500: 
    at triggerWorkflow (/home/runner/work/workflow/workflow/pac
turso (🌍 Community Worlds): e2e sleepingWorkflow

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

Error: Failed to trigger workflow: http://localhost:3000/api/trigger?workflowFile=workflows%2F99_e2e.ts&workflowFn=sleepingWorkflow 500: 
    at triggerWorkflow (/home/runner/work/workflow/workflow/pa
turso (🌍 Community Worlds): e2e nullByteWorkflow

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

Error: Failed to trigger workflow: http://localhost:3000/api/trigger?workflowFile=workflows%2F99_e2e.ts&workflowFn=nullByteWorkflow 500: 
    at triggerWorkflow (/home/runner/work/workflow/workflow/pa
turso (🌍 Community Worlds): e2e workflowAndStepMetadataWorkflow

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

Error: Failed to trigger workflow: http://localhost:3000/api/trigger?workflowFile=workflows%2F99_e2e.ts&workflowFn=workflowAndStepMetadataWorkflow 500: 
    at triggerWorkflow (/home/runner/work/workf
turso (🌍 Community Worlds): e2e outputStreamWorkflow

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

Error: Failed to trigger workflow: http://localhost:3000/api/trigger?workflowFile=workflows%2F99_e2e.ts&workflowFn=outputStreamWorkflow 500: 
    at triggerWorkflow (/home/runner/work/workflow/workflo
turso (🌍 Community Worlds): e2e outputStreamInsideStepWorkflow - getWritable() called inside step functions

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

Error: Failed to trigger workflow: http://localhost:3000/api/trigger?workflowFile=workflows%2F99_e2e.ts&workflowFn=outputStreamInsideStepWorkflow 500: 
    at triggerWorkflow (/home/runner/work/workfl
turso (🌍 Community Worlds): e2e fetchWorkflow

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

Error: Failed to trigger workflow: http://localhost:3000/api/trigger?workflowFile=workflows%2F99_e2e.ts&workflowFn=fetchWorkflow 500: 
    at triggerWorkflow (/home/runner/work/workflow/workflow/packa
turso (🌍 Community Worlds): e2e promiseRaceStressTestWorkflow

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

Error: Failed to trigger workflow: http://localhost:3000/api/trigger?workflowFile=workflows%2F99_e2e.ts&workflowFn=promiseRaceStressTestWorkflow 500: 
    at triggerWorkflow (/home/runner/work/workflo
turso (🌍 Community Worlds): e2e retryAttemptCounterWorkflow

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

Error: Failed to trigger workflow: http://localhost:3000/api/trigger?workflowFile=workflows%2F99_e2e.ts&workflowFn=retryAttemptCounterWorkflow 500: 
    at triggerWorkflow (/home/runner/work/workflow/
turso (🌍 Community Worlds): e2e retryableAndFatalErrorWorkflow

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

Error: Failed to trigger workflow: http://localhost:3000/api/trigger?workflowFile=workflows%2F99_e2e.ts&workflowFn=retryableAndFatalErrorWorkflow 500: 
    at triggerWorkflow (/home/runner/work/workfl
turso (🌍 Community Worlds): e2e crossFileErrorWorkflow - stack traces work across imported modules

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

Error: Failed to trigger workflow: http://localhost:3000/api/trigger?workflowFile=workflows%2F99_e2e.ts&workflowFn=crossFileErrorWorkflow 500: 
    at triggerWorkflow (/home/runner/work/workflow/workf
turso (🌍 Community Worlds): e2e hookCleanupTestWorkflow - hook token reuse after workflow completion

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

Error: Failed to trigger workflow: http://localhost:3000/api/trigger?workflowFile=workflows%2F99_e2e.ts&workflowFn=hookCleanupTestWorkflow 500: 
    at triggerWorkflow (/home/runner/work/workflow/work
turso (🌍 Community Worlds): e2e stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars)

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

Error: Failed to trigger workflow: http://localhost:3000/api/trigger?workflowFile=workflows%2F99_e2e.ts&workflowFn=stepFunctionPassingWorkflow 500: 
    at triggerWorkflow (/home/runner/work/workflow/
turso (🌍 Community Worlds): e2e stepFunctionWithClosureWorkflow - step function with closure variables passed as argument

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

Error: Failed to trigger workflow: http://localhost:3000/api/trigger?workflowFile=workflows%2F99_e2e.ts&workflowFn=stepFunctionWithClosureWorkflow 500: 
    at triggerWorkflow (/home/runner/work/workf
turso (🌍 Community Worlds): e2e closureVariableWorkflow - nested step functions with closure variables

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

Error: Failed to trigger workflow: http://localhost:3000/api/trigger?workflowFile=workflows%2F99_e2e.ts&workflowFn=closureVariableWorkflow 500: 
    at triggerWorkflow (/home/runner/work/workflow/work
turso (🌍 Community Worlds): e2e spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

Error: Failed to trigger workflow: http://localhost:3000/api/trigger?workflowFile=workflows%2F99_e2e.ts&workflowFn=spawnWorkflowFromStepWorkflow 500: 
    at triggerWorkflow (/home/runner/work/workflo
e2e-vercel-prod-fastify (📋 Other): e2e sleepingWorkflow

File: /home/runner/work/workflow/workflow/packages/core/e2e/e2e.test.ts

Error: STACK_TRACE_ERROR
    at task (file:///home/runner/work/workflow/workflow/node_modules/.pnpm/@[email protected]/node_modules/@vitest/runner/dist/chunk-hooks.js:638:27)
    at Object.<anonymou

Details by Category

⚠️ ▲ Vercel Production
App Passed Failed Skipped
⚠️ astro 25 0 1
⚠️ example 25 0 1
⚠️ express 25 0 1
⚠️ hono 25 0 1
⚠️ nextjs-turbopack 25 0 1
⚠️ nextjs-webpack 25 0 1
⚠️ nitro 25 0 1
⚠️ nuxt 25 0 1
⚠️ sveltekit 25 0 1
⚠️ vite 25 0 1
✅ 🪟 Windows
App Passed Failed Skipped
✅ nextjs-turbopack 26 0 0
❌ 🌍 Community Worlds
App Passed Failed Skipped
✅ mongodb-dev 3 0 0
❌ mongodb 25 1 0
✅ redis-dev 3 0 0
❌ redis 25 1 0
✅ starter-dev 3 0 0
❌ starter 18 8 0
✅ turso-dev 3 0 0
❌ turso 2 24 0
❌ 📋 Other
App Passed Failed Skipped
❌ e2e-vercel-prod-fastify 24 1 1

⚠️ Some E2E test jobs failed:

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

Check the workflow run for details.

Copy link
Collaborator Author

pranaygp commented Dec 5, 2025

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds stress test benchmarks to reproduce and measure performance issues with Promise.race and Promise.all when handling hundreds to thousands of concurrent steps. The benchmarks test workflow execution at 100, 500, and 1000 concurrent step scales.

  • Adds two new stress test workflow functions to isolate concurrent step tracking overhead
  • Introduces six new benchmark tests (3 for Promise.all, 3 for Promise.race) at different scales
  • Uses longer timeout durations and fewer iterations for larger tests to accommodate potential performance degradation

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
workbench/example/workflows/97_bench.ts Adds stressTestStep, promiseAllStressTestWorkflow, and promiseRaceStressTestLargeWorkflow to test concurrent step handling at scale
packages/core/e2e/bench.bench.ts Adds 6 new benchmark tests for Promise.all and Promise.race patterns with 100/500/1000 concurrent steps, using appropriate timeout and iteration configurations

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +121 to +123
const result = await Promise.race(runningTasks.values());
done.push(result);
runningTasks.delete(result);
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

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

The Promise.race pattern has a logical bug. The Map is keyed by index i, but runningTasks.delete(result) attempts to delete using the result value (which equals i since stressTestStep(i) returns i). While this happens to work when result equals the key, it creates a tight coupling and will fail if the step returns any value different from its input.

Additionally, this doesn't correctly track which promise completed. Since multiple tasks can have the same result value, deleting by result could remove the wrong task or fail to remove any task if the result doesn't match a key.

Consider using Promise.race with an array of objects that include both the promise and its key:

const runningTasks = new Map<number, Promise<number>>();
for (let i = 0; i < count; i++) {
  runningTasks.set(i, stressTestStep(i));
}

const done: number[] = [];
while (runningTasks.size > 0) {
  const entries = Array.from(runningTasks.entries());
  const racePromises = entries.map(([key, promise]) => 
    promise.then(result => ({ key, result }))
  );
  const { key, result } = await Promise.race(racePromises);
  done.push(result);
  runningTasks.delete(key);
}
Suggested change
const result = await Promise.race(runningTasks.values());
done.push(result);
runningTasks.delete(result);
const entries = Array.from(runningTasks.entries());
const racePromises = entries.map(([key, promise]) =>
promise.then(result => ({ key, result }))
);
const { key, result } = await Promise.race(racePromises);
done.push(result);
runningTasks.delete(key);

Copilot uses AI. Check for mistakes.
pranaygp and others added 5 commits December 4, 2025 22:13
Add new benchmark workflows to reproduce reported issues with Promise.race
and Promise.all falling over when array sizes exceed a few hundred.

New workflows:
- promiseAllStressTestWorkflow(count) - Tests Promise.all with many concurrent steps
- promiseRaceStressTestLargeWorkflow(count) - Tests Promise.race with Map pattern

New benchmarks at 100, 500, and 1000 concurrent step scales for both
Promise.all and Promise.race patterns.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
- Add in-memory cache for file existence checks to avoid expensive fs.access() calls
- Increase default concurrency limit from 20 to 100
- Improve HTTP connection pooling (100 connections, 30s keep-alive)

These optimizations significantly improve performance when running workflows
with many concurrent steps (100+).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Skip warmup iterations and run only 1 sample for stress tests
to reduce CI time while still catching the reported issue.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Temporarily skip the high-concurrency benchmarks (500/1000 steps) to
avoid CI issues while we implement performance optimizations.

See beads issue wrk-fyx for the optimization plan.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@pranaygp pranaygp force-pushed the pranaygp/12-04-add_stress_test_benchmarks_for_large_concurrent_step_counts branch from 369a873 to 9487c93 Compare December 5, 2025 06:20
@pranaygp pranaygp marked this pull request as ready for review December 5, 2025 08:05
{ time: 60000, iterations: 1, warmupIterations: 0, teardown }
);

// TODO: Re-enable after performance optimizations (see beads issue wrk-fyx)
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we also be stress testing for Promise.allSettled?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Can add more in a future PR but should be no different than Promise.all where everything succeeds

Will need to add a new step that throws errors too, to stress test retrying steps that fail

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'm gonna make sure these tests are performant with the incoming PRs, and make sure they don't break (hence why I disabled 500 and 1k) and then will add more teats

@pranaygp pranaygp merged commit 48b3a12 into main Dec 5, 2025
94 of 95 checks passed
@pranaygp pranaygp deleted the pranaygp/12-04-add_stress_test_benchmarks_for_large_concurrent_step_counts branch December 5, 2025 22:20
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.

4 participants