Skip to content

Fix 429 retry#1051

Merged
VaguelySerious merged 5 commits into
mainfrom
peter/fix-429-retry
Feb 14, 2026
Merged

Fix 429 retry#1051
VaguelySerious merged 5 commits into
mainfrom
peter/fix-429-retry

Conversation

@VaguelySerious
Copy link
Copy Markdown
Member

No description provided.

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

changeset-bot Bot commented Feb 13, 2026

🦋 Changeset detected

Latest commit: f8fc681

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

This PR includes changesets to release 14 packages
Name Type
@workflow/core Patch
@workflow/builders Patch
@workflow/cli Patch
@workflow/next Patch
@workflow/nitro Patch
@workflow/web-shared Patch
workflow Patch
@workflow/astro Patch
@workflow/nest Patch
@workflow/rollup Patch
@workflow/sveltekit Patch
@workflow/vite Patch
@workflow/world-testing 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
Copy Markdown
Contributor

vercel Bot commented Feb 13, 2026

@VaguelySerious VaguelySerious marked this pull request as ready for review February 13, 2026 22:09
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 13, 2026

🧪 E2E Test Results

⚠️ Results below are stale and not from the latest commit. This comment will be updated when CI completes on the latest run.

Tests are running...


Started at: 2026-02-14T00:26:38Z


Some tests failed

Summary

Passed Failed Skipped Total
✅ ▲ Vercel Production 501 0 38 539
✅ 💻 Local Development 520 0 68 588
✅ 📦 Local Production 520 0 68 588
✅ 🐘 Local Postgres 520 0 68 588
✅ 🪟 Windows 46 0 3 49
❌ 🌍 Community Worlds 105 42 9 156
✅ 📋 Other 126 0 21 147
Total 2338 42 275 2655

❌ Failed Tests

🌍 Community Worlds (42 failed)

turso (42 failed):

  • addTenWorkflow
  • addTenWorkflow
  • should work with react rendering in step
  • promiseAllWorkflow
  • promiseRaceWorkflow
  • promiseAnyWorkflow
  • hookWorkflow
  • webhookWorkflow
  • sleepingWorkflow
  • nullByteWorkflow
  • workflowAndStepMetadataWorkflow
  • fetchWorkflow
  • promiseRaceStressTestWorkflow
  • error handling error propagation workflow errors nested function calls preserve message and stack trace
  • error handling error propagation workflow errors cross-file imports preserve message and stack trace
  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack
  • error handling retry behavior regular Error retries until success
  • error handling retry behavior FatalError fails immediately without retries
  • error handling retry behavior RetryableError respects custom retryAfter delay
  • error handling retry behavior maxRetries=0 disables retries
  • error handling retry behavior workflow completes despite transient 5xx on step_completed
  • error handling catchability FatalError can be caught and detected with FatalError.is()
  • hookCleanupTestWorkflow - hook token reuse after workflow completion
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars)
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument
  • closureVariableWorkflow - nested step functions with closure variables
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly
  • Calculator.calculate - static workflow method using static step methods from another class
  • AllInOneService.processNumber - static workflow method using sibling static step methods
  • ChainableService.processWithThis - static step methods using this to reference the class
  • thisSerializationWorkflow - step function invoked with .call() and .apply()
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE
  • instanceMethodStepWorkflow - instance methods with "use step" directive
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument
  • pages router addTenWorkflow via pages router
  • pages router promiseAllWorkflow via pages router
  • pages router sleepingWorkflow via pages router

Details by Category

