Skip to content

Add cookbook with 50 workflow pattern recipes#1564

Open
johnlindquist wants to merge 50 commits intomainfrom
cookbook
Open

Add cookbook with 50 workflow pattern recipes#1564
johnlindquist wants to merge 50 commits intomainfrom
cookbook

Conversation

@johnlindquist
Copy link
Copy Markdown
Contributor

Summary

  • Adds a Cookbook section to useworkflow.dev docs with an interactive decision tree explorer ("I want to...") that guides users to the right workflow pattern
  • Migrates all 50 workflow patterns from the campaign demos project as MDX recipe pages, each with simplified + full implementation code snippets
  • 8 categories: Payments & Orders, Approvals, Resilience, Notifications, Webhooks & Callbacks, Data Processing, Routing, Observability

Test plan

  • Visit /docs/cookbook and verify the decision tree renders with all 7 top-level branches
  • Click through each branch to confirm sub-questions and results link to correct recipe pages
  • Verify breadcrumb navigation works (click back to previous steps, "Start over")
  • Open a recipe page (e.g. /docs/cookbook/payments/saga) and confirm both simplified and full code blocks render with syntax highlighting
  • Check sidebar nav shows Cookbook section with all 8 category subfolders
  • Verify no build errors with pnpm build in docs/

Migrate the "Workflow API Explorer" decision tree concept from
workflow-campaign-demos into useworkflow.dev docs as a Cookbook.

Infrastructure:
- docs/lib/cookbook-tree.ts: decision tree data, 50 recipe metadata entries, slug-to-category mapping
- docs/components/geistdocs/cookbook-explorer.tsx: interactive "I want to..." decision tree UI with breadcrumb navigation
- docs/content/docs/cookbook/index.mdx: landing page rendering CookbookExplorer component
- docs/content/docs/cookbook/meta.json + 8 category meta.json files for sidebar nav
- docs/content/docs/meta.json: added cookbook to docs nav between foundations and how-it-works
- docs/app/[lang]/docs/[[...slug]]/page.tsx: registered CookbookExplorer component

50 recipe MDX files across 8 categories (payments, approvals, resilience,
notifications, webhooks, data-processing, routing, observability), each with:
- Frontmatter (title, description, type: guide, summary with use-case scenario)
- Simplified code snippet (core pattern only, stripped of demo UI concerns)
- Full implementation code snippet (exact source from campaign demos)
- Key APIs section with links to API reference docs
@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Mar 30, 2026

@johnlindquist johnlindquist requested a review from a team as a code owner March 30, 2026 23:03
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 30, 2026

⚠️ No Changeset found

Latest commit: bf10a7f

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 30, 2026

🧪 E2E Test Results

Some tests failed

Summary

Passed Failed Skipped Total
❌ ▲ Vercel Production 845 1 67 913
✅ 💻 Local Development 760 0 153 913
✅ 📦 Local Production 818 0 178 996
✅ 🐘 Local Postgres 818 0 178 996
✅ 🪟 Windows 75 0 8 83
❌ 🌍 Community Worlds 132 60 24 216
✅ 📋 Other 207 0 42 249
Total 3655 61 650 4366

❌ Failed Tests

▲ Vercel Production (1 failed)

astro (1 failed):

  • error handling retry behavior FatalError fails immediately without retries
🌍 Community Worlds (60 failed)

mongodb (3 failed):

  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KN50B85RFV0XQS3CTGYZ847B
  • webhookWorkflow | wrun_01KN50BH27254XW05YR2B5Q77X
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KN50K21059C2946RRQS4RSGJ

redis (2 failed):

  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KN50B85RFV0XQS3CTGYZ847B
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KN50K21059C2946RRQS4RSGJ