✅ ▲ Vercel Production
App Passed Failed Skipped
✅ astro 45 0 4
✅ example 45 0 4
✅ express 45 0 4
✅ fastify 45 0 4
✅ hono 45 0 4
✅ nextjs-turbopack 48 0 1
✅ nextjs-webpack 48 0 1
✅ nitro 45 0 4
✅ nuxt 45 0 4
✅ sveltekit 45 0 4
✅ vite 45 0 4
✅ 💻 Local Development
App Passed Failed Skipped
✅ astro-stable 42 0 7
✅ express-stable 42 0 7
✅ fastify-stable 42 0 7
✅ hono-stable 42 0 7
✅ nextjs-turbopack-canary 46 0 3
✅ nextjs-turbopack-stable 46 0 3
✅ nextjs-webpack-canary 46 0 3
✅ nextjs-webpack-stable 46 0 3
✅ nitro-stable 42 0 7
✅ nuxt-stable 42 0 7
✅ sveltekit-stable 42 0 7
✅ vite-stable 42 0 7
✅ 📦 Local Production
App Passed Failed Skipped
✅ astro-stable 42 0 7
✅ express-stable 42 0 7
✅ fastify-stable 42 0 7
✅ hono-stable 42 0 7
✅ nextjs-turbopack-canary 46 0 3
✅ nextjs-turbopack-stable 46 0 3
✅ nextjs-webpack-canary 46 0 3
✅ nextjs-webpack-stable 46 0 3
✅ nitro-stable 42 0 7
✅ nuxt-stable 42 0 7
✅ sveltekit-stable 42 0 7
✅ vite-stable 42 0 7
✅ 🐘 Local Postgres
App Passed Failed Skipped
✅ astro-stable 42 0 7
✅ express-stable 42 0 7
✅ fastify-stable 42 0 7
✅ hono-stable 42 0 7
✅ nextjs-turbopack-canary 46 0 3
✅ nextjs-turbopack-stable 46 0 3
✅ nextjs-webpack-canary 46 0 3
✅ nextjs-webpack-stable 46 0 3
✅ nitro-stable 42 0 7
✅ nuxt-stable 42 0 7
✅ sveltekit-stable 42 0 7
✅ vite-stable 42 0 7
✅ 🪟 Windows
App Passed Failed Skipped
✅ nextjs-turbopack 46 0 3
❌ 🌍 Community Worlds
App Passed Failed Skipped
✅ mongodb-dev 3 0 0
✅ mongodb 46 0 3
✅ redis-dev 3 0 0
✅ redis 46 0 3
✅ turso-dev 3 0 0
❌ turso 4 42 3
✅ 📋 Other
App Passed Failed Skipped
✅ e2e-local-dev-nest-stable 42 0 7
✅ e2e-local-postgres-nest-stable 42 0 7
✅ e2e-local-prod-nest-stable 42 0 7

📋 View full workflow run

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 13, 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.025s (-25.7% 🟢) 1.005s (~) 0.980s 10 1.00x
💻 Local Nitro 0.032s (~) 1.004s (~) 0.972s 10 1.28x
💻 Local Next.js (Turbopack) 0.044s 1.005s 0.961s 10 1.74x
🌐 Redis Next.js (Turbopack) 0.047s 1.005s 0.958s 10 1.86x
🌐 MongoDB Next.js (Turbopack) 0.092s 1.007s 0.915s 10 3.66x
🐘 Postgres Nitro 0.102s (-18.1% 🟢) 1.010s (~) 0.908s 10 4.04x
🐘 Postgres Express 0.127s (+11.0% 🔺) 1.009s (~) 0.883s 10 5.03x
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 0.574s (-34.9% 🟢) 1.801s (-21.3% 🟢) 1.227s 10 1.00x
▲ Vercel Nitro 0.621s (+16.4% 🔺) 2.020s (+5.7% 🔺) 1.400s 10 1.08x
▲ Vercel Next.js (Turbopack) 0.655s (-9.5% 🟢) 2.053s (-0.7%) 1.398s 10 1.14x

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