turso (55 failed):

  • addTenWorkflow | wrun_01KN50A3J33XBV841MK7S0BDGG
  • addTenWorkflow | wrun_01KN50A3J33XBV841MK7S0BDGG
  • wellKnownAgentWorkflow (.well-known/agent) | wrun_01KN50BK1KWV1Q7QSGDWPTRC0C
  • should work with react rendering in step
  • promiseAllWorkflow | wrun_01KN50A9TBWMVQY1NSXTAX064Z
  • promiseRaceWorkflow | wrun_01KN50AF7EG9TMM4TMYZ8CHB02
  • promiseAnyWorkflow | wrun_01KN50AHFGV4WWK9Q4P06DJGRA
  • importedStepOnlyWorkflow | wrun_01KN50BYXPD7JG635NDT3EQCY1
  • hookWorkflow | wrun_01KN50AXQ7M19GQHM4XT6NNESE
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KN50B85RFV0XQS3CTGYZ847B
  • webhookWorkflow | wrun_01KN50BH27254XW05YR2B5Q77X
  • sleepingWorkflow | wrun_01KN50BPHP0QWXPZPCB89V9ZPN
  • parallelSleepWorkflow | wrun_01KN50C40YGS0SRRDCS92XYDHC
  • nullByteWorkflow | wrun_01KN50C7GR1CPXS24JQZDJZ4VQ
  • workflowAndStepMetadataWorkflow | wrun_01KN50C9KD642GEW76WFXVAAB4
  • fetchWorkflow | wrun_01KN50F203ZEM3Z2W59F9JH025
  • promiseRaceStressTestWorkflow | wrun_01KN50F6WBZ2KD5VEDX0V1RFTD
  • 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 catchability FatalError can be caught and detected with FatalError.is()
  • error handling not registered WorkflowNotRegisteredError fails the run when workflow does not exist
  • error handling not registered StepNotRegisteredError fails the step but workflow can catch it
  • error handling not registered StepNotRegisteredError fails the run when not caught in workflow
  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_01KN50JF484G2N225JG0W28KN4
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KN50K21059C2946RRQS4RSGJ
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KN50KQ8NZGJWP5ABTW6PY7MM
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KN50M9RG80BSHW6EM83AN3B7
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_01KN50MH8VRY4T8N97ZQ8AX6NE
  • closureVariableWorkflow - nested step functions with closure variables | wrun_01KN50MP1CRPBJYJ1TE5JREJ55
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_01KN50MR2SDAEBD07RMZSY5GQK
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_01KN50N5DRD99V1N7QVG9Q2RTZ
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_01KN50NBB6R65NC3EKBB1YC2JR
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_01KN50NH9KFMYTF4A9KWB1CGWG
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_01KN50NQDPCDJ4M1M11JYJ8AVB
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_01KN50NXVPPG8C87H78CEHB2WM
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_01KN50P4AJ6VGXBFYC1MZ6RAFD
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_01KN50PAPTR4RQ9C1RWG7QBV1T
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_01KN50PMKNCCV84Y5NYCTJ7080
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_01KN50PWQCZSD79DJPGH1YV49S
  • cancelRun - cancelling a running workflow | wrun_01KN50Q329STVTB3M67JT8WTPK
  • cancelRun via CLI - cancelling a running workflow | wrun_01KN50QBPA07AQC1PKQA9E1ZP8
  • pages router addTenWorkflow via pages router
  • pages router promiseAllWorkflow via pages router
  • pages router sleepingWorkflow via pages router
  • hookWithSleepWorkflow - hook payloads delivered correctly with concurrent sleep | wrun_01KN50QPTHNW9W7EQKJX3D70AM
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KN50RANTWR1E437F0T4W80T4
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KN50RMRP52CZNMY4XCV42SHY
  • importMetaUrlWorkflow - import.meta.url is available in step bundles

Details by Category

❌ ▲ Vercel Production
App Passed Failed Skipped
❌ astro 75 1 7
✅ example 76 0 7
✅ express 76 0 7
✅ fastify 76 0 7
✅ hono 76 0 7
✅ nextjs-turbopack 81 0 2
✅ nextjs-webpack 81 0 2
✅ nitro 76 0 7
✅ nuxt 76 0 7
✅ sveltekit 76 0 7
✅ vite 76 0 7
✅ 💻 Local Development
App Passed Failed Skipped
✅ astro-stable 69 0 14
✅ express-stable 69 0 14
✅ fastify-stable 69 0 14
✅ hono-stable 69 0 14
✅ nextjs-turbopack-stable 75 0 8
✅ nextjs-webpack-canary 58 0 25
✅ nextjs-webpack-stable 75 0 8
✅ nitro-stable 69 0 14
✅ nuxt-stable 69 0 14
✅ sveltekit-stable 69 0 14
✅ vite-stable 69 0 14
✅ 📦 Local Production
App Passed Failed Skipped
✅ astro-stable 69 0 14
✅ express-stable 69 0 14
✅ fastify-stable 69 0 14
✅ hono-stable 69 0 14
✅ nextjs-turbopack-canary 58 0 25
✅ nextjs-turbopack-stable 75 0 8
✅ nextjs-webpack-canary 58 0 25
✅ nextjs-webpack-stable 75 0 8
✅ nitro-stable 69 0 14
✅ nuxt-stable 69 0 14
✅ sveltekit-stable 69 0 14
✅ vite-stable 69 0 14
✅ 🐘 Local Postgres
App Passed Failed Skipped
✅ astro-stable 69 0 14
✅ express-stable 69 0 14
✅ fastify-stable 69 0 14
✅ hono-stable 69 0 14
✅ nextjs-turbopack-canary 58 0 25
✅ nextjs-turbopack-stable 75 0 8
✅ nextjs-webpack-canary 58 0 25
✅ nextjs-webpack-stable 75 0 8
✅ nitro-stable 69 0 14
✅ nuxt-stable 69 0 14
✅ sveltekit-stable 69 0 14
✅ vite-stable 69 0 14
✅ 🪟 Windows
App Passed Failed Skipped
✅ nextjs-turbopack 75 0 8
❌ 🌍 Community Worlds
App Passed Failed Skipped
✅ mongodb-dev 5 0 0
❌ mongodb 56 3 8
✅ redis-dev 5 0 0
❌ redis 57 2 8
✅ turso-dev 5 0 0
❌ turso 4 55 8
✅ 📋 Other
App Passed Failed Skipped
✅ e2e-local-dev-nest-stable 69 0 14
✅ e2e-local-postgres-nest-stable 69 0 14
✅ e2e-local-prod-nest-stable 69 0 14

📋 View full workflow run


Some E2E test jobs failed:

  • Vercel Prod: failure
  • Local Dev: cancelled
  • Local Prod: success
  • Local Postgres: success
  • Windows: success

Check the workflow run for details.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 30, 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 🥇 Nitro 0.043s (-3.4%) 1.005s (~) 0.962s 10 1.00x
💻 Local Express 0.046s (+1.1%) 1.005s (~) 0.960s 10 1.06x
🐘 Postgres Nitro 0.049s (-29.7% 🟢) 1.011s (~) 0.962s 10 1.14x
🐘 Postgres Express 0.051s (-25.9% 🟢) 1.010s (~) 0.959s 10 1.19x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 0.544s (+8.0% 🔺) 2.804s (+4.1%) 2.259s 10 1.00x
▲ Vercel Nitro 0.593s (+13.0% 🔺) 2.433s (-11.5% 🟢) 1.840s 10 1.09x

🔍 Observability: Express | Nitro

workflow with 1 step

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.111s (-3.5%) 2.010s (~) 0.899s 10 1.00x
💻 Local Express 1.125s (~) 2.007s (~) 0.882s 10 1.01x
🐘 Postgres Express 1.131s (-1.7%) 2.010s (~) 0.878s 10 1.02x
💻 Local Nitro 1.138s (~) 2.006s (~) 0.868s 10 1.02x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 2.118s (+1.7%) 3.979s (+2.1%) 1.861s 10 1.00x
▲ Vercel Express 2.430s (+7.3% 🔺) 4.295s (+8.6% 🔺) 1.864s 10 1.15x

🔍 Observability: Nitro | Express

workflow with 10 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 10.686s (-2.4%) 11.024s (~) 0.338s 3 1.00x
🐘 Postgres Nitro 10.688s (-2.2%) 11.021s (~) 0.333s 3 1.00x
💻 Local Express 10.921s (~) 11.023s (~) 0.102s 3 1.02x
💻 Local Nitro 10.946s (+0.5%) 11.023s (~) 0.077s 3 1.02x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 16.841s (-26.9% 🟢) 18.353s (-27.8% 🟢) 1.512s 2 1.00x
▲ Vercel Express 16.891s (-3.7%) 18.916s (-3.7%) 2.025s 2 1.00x

🔍 Observability: Nitro | Express

workflow with 25 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 14.003s (-4.1%) 14.622s (-2.7%) 0.619s 5 1.00x
🐘 Postgres Express 14.081s (-3.6%) 15.022s (~) 0.941s 4 1.01x
💻 Local Express 14.960s (~) 15.030s (~) 0.070s 4 1.07x
💻 Local Nitro 14.982s (~) 15.030s (~) 0.048s 4 1.07x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 31.162s (-3.1%) 32.991s (-3.4%) 1.829s 2 1.00x
▲ Vercel Express 32.248s (-7.8% 🟢) 34.259s (-7.0% 🟢) 2.011s 2 1.03x

🔍 Observability: Nitro | Express

workflow with 50 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 12.906s (-8.5% 🟢) 13.020s (-11.7% 🟢) 0.115s 7 1.00x
🐘 Postgres Express 13.144s (-8.7% 🟢) 14.022s (-6.7% 🟢) 0.878s 7 1.02x
💻 Local Nitro 16.520s (~) 17.031s (~) 0.510s 6 1.28x
💻 Local Express 16.673s (~) 17.032s (~) 0.359s 6 1.29x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 51.285s (-10.9% 🟢) 53.174s (-11.3% 🟢) 1.889s 2 1.00x
▲ Vercel Express 54.106s (-3.7%) 57.174s (-1.7%) 3.068s 2 1.06x

🔍 Observability: Nitro | Express