workflow with 1 step

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Express 1.073s (-3.7%) 2.006s (~) 0.932s 10 1.00x
💻 Local Next.js (Turbopack) 1.102s 2.006s 0.904s 10 1.03x
💻 Local Nitro 1.103s (~) 2.005s (~) 0.902s 10 1.03x
🌐 Redis Next.js (Turbopack) 1.110s 2.007s 0.897s 10 1.03x
🌐 MongoDB Next.js (Turbopack) 1.312s 2.008s 0.696s 10 1.22x
🐘 Postgres Express 1.910s (-22.9% 🟢) 2.312s (-23.3% 🟢) 0.402s 10 1.78x
🐘 Postgres Nitro 2.475s (+33.1% 🔺) 3.013s (+36.3% 🔺) 0.538s 10 2.31x
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.264s (-3.8%) 3.475s (+10.1% 🔺) 1.210s 10 1.00x
▲ Vercel Next.js (Turbopack) 2.319s (-5.1% 🟢) 3.221s (-3.1%) 0.902s 10 1.02x
▲ Vercel Nitro 2.370s (~) 3.616s (+21.7% 🔺) 1.246s 10 1.05x

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

workflow with 10 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Express 10.542s (-3.1%) 11.024s (~) 0.482s 3 1.00x
💻 Local Next.js (Turbopack) 10.719s 11.023s 0.304s 3 1.02x
🌐 Redis Next.js (Turbopack) 10.734s 11.022s 0.288s 3 1.02x
💻 Local Nitro 10.820s (~) 11.022s (~) 0.202s 3 1.03x
🌐 MongoDB Next.js (Turbopack) 12.263s 13.021s 0.759s 3 1.16x
🐘 Postgres Express 15.406s (-9.9% 🟢) 16.046s (-8.5% 🟢) 0.639s 2 1.46x
🐘 Postgres Nitro 20.338s (+32.1% 🔺) 21.057s (+31.2% 🔺) 0.719s 2 1.93x
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 17.925s (-7.4% 🟢) 18.601s (-9.5% 🟢) 0.676s 2 1.00x
▲ Vercel Nitro 18.258s (-5.9% 🟢) 20.115s (-1.3%) 1.858s 2 1.02x
▲ Vercel Next.js (Turbopack) 18.538s (-7.3% 🟢) 20.611s (-4.1%) 2.074s 2 1.03x

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

workflow with 25 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Express 26.758s (-3.1%) 27.052s (-3.6%) 0.294s 3 1.00x
🌐 Redis Next.js (Turbopack) 26.899s 27.051s 0.151s 3 1.01x
💻 Local Next.js (Turbopack) 27.195s 28.051s 0.856s 3 1.02x
💻 Local Nitro 27.479s (~) 28.052s (~) 0.572s 3 1.03x
🌐 MongoDB Next.js (Turbopack) 30.436s 31.041s 0.605s 2 1.14x
🐘 Postgres Express 39.453s (+4.6%) 40.103s (+5.3% 🔺) 0.650s 2 1.47x
🐘 Postgres Nitro 48.867s (+29.6% 🔺) 49.618s (+30.2% 🔺) 0.750s 2 1.83x
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 43.903s (-10.0% 🟢) 44.574s (-10.3% 🟢) 0.671s 2 1.00x
▲ Vercel Nitro 44.279s (-10.1% 🟢) 46.225s (-7.9% 🟢) 1.945s 2 1.01x
▲ Vercel Next.js (Turbopack) 44.505s (-9.8% 🟢) 46.055s (-9.4% 🟢) 1.550s 2 1.01x

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

workflow with 50 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 54.383s 55.097s 0.714s 2 1.00x
💻 Local Express 55.641s (-3.1%) 56.106s (-3.4%) 0.466s 2 1.02x
💻 Local Next.js (Turbopack) 56.728s 57.102s 0.374s 2 1.04x
💻 Local Nitro 57.203s (~) 58.100s (~) 0.897s 2 1.05x
🌐 MongoDB Next.js (Turbopack) 60.901s 61.065s 0.163s 2 1.12x
🐘 Postgres Express 75.342s (~) 76.179s (~) 0.837s 2 1.39x
🐘 Postgres Nitro 75.483s (~) 76.170s (~) 0.687s 2 1.39x
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 89.443s (-1.6%) 90.354s (-1.2%) 0.911s 2 1.00x
▲ Vercel Express 92.340s (+2.0%) 93.007s (+2.2%) 0.667s 1 1.03x
▲ Vercel Next.js (Turbopack) 92.641s (+1.1%) 93.551s (+1.5%) 0.910s 1 1.04x

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