Promise.all with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.198s (-5.1% 🟢) 2.009s (~) 0.811s 15 1.00x
🐘 Postgres Express 1.207s (-5.2% 🟢) 2.011s (~) 0.804s 15 1.01x
💻 Local Express 1.492s (-3.1%) 2.006s (~) 0.515s 15 1.25x
💻 Local Nitro 1.545s (+0.8%) 2.073s (+3.3%) 0.528s 15 1.29x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 2.491s (+2.2%) 3.871s (-4.1%) 1.380s 8 1.00x
▲ Vercel Express 2.903s (+12.1% 🔺) 4.675s (+4.3%) 1.772s 7 1.17x

🔍 Observability: Nitro | Express

Promise.all with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 2.293s (-2.4%) 3.009s (~) 0.716s 10 1.00x
🐘 Postgres Express 2.314s (-2.2%) 3.011s (~) 0.697s 10 1.01x
💻 Local Express 2.894s (-1.1%) 3.207s (+6.6% 🔺) 0.313s 10 1.26x
💻 Local Nitro 2.914s (-1.7%) 3.341s (-3.3%) 0.426s 9 1.27x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 3.264s (+24.2% 🔺) 5.105s (+17.0% 🔺) 1.841s 6 1.00x
▲ Vercel Nitro 3.766s (+32.3% 🔺) 5.380s (+26.1% 🔺) 1.614s 6 1.15x

🔍 Observability: Express | Nitro

Promise.all with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 3.369s (-3.1%) 4.010s (~) 0.641s 8 1.00x
🐘 Postgres Express 3.409s (-2.3%) 4.014s (~) 0.605s 8 1.01x
💻 Local Nitro 7.498s (-6.7% 🟢) 8.018s (-5.9% 🟢) 0.520s 4 2.23x
💻 Local Express 8.687s (+6.5% 🔺) 9.273s (+2.8%) 0.586s 4 2.58x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 3.090s (+1.7%) 5.207s (+3.0%) 2.117s 6 1.00x
▲ Vercel Express 3.226s (-11.8% 🟢) 4.972s (-12.5% 🟢) 1.746s 7 1.04x

🔍 Observability: Nitro | Express

Promise.race with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.189s (-6.3% 🟢) 2.009s (~) 0.821s 15 1.00x
🐘 Postgres Express 1.204s (-4.1%) 2.010s (~) 0.805s 15 1.01x
💻 Local Nitro 1.499s (-4.9%) 2.006s (~) 0.507s 15 1.26x
💻 Local Express 1.554s (~) 2.007s (~) 0.453s 15 1.31x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 2.243s (-8.4% 🟢) 3.770s (-5.6% 🟢) 1.527s 8 1.00x
▲ Vercel Express 2.323s (~) 4.181s (+4.3%) 1.858s 8 1.04x

🔍 Observability: Nitro | Express

Promise.race with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 2.281s (-3.2%) 3.009s (~) 0.728s 10 1.00x
🐘 Postgres Express 2.294s (-1.1%) 3.011s (~) 0.717s 10 1.01x
💻 Local Nitro 2.881s (-5.5% 🟢) 3.107s (-20.0% 🟢) 0.227s 10 1.26x
💻 Local Express 2.922s (-6.4% 🟢) 3.760s (-3.3%) 0.839s 8 1.28x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 2.972s (+2.6%) 4.384s (+1.6%) 1.412s 7 1.00x
▲ Vercel Express 3.251s (+11.2% 🔺) 4.925s (+8.4% 🔺) 1.674s 7 1.09x

🔍 Observability: Nitro | Express

Promise.race with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 3.388s (-3.1%) 4.011s (~) 0.623s 8 1.00x
🐘 Postgres Express 3.409s (-2.1%) 4.013s (~) 0.604s 8 1.01x
💻 Local Nitro 8.382s (-2.7%) 9.024s (~) 0.642s 4 2.47x
💻 Local Express 8.826s (~) 9.028s (-2.6%) 0.202s 4 2.61x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.947s (~) 4.361s (-2.2%) 1.414s 7 1.00x
▲ Vercel Nitro 3.236s (-2.9%) 5.126s (+6.8% 🔺) 1.890s 6 1.10x

🔍 Observability: Express | Nitro

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 0.586s (-30.7% 🟢) 1.007s (~) 0.421s 60 1.00x
🐘 Postgres Express 0.620s (-26.3% 🟢) 1.007s (~) 0.388s 60 1.06x
💻 Local Express 0.973s (-1.0%) 1.057s (-10.5% 🟢) 0.084s 57 1.66x
💻 Local Nitro 1.011s (+2.3%) 1.748s (+48.1% 🔺) 0.738s 35 1.73x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 9.732s (-3.1%) 12.041s (-0.8%) 2.308s 6 1.00x
▲ Vercel Nitro 9.844s (-4.1%) 11.774s (-3.8%) 1.930s 6 1.01x

🔍 Observability: Express | Nitro

workflow with 25 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.425s (-29.8% 🟢) 2.008s (-26.0% 🟢) 0.583s 45 1.00x
🐘 Postgres Express 1.507s (-25.4% 🟢) 2.009s (-23.9% 🟢) 0.502s 45 1.06x
💻 Local Nitro 3.012s (~) 3.453s (-4.3%) 0.441s 27 2.11x
💻 Local Express 3.025s (~) 3.729s (+4.0%) 0.704s 25 2.12x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 28.406s (-17.2% 🟢) 30.924s (-14.8% 🟢) 2.518s 3 1.00x
▲ Vercel Express 30.420s (-10.4% 🟢) 32.609s (-8.4% 🟢) 2.189s 3 1.07x

🔍 Observability: Nitro | Express

workflow with 50 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 2.895s (-29.4% 🟢) 3.086s (-35.9% 🟢) 0.191s 39 1.00x
🐘 Postgres Express 3.056s (-25.9% 🟢) 3.707s (-23.6% 🟢) 0.652s 33 1.06x
💻 Local Nitro 8.957s (-2.2%) 9.402s (-3.9%) 0.445s 13 3.09x
💻 Local Express 9.236s (~) 9.941s (-0.8%) 0.705s 13 3.19x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 73.524s (-16.2% 🟢) 75.364s (-16.0% 🟢) 1.840s 2 1.00x
▲ Vercel Express 73.616s (-14.9% 🟢) 76.244s (-13.9% 🟢) 2.628s 2 1.00x

🔍 Observability: Nitro | Express

workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 0.219s (-25.7% 🟢) 1.008s (~) 0.788s 60 1.00x
🐘 Postgres Express 0.238s (-19.6% 🟢) 1.008s (~) 0.770s 60 1.08x
💻 Local Nitro 0.567s (-2.1%) 1.004s (~) 0.437s 60 2.58x
💻 Local Express 0.600s (-1.6%) 1.021s (~) 0.421s 59 2.73x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 1.610s (-4.6%) 3.052s (-10.2% 🟢) 1.441s 20 1.00x
▲ Vercel Express 1.661s (-4.7%) 3.392s (+2.3%) 1.731s 18 1.03x

🔍 Observability: Nitro | Express

workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 0.359s (-30.5% 🟢) 1.006s (~) 0.648s 90 1.00x
🐘 Postgres Express 0.395s (-24.7% 🟢) 1.007s (~) 0.613s 90 1.10x
💻 Local Nitro 2.374s (-7.0% 🟢) 3.008s (~) 0.634s 30 6.62x
💻 Local Express 2.540s (~) 3.009s (~) 0.469s 30 7.08x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 3.327s (+6.0% 🔺) 4.961s (+1.7%) 1.634s 19 1.00x
▲ Vercel Nitro 3.663s (-9.8% 🟢) 5.436s (-3.8%) 1.773s 17 1.10x

🔍 Observability: Express | Nitro

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 0.564s (-29.7% 🟢) 1.007s (~) 0.444s 120 1.00x
🐘 Postgres Express 0.597s (-27.4% 🟢) 1.007s (~) 0.411s 120 1.06x
💻 Local Nitro 10.434s (-6.6% 🟢) 11.027s (-6.2% 🟢) 0.592s 11 18.51x
💻 Local Express 11.220s (~) 12.028s (+1.5%) 0.808s 10 19.91x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 8.219s (+5.6% 🔺) 10.129s (+8.6% 🔺) 1.911s 12 1.00x
▲ Vercel Nitro 9.545s (+15.4% 🔺) 11.503s (+13.8% 🔺) 1.958s 11 1.16x

🔍 Observability: Express | Nitro

Stream Benchmarks (includes TTFB metrics)
workflow with stream

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 0.146s (-31.0% 🟢) 0.998s (~) 0.001s (-8.3% 🟢) 1.009s (~) 0.862s 10 1.00x
🐘 Postgres Express 0.159s (-27.9% 🟢) 0.998s (+0.7%) 0.001s (-14.3% 🟢) 1.011s (~) 0.852s 10 1.09x
💻 Local Express 0.202s (-2.8%) 1.003s (~) 0.012s (~) 1.018s (~) 0.816s 10 1.38x
💻 Local Nitro 0.225s (+10.9% 🔺) 1.003s (~) 0.010s (-11.0% 🟢) 1.015s (~) 0.790s 10 1.54x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 1.875s (+8.0% 🔺) 3.238s (+4.0%) 1.115s (+74.6% 🔺) 5.053s (+10.6% 🔺) 3.179s 10 1.00x
▲ Vercel Nitro 2.032s (+22.5% 🔺) 3.240s (+12.9% 🔺) 2.065s (+268.5% 🔺) 5.922s (+44.2% 🔺) 3.890s 10 1.08x