Promise.all with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 1.255s 2.006s 0.751s 15 1.00x
💻 Local Express 1.346s (-3.8%) 2.005s (~) 0.660s 15 1.07x
💻 Local Nitro 1.413s (~) 2.005s (~) 0.592s 15 1.13x
💻 Local Next.js (Turbopack) 1.415s 2.006s 0.590s 15 1.13x
🐘 Postgres Nitro 2.147s (+1.4%) 2.597s (-3.1%) 0.450s 12 1.71x
🌐 MongoDB Next.js (Turbopack) 2.154s 3.008s 0.854s 10 1.72x
🐘 Postgres Express 2.290s (+6.4% 🔺) 2.740s (+5.6% 🔺) 0.451s 11 1.82x
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.536s (-6.6% 🟢) 3.529s (-1.4%) 0.992s 9 1.00x
▲ Vercel Next.js (Turbopack) 3.129s (+25.4% 🔺) 4.304s (+23.2% 🔺) 1.175s 7 1.23x
▲ Vercel Nitro 3.569s (+49.6% 🔺) 4.583s (+45.4% 🔺) 1.014s 7 1.41x

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

Promise.all with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Express 2.245s (-12.2% 🟢) 3.007s (~) 0.762s 10 1.00x
🌐 Redis Next.js (Turbopack) 2.520s 3.008s 0.487s 10 1.12x
💻 Local Next.js (Turbopack) 2.578s 3.007s 0.429s 10 1.15x
💻 Local Nitro 2.599s (+1.6%) 3.007s (~) 0.408s 10 1.16x
🌐 MongoDB Next.js (Turbopack) 4.699s 5.175s 0.477s 6 2.09x
🐘 Postgres Nitro 10.757s (-12.3% 🟢) 11.037s (-13.1% 🟢) 0.280s 3 4.79x
🐘 Postgres Express 11.965s (+19.8% 🔺) 12.369s (+19.4% 🔺) 0.404s 3 5.33x
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 2.749s (-12.9% 🟢) 4.175s (+7.5% 🔺) 1.426s 8 1.00x
▲ Vercel Next.js (Turbopack) 3.264s (+9.4% 🔺) 3.969s (-10.3% 🟢) 0.705s 8 1.19x
▲ Vercel Express 3.424s (+13.5% 🔺) 4.022s (-1.8%) 0.598s 8 1.25x

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

Promise.all with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 4.078s 5.011s 0.934s 6 1.00x
💻 Local Express 6.051s (-18.9% 🟢) 6.813s (-15.0% 🟢) 0.762s 5 1.48x
💻 Local Nitro 7.292s (-0.6%) 8.019s (~) 0.727s 4 1.79x
💻 Local Next.js (Turbopack) 7.396s 8.016s 0.620s 4 1.81x
🌐 MongoDB Next.js (Turbopack) 9.725s 10.352s 0.626s 3 2.38x
🐘 Postgres Express 48.478s (~) 49.119s (~) 0.641s 1 11.89x
🐘 Postgres Nitro 52.175s (-3.2%) 53.125s (-1.9%) 0.950s 1 12.79x
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 3.544s (-47.0% 🟢) 4.497s (-41.6% 🟢) 0.953s 7 1.00x
▲ Vercel Next.js (Turbopack) 3.829s (-63.9% 🟢) 5.156s (-54.6% 🟢) 1.327s 6 1.08x
▲ Vercel Express 4.365s (-40.7% 🟢) 5.951s (-29.2% 🟢) 1.586s 6 1.23x

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