🔍 Observability: Express | Nitro

stream pipeline with 5 transform steps (1MB)

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 0.487s (-21.9% 🟢) 1.005s (~) 0.003s (-17.2% 🟢) 1.020s (~) 0.533s 59 1.00x
🐘 Postgres Express 0.513s (-17.5% 🟢) 1.005s (~) 0.004s (-4.7%) 1.025s (~) 0.511s 59 1.05x
💻 Local Express 0.735s (+1.0%) 1.009s (~) 0.009s (+10.0% 🔺) 1.023s (~) 0.288s 59 1.51x
💻 Local Nitro 0.747s (+2.7%) 1.010s (~) 0.009s (+7.4% 🔺) 1.023s (~) 0.276s 59 1.53x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 4.285s (+1.7%) 5.816s (+5.9% 🔺) 0.259s (-47.6% 🟢) 6.768s (+2.1%) 2.483s 9 1.00x
▲ Vercel Nitro 4.525s (+9.5% 🔺) 5.594s (+4.9%) 0.246s (+4.0%) 6.484s (+3.3%) 1.959s 10 1.06x

🔍 Observability: Express | Nitro

10 parallel streams (1MB each)

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 0.908s (-6.1% 🟢) 1.109s (-9.4% 🟢) 0.000s (-11.1% 🟢) 1.119s (-10.6% 🟢) 0.211s 54 1.00x
🐘 Postgres Nitro 0.917s (-8.4% 🟢) 1.068s (-21.2% 🟢) 0.000s (-61.4% 🟢) 1.078s (-21.8% 🟢) 0.161s 57 1.01x
💻 Local Nitro 1.222s (-2.0%) 2.020s (~) 0.000s (~) 2.023s (~) 0.800s 30 1.35x
💻 Local Express 1.248s (~) 2.021s (~) 0.000s (+57.1% 🔺) 2.024s (~) 0.776s 30 1.37x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 2.790s (-16.9% 🟢) 3.720s (-13.4% 🟢) 0.000s (NaN%) 4.363s (-12.8% 🟢) 1.573s 14 1.00x
▲ Vercel Express 3.115s (-12.0% 🟢) 4.091s (-9.2% 🟢) 0.001s (-26.2% 🟢) 4.845s (-6.9% 🟢) 1.729s 13 1.12x

🔍 Observability: Nitro | 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.685s (-6.1% 🟢) 2.142s (~) 0.000s (+250.0% 🔺) 2.162s (~) 0.477s 28 1.00x
🐘 Postgres Express 1.714s (-3.6%) 2.104s (-0.8%) 0.000s (+Infinity% 🔺) 2.113s (-2.4%) 0.399s 29 1.02x
💻 Local Nitro 3.355s (-7.1% 🟢) 4.033s (-1.6%) 0.001s (~) 4.036s (-1.6%) 0.682s 15 1.99x
💻 Local Express 3.435s (-0.8%) 4.032s (~) 0.000s (-40.0% 🟢) 4.036s (~) 0.600s 15 2.04x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 3.986s (-9.5% 🟢) 4.778s (-13.1% 🟢) 0.000s (+Infinity% 🔺) 5.687s (-7.8% 🟢) 1.701s 11 1.00x
▲ Vercel Nitro 4.048s (-11.9% 🟢) 4.814s (-14.4% 🟢) 0.000s (-100.0% 🟢) 5.692s (-9.7% 🟢) 1.644s 11 1.02x

🔍 Observability: Express | Nitro

Summary

Fastest Framework by World

Winner determined by most benchmark wins

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

Winner determined by most benchmark wins

Framework 🥇 Fastest World Wins
Express 🐘 Postgres 17/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)

📋 View full workflow run


Some benchmark jobs failed:

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

Check the workflow run for details.

Automated checkpoint commit.

Ploop-Iter: 1
Keep the cookbook surface canonical at /cookbooks so docs navigation, sitemap output, and AI/chat entry points stop leaking the legacy /docs/cookbook paths.

Correct the approval-chain example so the docs teach the intended sequential approval semantics instead of implying the workflow approves after the first successful level. This keeps the cookbook aligned with the docs quality bar and avoids misleading readers with inconsistent behavior.

Ploop-Iter: 2
Align cookbook-facing docs outputs with the new public route so
redirects, sitemap entries, and LLM-facing exports stay consistent.
This keeps the polished cookbook section discoverable at its canonical
location while trimming the last demo-heavy recipe examples toward the
same concise style as the rest of the docs.

Ploop-Iter: 3
Automated checkpoint commit.

Ploop-Iter: 4
Keep cookbook content discoverable after moving it to a first-class /cookbooks surface so navigation, canonical metadata, and markdown consumers resolve the new public URLs consistently.

Avoid serving the legacy /docs/cookbook tree as if it were still part of the docs section, which reduces duplicate navigation paths and prevents stale static output from competing with the new route structure.

Ploop-Iter: 5
The cookbook landing page needs to work for both exploratory users and users who already know the pattern they want. This keeps the guided decision tree while adding shared category metadata and a searchable browse mode so recipe discovery feels faster and more consistent with the rest of the docs experience.

Ploop-Iter: 6
Tighten the simplified cookbook recipes so the examples teach the intended workflow semantics clearly and consistently. The changes keep the documentation focused on the core control-flow patterns reviewers called out, while removing ambiguity around partial arrivals, deadlines, and first-success behavior.

Ploop-Iter: 7
Separate cookbook navigation from the docs page tree so the standalone /cookbooks experience stays stable after the route move and the main docs sidebar no longer leaks cookbook entries.\n\nThis keeps cookbook navigation driven by explicit recipe metadata, which avoids duplicated section titles and makes the docs and cookbook surfaces easier to evolve independently.\n\nPloop-Iter: 8
Keep cookbook pages on their public /cookbooks surface so metadata and copied markdown do not leak legacy /docs/cookbook paths.\n\nSimplify sidebar rendering to trust the injected page tree, which avoids route-specific filtering and keeps cookbook navigation consistent with the active layout tree.\n\nPloop-Iter: 9
Move cookbook rendering off the shared docs route so cookbook pages can behave like a first-class docs surface without leaking cookbook-specific UI into the main docs experience.

Centralizing cookbook tree filtering keeps sidebar behavior consistent in one place and avoids duplicate cookbook navigation state across layouts.

Ploop-Iter: 10
Improve the cookbooks entrypoint so loading and keyboard navigation
are usable without visual cues, and keep guided and browse modes
resilient while the route hydrates.

Ploop-Iter: 11
Automated checkpoint commit.

Ploop-Iter: 1
Clarify migration rules so agents choose the correct resume primitive, keep streaming guidance aligned with runtime behavior, and avoid implying Vercel-managed execution for self-hosted targets.

This reduces avoidable migration mistakes in generated guidance and keeps the skill consistent with the acceptance criteria used to evaluate it.

Ploop-Iter: 2
Automated checkpoint commit.

Ploop-Iter: 3
Reduce the migration skill entry point to the decision surface agents need\nso they can select the correct resume pattern without carrying duplicate\nexamples in the initial context.\n\nClarify framework precedence so prompts that explicitly ask for\nframework-agnostic boundaries do not get Hono- or Next-specific route\nshapes, while preserving framework-specific examples when requested.\n\nCentralize canonical resume examples in the shared patterns reference to\nkeep the guidance consistent across migration paths and reduce drift.\n\nPloop-Iter: 4
Add a cohesive set of deep-dive reference articles so the GA launch
has architecture-level documentation grounded in the current SDK
implementation. This gives readers verified explanations of runtime,
replay, streaming, compiler, and cost-model behavior while linking the
series together for easier navigation.

Ploop-Iter: 1
Automated checkpoint commit.

Ploop-Iter: 5
Keep the new deep-dive reference pages cross-linked so readers can move between adjacent runtime concepts without depending on older how-it-works pages alone.

This preserves navigational consistency across the GA launch docs set and reduces the chance that architectural explanations drift into isolated pages that are harder to discover and maintain.

Ploop-Iter: 2
Tighten the migration guidance so agents choose the correct resume surface and runtime boundary earlier, reducing incorrect mixed patterns in generated migrations.

Add explicit fast paths for self-hosted targets and Step Functions task-token callbacks so the skill stays consistent on callback URL vs deterministic resume decisions.

Ploop-Iter: 6
Clarify route selection so the migration skill composes resume, runtime, and app-boundary concerns deterministically. Add a canonical Step Functions self-hosted Hono callback recipe so migrations produce the correct callback-url pattern without mixing incompatible hook surfaces.\n\nPloop-Iter: 7
Preserve the verified GA launch deep-dive drafts in git so the campaign work can continue from a stable checkpoint.

Capture the reviewed documentation progress now to reduce risk of drift between source-backed research and the publishable drafts.

Ploop-Iter: 3
Clarify the migration skill's route-selection rules so generated guidance stays consistent across resume surfaces, runtime targets, and named framework boundaries.

This reduces ambiguous outputs where agents might mix framework syntaxes or invent callback routes for webhook-based flows, which leads to migration guidance that does not match the user's runtime model.

Ploop-Iter: 8
Clarify the runtime mechanics behind the GA deep-dive series so launch content stays aligned with the implementation and existing docs. Tightening these explanations reduces the risk of readers internalizing inaccurate mental models about replay, compilation, and workflow execution.\n\nPloop-Iter: 4
Clarify route selection so migrations choose the correct resume surface and app boundary patterns for the target runtime and framework. Strengthen verification guidance to reject invented callback routes in URL-based flows and keep examples aligned with the documented migration rules.