Promise.race with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 1.244s 2.006s 0.762s 15 1.00x
💻 Local Express 1.354s (-5.4% 🟢) 2.005s (~) 0.651s 15 1.09x
💻 Local Next.js (Turbopack) 1.412s 2.005s 0.593s 15 1.14x
💻 Local Nitro 1.436s (~) 2.005s (~) 0.569s 15 1.15x
🐘 Postgres Nitro 2.010s (-0.9%) 2.513s (+4.8%) 0.504s 12 1.62x
🐘 Postgres Express 2.176s (-3.5%) 2.742s (~) 0.567s 11 1.75x
🌐 MongoDB Next.js (Turbopack) 2.204s 3.008s 0.804s 10 1.77x
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 2.350s (-5.3% 🟢) 3.627s (+15.3% 🔺) 1.277s 9 1.00x
▲ Vercel Express 2.386s (-4.4%) 3.169s (-2.5%) 0.783s 10 1.02x
▲ Vercel Next.js (Turbopack) 2.394s (-16.8% 🟢) 3.213s (-15.5% 🟢) 0.820s 10 1.02x

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

Promise.race with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Express 2.353s (-11.3% 🟢) 3.007s (~) 0.654s 10 1.00x
🌐 Redis Next.js (Turbopack) 2.533s 3.008s 0.475s 10 1.08x
💻 Local Next.js (Turbopack) 2.602s 3.008s 0.407s 10 1.11x
💻 Local Nitro 2.699s (-1.8%) 3.007s (~) 0.308s 10 1.15x
🌐 MongoDB Next.js (Turbopack) 4.717s 5.175s 0.458s 6 2.00x
🐘 Postgres Express 12.131s (+10.6% 🔺) 12.707s (+8.6% 🔺) 0.576s 3 5.16x
🐘 Postgres Nitro 13.261s (+13.2% 🔺) 13.705s (+10.8% 🔺) 0.444s 3 5.64x
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.441s (-2.5%) 3.435s (+1.8%) 0.994s 9 1.00x
▲ Vercel Nitro 2.558s (-14.1% 🟢) 3.676s (-2.8%) 1.119s 9 1.05x
▲ Vercel Next.js (Turbopack) 3.409s (+1.9%) 4.212s (-2.0%) 0.803s 8 1.40x

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

Promise.race with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 4.078s 4.725s 0.647s 7 1.00x
💻 Local Express 6.799s (-11.0% 🟢) 7.215s (-10.0% 🟢) 0.417s 5 1.67x
💻 Local Next.js (Turbopack) 7.597s 8.015s 0.419s 4 1.86x
💻 Local Nitro 7.746s (~) 8.021s (~) 0.275s 4 1.90x
🌐 MongoDB Next.js (Turbopack) 10.143s 10.348s 0.205s 3 2.49x
🐘 Postgres Express 51.471s (+4.3%) 52.113s (+4.0%) 0.642s 1 12.62x
🐘 Postgres Nitro 51.722s (+9.0% 🔺) 52.116s (+8.3% 🔺) 0.394s 1 12.68x
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 2.990s (-29.2% 🟢) 4.200s (-25.1% 🟢) 1.210s 8 1.00x
▲ Vercel Express 3.386s (-7.4% 🟢) 4.633s (-3.6%) 1.247s 7 1.13x
▲ Vercel Nitro 4.279s (+16.3% 🔺) 5.262s (+7.8% 🔺) 0.984s 6 1.43x

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

Stream Benchmarks (includes TTFB metrics)
workflow with stream

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Express 0.111s (-38.2% 🟢) 1.002s (~) 0.010s (-12.7% 🟢) 1.014s (~) 0.903s 10 1.00x
💻 Local Next.js (Turbopack) 0.144s 1.001s 0.011s 1.017s 0.872s 10 1.30x
🌐 Redis Next.js (Turbopack) 0.151s 0.999s 0.002s 1.007s 0.856s 10 1.35x
💻 Local Nitro 0.173s (+2.1%) 1.002s (~) 0.011s (-2.7%) 1.016s (~) 0.842s 10 1.56x
🌐 MongoDB Next.js (Turbopack) 0.507s 0.939s 0.001s 1.008s 0.501s 10 4.56x
🐘 Postgres Nitro 1.291s (-9.5% 🟢) 1.747s (+8.4% 🔺) 0.001s (-7.1% 🟢) 2.013s (~) 0.722s 10 11.60x
🐘 Postgres Express 1.404s (+33.8% 🔺) 1.637s (-16.8% 🟢) 0.001s (+18.2% 🔺) 2.013s (~) 0.609s 10 12.61x
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - - -

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 1.930s (-7.6% 🟢) 2.800s (+5.9% 🔺) 0.230s (+45.8% 🔺) 3.516s (+5.9% 🔺) 1.587s 10 1.00x
▲ Vercel Next.js (Turbopack) 2.140s (-2.6%) 2.936s (+5.2% 🔺) 0.400s (+36.1% 🔺) 3.926s (+2.8%) 1.786s 10 1.11x
▲ Vercel Nitro 2.186s (+13.1% 🔺) 2.830s (+16.2% 🔺) 0.246s (-28.4% 🟢) 3.680s (+11.5% 🔺) 1.494s 10 1.13x

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

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World 🥇 Fastest Framework Wins
💻 Local Express 12/12
🐘 Postgres Express 7/12
▲ Vercel Express 7/12
Fastest World by Framework

Winner determined by most benchmark wins

Framework 🥇 Fastest World Wins
Express 💻 Local 10/12
Next.js (Turbopack) 🌐 Redis 6/12
Nitro 💻 Local 9/12
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run

Comment thread packages/core/src/runtime.ts
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.

This PR has the right intent but the fix has two structural bugs — the 429 path is still unreachable, and non-5xx errors are now silently swallowed. See inline comments.

Comment thread packages/core/src/runtime.ts
Comment thread packages/core/src/runtime.ts Outdated
WorkflowAPIError.is(err) &&
err.status !== undefined &&
err.status >= 500
) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Bug: Non-5xx errors are now silently swallowed. The old code used a generic else block, so all non-suspension errors (user code errors, 4xx, network errors, etc.) would fall through to the run_failed handling below. By changing this to else if (status >= 500), the run_failed code (lines 321-372) is now inside this block and only executes for 5xx errors. Any other error type silently falls through the catch without recording run_failed.

Suggested structure:

} else if (WorkflowAPIError.is(err) && err.status === 429) {
  // Re-throw to let withThrottleRetry handle it
  throw err;
} else if (
  WorkflowAPIError.is(err) &&
  err.status !== undefined &&
  err.status >= 500
) {
  const retryCount = serverErrorRetryCount ?? 0;
  const delaySecondSteps = [5, 30, 120];
  if (retryCount < delaySecondSteps.length) {
    // re-enqueue with backoff
    ...
    return;
  }
  // Fall through to run_failed after exhausting retries
} else {
  // Intentional fall-through for all other errors
}
// run_failed handling here (outside all branches)

This way:

  1. 429 is handled first and re-thrown to withThrottleRetry
  2. 5xx gets exponential backoff retry, falling through to run_failed when exhausted
  3. All other errors (user code, network, etc.) still reach run_failed

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.

One more note on testing:

Comment thread packages/core/src/runtime.ts
Signed-off-by: Peter Wielander <mittgfu@gmail.com>
Signed-off-by: Peter Wielander <mittgfu@gmail.com>
Signed-off-by: Peter Wielander <mittgfu@gmail.com>
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.

The latest revision (f8fc681) looks correct. The 429 else if is now a proper sibling to the 5xx check inside the generic else block, so:

  1. 429 errors correctly re-throw to withThrottleRetry
  2. 5xx retry + fallthrough to run_failed is preserved ✓
  3. All other errors (user code, network, etc.) still reach run_failed

The structural bugs from the first commit (dead 429 branch, swallowed non-5xx errors) are resolved.

Suggestion: Consider adding a 429 fault injection test (similar to the existing 5xx installServerErrorFaultInjection pattern) to cover this integration path. That would prevent regressions like the original dead-code bug from shipping undetected.

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.

The latest revision correctly fixes the 429 retry path. LGTM.

One suggestion for follow-up: consider adding a 429 fault injection e2e test (similar to the existing 5xx pattern) to prevent regressions.

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