Ploop-Iter: 9
Align the compiler deep-dive trio with the actual Workflow runtime so launch materials describe the same execution model users rely on. This keeps the GA narrative accurate around deterministic replay, step queue triggers, and runtime bundle responsibilities, reducing the risk of docs teaching an architecture the SDK does not implement.

Ploop-Iter: 5
Reduce hot-path skill context so migration routing stays easier to select and
verify during activation.

Trimmed examples and converted long invalid samples into concise failure rules
so the skill points agents to on-demand references instead of loading bulky
worked code by default.

Ploop-Iter: 10
Clarify route-key planning and resume-surface defaults so migration outputs
stay deterministic when prompts underspecify callback behavior.

Strengthen the deep-dive docs to trace runtime handoffs more directly,
which reduces ambiguity about how the compiler split maps to durable
execution behavior.

Ploop-Iter: 11
Clarify the operational model behind durable streaming and zero-cost suspension so launch materials stay source-accurate for readers comparing workflow runtimes.

The updates make the workflow-step boundary, persistence path, and queue-driven cost story more explicit, reducing ambiguity around where stream I/O is allowed and why long waits do not consume compute.

Ploop-Iter: 6
Automated checkpoint commit.

Ploop-Iter: 12
Align the launch deep dives with the current runtime so campaign content does not misstate suspension behavior or streaming backend capabilities.

These edits clarify the distinct resume paths for step suspension versus timed waits and document the backend-specific streaming guarantees now available across local, Vercel, and Postgres worlds, reducing the risk that readers build incorrect mental models from launch materials.

Ploop-Iter: 7
Clarify when migrations should use deterministic internal resume versus generated callback URLs so skill outputs stay consistent across frameworks and hosting targets. Distinguish default webhook responses from manual-response flows to prevent ambiguous guidance and keep the shared callback references directly inspectable.\n\nPloop-Iter: 13
Clarify the runtime semantics behind suspension and durable streaming so the GA launch materials stay aligned with the source of truth.

These edits tighten descriptions around wake-up paths, backend behavior, and stream lifecycle details to reduce ambiguity for readers comparing the docs to the implementation.

Ploop-Iter: 8
Clarify when migrations should use the default webhook behavior versus
manual responses so agents make the same callback choice across the
skill entrypoint, shared patterns, and API reference.

This reduces avoidable ambiguity for callback-url prompts and makes the
default 202 behavior explicit unless a prompt requires custom response
semantics.

Ploop-Iter: 14
Prevent the GA launch materials from teaching an incorrect mental model about how suspended runs wake back up. The updated wording keeps the blog, social, and reference variants anchored to the real runtime paths so readers understand which transitions are queue-delayed, which are step-driven re-enqueues, and why that distinction matters for the cost story.

Ploop-Iter: 9
Automated checkpoint commit.

Ploop-Iter: 10
Explain the resume-surface decision points so migration and API guidance steer authors toward the correct webhook or hook pattern for the prompt.

Reduce common callback-routing mistakes early in the docs and skill so agents make fewer wrong assumptions during workflow migrations.

Ploop-Iter: 15
Clarify the cost-model narrative so launch materials make source-verifiable
claims about suspension, wake-up paths, and polling behavior.

This keeps the GA messaging aligned with the runtime's actual control
flow and avoids overclaiming where the implementation has narrower
semantics than the original copy suggested.

Ploop-Iter: 11
Keep the migration skill entrypoint small so agents load the routing contract only when the source actually pauses for external resume. Clarify the public webhook docs around the default callback flow to reduce accidental use of lower-level runtime APIs.\n\nPloop-Iter: 16
Align the launch materials with the current runtime semantics so the
cost-model and execution-model narrative stays defensible against the
actual implementation.

This keeps the GA campaign focused on claims we can support directly from
source, especially around suspension, re-enqueue behavior, and the
difference between orchestration compute and client-side polling helpers.

Ploop-Iter: 12
Align the cost-model launch content with the runtime's actual suspension and re-entry mechanics so GA messaging does not overstate identical-cost waits or imply residency that the queue-based engine does not have.

This keeps the public explanation consistent with source-backed behavior around timed wake-ups, explicit workflow re-queue after step completion, and the distinction between idle worker residency and boundary I/O.

Ploop-Iter: 13
Remove deep-dive articles, migration guides/skill, vercel-toolbar skill,
workflow-skills test fixtures, and misc artifacts that belong in separate
branches (deep-dives, migration-guides). Revert create-webhook.mdx,
getting-started/meta.json, and code-transform.mdx to main versions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant