refactor(swc-plugin): remove client transform mode, merge into step mode - #1686

Merged
TooTallNate merged 3 commits into
mainfrom
nr/remove-client-mode
Apr 16, 2026
Merged

refactor(swc-plugin): remove client transform mode, merge into step mode#1686
TooTallNate merged 3 commits into
mainfrom
nr/remove-client-mode

Conversation

@TooTallNate

@TooTallNateTooTallNate commented Apr 10, 2026

Copy link
Copy Markdown
Member

Summary

  • Remove the client transform mode from the SWC compiler plugin, merging it into step mode
  • The plugin now has 3 modes (Step, Workflow, Detect) instead of 4
  • All integrations that previously used mode: 'client' now use mode: 'step'

Motivation

The client and step modes were nearly identical — both preserved step function bodies, replaced workflow bodies with throw stubs, and emitted the same JSON manifest. The only differences were:

  1. Registration mechanism: client used a simple .stepId property assignment; step used an IIFE with global Map registration
  2. Dead code elimination: client ran DCE; step did not
  3. Object property step call sites: client replaced inline functions with hoisted variable references; step kept the original inline copy

None of these differences were fundamentally necessary. Merging them simplifies the codebase by ~450 lines of Rust and removes 67 test fixture files.

What changed in step mode

  • DCE now runs — removes dead code just like it did in client mode, preserving step bodies and their dependencies
  • Object property steps use hoisted variable references at call sites so .stepId is accessible on the same function object
  • IIFE registration is unchanged — all step functions are registered in the global Map

Changed packages

PackageChange
@workflow/swc-pluginRemoved Client variant from TransformMode enum, ~450 lines of client-specific match arms
@workflow/nextloader.ts now always uses mode: 'step'
@workflow/buildersbase-builder.ts, apply-swc-transform.ts, swc-esbuild-plugin.ts — removed 'client' from types and mode values
@workflow/cliRemoved 'client' from transform command options
@workflow/rollupChanged mode: 'client' to mode: 'step'
@workflow/nestChanged mode: 'client' to mode: 'step'
@workflow/swc-playground-wasmRemoved client output from batch transform

@github-actions

github-actionsBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production923067990
✅ 💻 Local Development9940861080
✅ 📦 Local Production9940861080
✅ 🐘 Local Postgres9940861080
✅ 🪟 Windows900090
❌ 🌍 Community Worlds133980231
✅ 📋 Other252018270
Total4380983434821

❌ Failed Tests

🌍 Community Worlds (98 failed)

mongodb (15 failed):

  • readableStreamWorkflow | wrun_01KPC49NNZW9YY0KB64K6VSQHB
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KPC4AC42WBKTER23K36G2ZAT
  • webhookWorkflow | wrun_01KPC4AMQBQNMGQ4RMS3XNMX4K
  • outputStreamWorkflow no startIndex (reads all chunks)
  • outputStreamWorkflow positive startIndex (skips first chunk)
  • outputStreamWorkflow negative startIndex (reads from end)
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns correct index after stream completes
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns -1 before any chunks are written
  • outputStreamWorkflow - getTailIndex and getChunks getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KPC4DTF69CSG9SGAXK101SCA
  • fetchWorkflow | wrun_01KPC4E7RZPD314K6BKBYSXGT0
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KPC4JB5B6GKYQ4NA68WW9JFN
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • health check (CLI) - workflow health command reports healthy endpoints
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KPC4RK5F4H2A50VNYVKYDZYH

redis (15 failed):

  • readableStreamWorkflow | wrun_01KPC49NNZW9YY0KB64K6VSQHB
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KPC4AC42WBKTER23K36G2ZAT
  • webhookWorkflow | wrun_01KPC4AMQBQNMGQ4RMS3XNMX4K
  • outputStreamWorkflow no startIndex (reads all chunks)
  • outputStreamWorkflow positive startIndex (skips first chunk)
  • outputStreamWorkflow negative startIndex (reads from end)
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns correct index after stream completes
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns -1 before any chunks are written
  • outputStreamWorkflow - getTailIndex and getChunks getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KPC4DTF69CSG9SGAXK101SCA
  • fetchWorkflow | wrun_01KPC4E7RZPD314K6BKBYSXGT0
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KPC4JB5B6GKYQ4NA68WW9JFN
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • health check (CLI) - workflow health command reports healthy endpoints
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KPC4RK5F4H2A50VNYVKYDZYH

turso (68 failed):

  • addTenWorkflow | wrun_01KPC494JMXC2S698ZCV0Z1A6J
  • addTenWorkflow | wrun_01KPC494JMXC2S698ZCV0Z1A6J
  • wellKnownAgentWorkflow (.well-known/agent) | wrun_01KPC4AGDR3W8R8RXJT4B0AAA1
  • should work with react rendering in step
  • promiseAllWorkflow | wrun_01KPC49C06JB8S19BQWT39ZGY3
  • promiseRaceWorkflow | wrun_01KPC49GDW34C2CAXQED5GQ5HD
  • promiseAnyWorkflow | wrun_01KPC49JF67R2674SKNT0B531G
  • importedStepOnlyWorkflow | wrun_01KPC4ATXWJTKEXDX5AZ5QQ00W
  • readableStreamWorkflow | wrun_01KPC49NNZW9YY0KB64K6VSQHB
  • hookWorkflow | wrun_01KPC4A08KB58ENADF0R99QWRK
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KPC4AC42WBKTER23K36G2ZAT
  • webhookWorkflow | wrun_01KPC4AMQBQNMGQ4RMS3XNMX4K
  • sleepingWorkflow | wrun_01KPC4ATTECEVNJQ03J54ZFBVM
  • parallelSleepWorkflow | wrun_01KPC4B757NA7GCQPA911F04ZY
  • nullByteWorkflow | wrun_01KPC4BBA9SENAQ2793T64G2HD
  • workflowAndStepMetadataWorkflow | wrun_01KPC4BD6G7ZV66PGPFA4QPD88
  • outputStreamWorkflow no startIndex (reads all chunks)
  • outputStreamWorkflow positive startIndex (skips first chunk)
  • outputStreamWorkflow negative startIndex (reads from end)
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns correct index after stream completes
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns -1 before any chunks are written
  • outputStreamWorkflow - getTailIndex and getChunks getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KPC4DTF69CSG9SGAXK101SCA
  • fetchWorkflow | wrun_01KPC4E7RZPD314K6BKBYSXGT0
  • promiseRaceStressTestWorkflow | wrun_01KPC4EB2BAVKDBD6MS0ZQ6EA2
  • 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_01KPC4HQX6G61Z1EVG4JNP930D
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KPC4JB5B6GKYQ4NA68WW9JFN
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KPC4JYZ7FS1R557Y32RKYX4X
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KPC4KHC0489EJS7TH6H8C1FP
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_01KPC4KSEB6GVW9G0XXRPWE3J8
  • closureVariableWorkflow - nested step functions with closure variables | wrun_01KPC4KYK1XY4DHRRTHJ2T1M21
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_01KPC4M0KZH3ASYEG5R6JBWENC
  • runClassSerializationWorkflow - Run instances serialize across workflow/step boundaries | wrun_01KPC4MB45KDRW8N8D6WN06XEQ
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • health check (CLI) - workflow health command reports healthy endpoints
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_01KPC4MS5KHDWDK2F94N22ZFQW
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_01KPC4MZ6PEQNSM56KWF9FJX1E
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_01KPC4N5GZH4ZFPZPW62YEP6KV
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_01KPC4NBR68W7CSHPE7R7M4EK3
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_01KPC4NHS0ARKDVB77N2MX3CAC
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_01KPC4NQW6FWS4MXN0R48DA026
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_01KPC4NZ0FPXKMQX3X2CQ04PBG
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_01KPC4P9N2G26Q97QRYDQ0Y9YK
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_01KPC4PGZWQE4GQXWWGY0QH4J7
  • cancelRun - cancelling a running workflow | wrun_01KPC4PR5VZ7PAPEH1FB5DTEBH
  • cancelRun via CLI - cancelling a running workflow | wrun_01KPC4Q0WDH365KZXRFP7S3YXX
  • 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_01KPC4QC7VC0XAK4HG5DG72TYK
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KPC4QZCT792E4TFQ8YN5Q6BV
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KPC4R9ARDE36CTKSVKBD0BV7
  • importMetaUrlWorkflow - import.meta.url is available in step bundles | wrun_01KPC4RF7T0AJ9JST4ZEVXQBYY
  • metadataFromHelperWorkflow - getWorkflowMetadata/getStepMetadata work from module-level helper (#1577) | wrun_01KPC4RH3HCX2FND5E2Q3889HY
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KPC4RK5F4H2A50VNYVKYDZYH
  • getterStepWorkflow - getter functions with "use step" directive | wrun_01KPC4RP4RG6MQ9C0QJJXPXG6F

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro8307
✅ example8307
✅ express8307
✅ fastify8307
✅ hono8307
✅ nextjs-turbopack8802
✅ nextjs-webpack8802
✅ nitro8307
✅ nuxt8307
✅ sveltekit8307
✅ vite8307
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable8406
✅ express-stable8406
✅ fastify-stable8406
✅ hono-stable8406
✅ nextjs-turbopack-canary71019
✅ nextjs-turbopack-stable9000
✅ nextjs-webpack-canary71019
✅ nextjs-webpack-stable9000
✅ nitro-stable8406
✅ nuxt-stable8406
✅ sveltekit-stable8406
✅ vite-stable8406
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable8406
✅ express-stable8406
✅ fastify-stable8406
✅ hono-stable8406
✅ nextjs-turbopack-canary71019
✅ nextjs-turbopack-stable9000
✅ nextjs-webpack-canary71019
✅ nextjs-webpack-stable9000
✅ nitro-stable8406
✅ nuxt-stable8406
✅ sveltekit-stable8406
✅ vite-stable8406
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable8406
✅ express-stable8406
✅ fastify-stable8406
✅ hono-stable8406
✅ nextjs-turbopack-canary71019
✅ nextjs-turbopack-stable9000
✅ nextjs-webpack-canary71019
✅ nextjs-webpack-stable9000
✅ nitro-stable8406
✅ nuxt-stable8406
✅ sveltekit-stable8406
✅ vite-stable8406
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack9000
❌ 🌍 Community Worlds
AppPassedFailedSkipped
✅ mongodb-dev600
❌ mongodb56150
✅ redis-dev600
❌ redis56150
✅ turso-dev600
❌ turso3680
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable8406
✅ e2e-local-postgres-nest-stable8406
✅ e2e-local-prod-nest-stable8406

📋 View full workflow run

@github-actions

github-actionsBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

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

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express0.044s (-0.9%)1.005s (~)0.961s101.00x
💻 LocalNitro0.044s (+1.9%)1.005s (~)0.961s101.00x
💻 LocalNext.js (Turbopack)0.047s1.005s0.958s101.08x
🐘 PostgresNitro0.053s (-44.2% 🟢)1.011s (-3.1%)0.957s101.21x
🐘 PostgresNext.js (Turbopack)0.056s1.010s0.954s101.27x
🐘 PostgresExpress0.057s (-1.6%)1.011s (~)0.954s101.30x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro0.232s (-43.5% 🟢)2.120s (-15.5% 🟢)1.888s101.00x
▲ VercelNext.js (Turbopack)0.265s (+5.5% 🔺)2.026s (-13.2% 🟢)1.760s101.15x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Next.js (Turbopack)1.122s2.006s0.884s101.00x
🐘 PostgresNitro1.124s (-1.4%)2.009s (~)0.885s101.00x
💻 LocalNitro1.131s (~)2.006s (~)0.875s101.01x
💻 LocalExpress1.134s (+0.8%)2.007s (~)0.872s101.01x
🐘 PostgresNext.js (Turbopack)1.136s2.011s0.875s101.01x
🐘 PostgresExpress1.154s (+0.6%)2.010s (~)0.856s101.03x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro1.948s (-50.0% 🟢)3.730s (-36.9% 🟢)1.782s101.00x
▲ VercelNext.js (Turbopack)1.978s (-2.8%)3.253s (-15.1% 🟢)1.275s101.02x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro10.738s (-1.2%)11.025s (~)0.287s31.00x
💻 LocalNext.js (Turbopack)10.830s11.023s0.193s31.01x
🐘 PostgresExpress10.894s (-0.6%)11.025s (~)0.131s31.01x
💻 LocalNitro10.920s (~)11.022s (~)0.102s31.02x
🐘 PostgresNext.js (Turbopack)10.927s11.018s0.091s31.02x
💻 LocalExpress10.947s (~)11.024s (~)0.078s31.02x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro17.104s (-27.9% 🟢)19.463s (-22.5% 🟢)2.360s21.00x
▲ VercelNext.js (Turbopack)17.338s (~)18.457s (-4.9%)1.119s21.01x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro14.143s (-3.1%)15.027s (~)0.884s41.00x
🐘 PostgresNext.js (Turbopack)14.476s15.029s0.553s41.02x
💻 LocalNext.js (Turbopack)14.575s15.028s0.454s41.03x
🐘 PostgresExpress14.575s (~)15.026s (~)0.451s41.03x
💻 LocalNitro14.924s (-0.9%)15.029s (-6.2% 🟢)0.104s41.06x
💻 LocalExpress15.108s (+0.9%)16.032s (+6.7% 🔺)0.924s41.07x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro32.373s (-49.8% 🟢)34.553s (-48.1% 🟢)2.179s21.00x
▲ VercelNext.js (Turbopack)33.318s (-36.6% 🟢)34.394s (-37.0% 🟢)1.076s21.03x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro13.235s (-5.2% 🟢)13.880s (-3.0%)0.645s71.00x
🐘 PostgresExpress13.877s (-0.9%)14.022s (-3.9%)0.145s71.05x
🐘 PostgresNext.js (Turbopack)13.974s14.455s0.481s71.06x
💻 LocalNext.js (Turbopack)15.884s16.196s0.312s61.20x
💻 LocalNitro16.479s (-1.8%)17.030s (~)0.552s61.25x
💻 LocalExpress16.807s (+1.2%)17.031s (~)0.224s61.27x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro55.193s (-86.9% 🟢)57.639s (-86.4% 🟢)2.446s21.00x
▲ VercelNext.js (Turbopack)59.836s (-84.8% 🟢)60.966s (-84.6% 🟢)1.130s21.08x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.223s (-4.1%)2.009s (~)0.787s151.00x
🐘 PostgresExpress1.251s (-0.8%)2.010s (~)0.760s151.02x
🐘 PostgresNext.js (Turbopack)1.252s2.009s0.756s151.02x
💻 LocalNext.js (Turbopack)1.488s2.005s0.517s151.22x
💻 LocalNitro1.498s (-8.2% 🟢)2.006s (-3.3%)0.507s151.23x
💻 LocalExpress1.528s (+2.6%)2.006s (~)0.477s151.25x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.389s (-15.2% 🟢)3.777s (-12.6% 🟢)1.388s91.00x
▲ VercelNext.js (Turbopack)2.457s (-27.7% 🟢)3.702s (-25.0% 🟢)1.244s91.03x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro2.320s (-1.3%)3.009s (~)0.689s101.00x
🐘 PostgresExpress2.335s (-1.1%)3.008s (~)0.674s101.01x
🐘 PostgresNext.js (Turbopack)2.393s3.010s0.617s101.03x
💻 LocalNext.js (Turbopack)2.874s3.309s0.435s101.24x
💻 LocalNitro2.898s (-7.8% 🟢)3.453s (-11.1% 🟢)0.555s91.25x
💻 LocalExpress3.040s (+3.0%)3.759s (+8.8% 🔺)0.719s81.31x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.873s (-29.1% 🟢)4.645s (-21.5% 🟢)1.772s71.00x
▲ VercelNext.js (Turbopack)3.637s (-48.8% 🟢)5.185s (-41.8% 🟢)1.548s61.27x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro3.426s (-1.5%)4.010s (~)0.583s81.00x
🐘 PostgresExpress3.459s (-0.8%)4.010s (~)0.551s81.01x
🐘 PostgresNext.js (Turbopack)3.689s4.010s0.321s81.08x
💻 LocalNext.js (Turbopack)7.497s8.019s0.522s42.19x
💻 LocalNitro8.051s (-3.6%)8.772s (-2.8%)0.721s42.35x
💻 LocalExpress8.203s (-1.6%)9.020s (~)0.817s42.39x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro3.559s (+1.0%)5.051s (-8.7% 🟢)1.492s61.00x
▲ VercelNext.js (Turbopack)6.803s (-23.7% 🟢)8.029s (-26.7% 🟢)1.226s41.91x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.209s (-3.8%)2.009s (~)0.800s151.00x
🐘 PostgresNext.js (Turbopack)1.228s2.010s0.782s151.02x
🐘 PostgresExpress1.267s (+0.8%)2.008s (~)0.741s151.05x
💻 LocalNitro1.515s (-18.8% 🟢)2.005s (-14.3% 🟢)0.490s151.25x
💻 LocalNext.js (Turbopack)1.531s2.006s0.475s151.27x
💻 LocalExpress1.544s (-18.5% 🟢)2.006s (-15.1% 🟢)0.462s151.28x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.037s (-17.2% 🟢)3.718s (-10.8% 🟢)1.681s91.00x
▲ VercelNext.js (Turbopack)2.401s (-18.1% 🟢)3.792s (-18.3% 🟢)1.391s81.18x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro2.327s (-0.5%)3.010s (~)0.683s101.00x
🐘 PostgresExpress2.336s (~)3.010s (~)0.674s101.00x
🐘 PostgresNext.js (Turbopack)2.393s3.008s0.616s101.03x
💻 LocalNext.js (Turbopack)2.787s3.452s0.665s91.20x
💻 LocalNitro2.836s (-7.5% 🟢)3.309s (-14.9% 🟢)0.473s101.22x
💻 LocalExpress3.261s (+4.1%)4.011s (+6.6% 🔺)0.750s81.40x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.598s (-19.7% 🟢)4.042s (-20.4% 🟢)1.444s81.00x
▲ VercelNext.js (Turbopack)2.787s (-11.3% 🟢)4.209s (-6.9% 🟢)1.422s81.07x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro3.456s (-0.7%)4.011s (~)0.555s81.00x
🐘 PostgresExpress3.480s (-0.5%)4.010s (~)0.530s81.01x
🐘 PostgresNext.js (Turbopack)3.617s4.012s0.395s81.05x
💻 LocalNext.js (Turbopack)7.510s8.018s0.507s42.17x
💻 LocalNitro8.662s (-5.3% 🟢)9.275s (-7.5% 🟢)0.613s42.51x
💻 LocalExpress8.993s (+2.2%)9.273s (~)0.279s42.60x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.764s (-45.7% 🟢)4.520s (-33.7% 🟢)1.756s71.00x
▲ VercelNext.js (Turbopack)4.827s (-28.6% 🟢)6.399s (-25.1% 🟢)1.572s51.75x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.624s (-23.9% 🟢)1.006s (~)0.382s601.00x
🐘 PostgresNext.js (Turbopack)0.786s1.023s0.237s591.26x
🐘 PostgresExpress0.808s (-3.7%)1.022s (~)0.214s591.29x
💻 LocalNext.js (Turbopack)0.852s1.039s0.187s581.36x
💻 LocalNitro0.988s (+0.8%)1.158s (+5.9% 🔺)0.170s521.58x
💻 LocalExpress0.989s (~)1.250s (+16.1% 🔺)0.261s491.58x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro10.124s (-54.1% 🟢)12.026s (-49.9% 🟢)1.902s51.00x
▲ VercelNext.js (Turbopack)11.473s (-20.9% 🟢)12.880s (-19.9% 🟢)1.407s51.13x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.503s (-22.0% 🟢)2.007s (-4.4%)0.504s451.00x
🐘 PostgresExpress1.918s (-3.0%)2.100s (-7.0% 🟢)0.183s431.28x
🐘 PostgresNext.js (Turbopack)1.959s2.203s0.244s411.30x
💻 LocalNext.js (Turbopack)2.627s3.008s0.381s301.75x
💻 LocalNitro3.004s (-1.0%)3.508s (-6.7% 🟢)0.504s262.00x
💻 LocalExpress3.039s (+0.8%)3.690s (+2.9%)0.651s252.02x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)32.147s (-35.5% 🟢)33.634s (-35.0% 🟢)1.487s31.00x
▲ VercelNitro37.762s (-4.4%)39.759s (-3.7%)1.997s31.17x
▲ VercelExpress⚠️missing----

🔍 Observability: Next.js (Turbopack) | Nitro

workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro3.164s (-22.9% 🟢)3.824s (-16.9% 🟢)0.660s321.00x
🐘 PostgresNext.js (Turbopack)3.883s4.147s0.264s291.23x
🐘 PostgresExpress3.890s (-2.5%)4.110s (-5.9% 🟢)0.219s301.23x
💻 LocalNext.js (Turbopack)8.566s9.018s0.452s142.71x
💻 LocalExpress9.269s (+0.6%)10.019s (~)0.749s122.93x
💻 LocalNitro9.497s (+2.1%)10.101s (+0.8%)0.604s123.00x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro77.978s (-19.5% 🟢)79.827s (-18.9% 🟢)1.850s21.00x
▲ VercelNext.js (Turbopack)89.255s (-16.7% 🟢)90.555s (-16.9% 🟢)1.300s21.14x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.235s (-16.9% 🟢)1.007s (~)0.772s601.00x
🐘 PostgresNext.js (Turbopack)0.256s1.008s0.751s601.09x
🐘 PostgresExpress0.285s (+0.8%)1.007s (~)0.723s601.21x
💻 LocalNext.js (Turbopack)0.575s1.004s0.430s602.44x
💻 LocalExpress0.615s (+9.8% 🔺)1.022s (+1.7%)0.407s592.61x
💻 LocalNitro0.668s (+10.5% 🔺)1.095s (+7.2% 🔺)0.427s552.84x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro1.858s (+11.9% 🔺)3.442s (+2.7%)1.584s181.00x
▲ VercelNext.js (Turbopack)5.248s (+159.5% 🔺)6.681s (+76.1% 🔺)1.432s92.82x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.383s (-22.8% 🟢)1.006s (~)0.623s901.00x
🐘 PostgresExpress0.488s (-4.2%)1.007s (~)0.519s901.27x
🐘 PostgresNext.js (Turbopack)0.503s1.007s0.503s901.31x
💻 LocalNitro2.463s (-3.0%)3.009s (~)0.546s306.43x
💻 LocalExpress2.591s (+3.1%)3.009s (~)0.418s306.76x
💻 LocalNext.js (Turbopack)2.594s3.008s0.414s306.77x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro5.501s (+70.5% 🔺)7.445s (+54.4% 🔺)1.944s131.00x
▲ VercelNext.js (Turbopack)8.725s (+146.8% 🔺)10.373s (+99.7% 🔺)1.648s91.59x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.614s (-22.3% 🟢)1.007s (~)0.393s1201.00x
🐘 PostgresNext.js (Turbopack)0.800s1.008s0.208s1201.30x
🐘 PostgresExpress0.802s (-2.0%)1.016s (~)0.214s1191.31x
💻 LocalNext.js (Turbopack)10.669s11.392s0.723s1117.38x
💻 LocalNitro10.798s (-3.5%)11.300s (-3.1%)0.501s1117.59x
💻 LocalExpress11.456s (+2.4%)12.032s (+0.8%)0.576s1018.66x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro9.424s (+22.0% 🔺)11.667s (+24.1% 🔺)2.243s111.00x
▲ VercelNext.js (Turbopack)15.660s (+51.6% 🔺)16.985s (+38.2% 🔺)1.325s81.66x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.177s (-13.8% 🟢)0.997s (~)0.001s (-20.0% 🟢)1.011s (~)0.834s101.00x
💻 LocalNext.js (Turbopack)0.188s1.003s0.011s1.017s0.830s101.06x
🐘 PostgresNext.js (Turbopack)0.192s1.001s0.002s1.011s0.818s101.09x
💻 LocalNitro0.201s (-6.2% 🟢)1.004s (~)0.011s (-9.6% 🟢)1.017s (~)0.817s101.13x
💻 LocalExpress0.204s (+2.5%)1.004s (~)0.013s (+8.3% 🔺)1.020s (~)0.816s101.15x
🐘 PostgresExpress0.204s (~)1.001s (~)0.002s (+6.2% 🔺)1.011s (~)0.806s101.16x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)1.554s (-77.3% 🟢)2.748s (-68.2% 🟢)0.996s (+57.7% 🔺)4.134s (-57.8% 🟢)2.581s101.00x
▲ VercelNitro1.705s (-55.5% 🟢)2.818s (-46.6% 🟢)1.037s (+39.8% 🔺)4.300s (-33.7% 🟢)2.594s101.10x
▲ VercelExpress⚠️missing-----

🔍 Observability: Next.js (Turbopack) | Nitro

stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.531s (-14.9% 🟢)1.008s (~)0.004s (-14.3% 🟢)1.022s (~)0.491s591.00x
🐘 PostgresExpress0.607s (-3.6%)1.006s (~)0.004s (+3.1%)1.023s (~)0.416s591.14x
🐘 PostgresNext.js (Turbopack)0.617s1.008s0.003s1.020s0.402s591.16x
💻 LocalNitro0.742s (-11.6% 🟢)1.012s (~)0.009s (-2.5%)1.023s (-8.3% 🟢)0.281s591.40x
💻 LocalNext.js (Turbopack)0.806s1.011s0.013s1.120s0.313s541.52x
💻 LocalExpress0.956s (+26.2% 🔺)1.012s (-1.6%)0.010s (+5.4% 🔺)1.229s (+18.2% 🔺)0.273s491.80x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro4.889s (-83.4% 🟢)6.748s (-78.1% 🟢)0.465s (+315.1% 🔺)7.635s (-76.0% 🟢)2.746s81.00x
▲ VercelNext.js (Turbopack)14.674s (-13.3% 🟢)15.526s (-14.9% 🟢)0.211s (~)16.076s (-15.1% 🟢)1.403s53.00x
▲ VercelExpress⚠️missing-----

🔍 Observability: Nitro | Next.js (Turbopack)

10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.938s1.112s0.000s1.119s0.182s541.00x
🐘 PostgresNitro0.944s (-2.6%)1.177s (-5.7% 🟢)0.000s (+41.2% 🔺)1.190s (-5.4% 🟢)0.246s511.01x
🐘 PostgresExpress0.974s (+1.4%)1.219s (-4.6%)0.000s (+87.8% 🔺)1.243s (-4.9%)0.269s491.04x
💻 LocalNitro1.214s (-0.7%)2.021s (~)0.000s (+33.3% 🔺)2.022s (~)0.808s301.30x
💻 LocalExpress1.238s (+1.0%)2.020s (~)0.000s (-10.0% 🟢)2.022s (~)0.785s301.32x
💻 LocalNext.js (Turbopack)1.296s2.019s0.000s2.023s0.727s301.38x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro6.050s (+98.3% 🔺)7.665s (+74.5% 🔺)0.000s (-100.0% 🟢)8.112s (+68.7% 🔺)2.062s81.00x
▲ VercelNext.js (Turbopack)7.695s (-24.4% 🟢)7.641s (-33.7% 🟢)0.000s (NaN%)9.028s (-25.1% 🟢)1.333s71.27x
▲ VercelExpress⚠️missing-----

🔍 Observability: Nitro | Next.js (Turbopack)

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

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.720s (-4.0%)2.104s (-1.7%)0.000s (+93.1% 🔺)2.112s (-2.9%)0.392s291.00x
🐘 PostgresExpress1.727s (-2.5%)2.104s (-3.4%)0.000s (NaN%)2.113s (-3.9%)0.386s291.00x
🐘 PostgresNext.js (Turbopack)1.888s2.182s0.000s2.189s0.301s281.10x
💻 LocalNitro3.502s (+3.4%)4.035s (~)0.001s (+50.0% 🔺)4.038s (~)0.536s152.04x
💻 LocalExpress3.589s (+3.5%)4.030s (~)0.000s (-58.3% 🟢)4.033s (~)0.444s152.09x
💻 LocalNext.js (Turbopack)3.746s4.166s0.000s4.170s0.424s152.18x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)5.451s (-3.0%)6.756s (-3.2%)0.000s (-100.0% 🟢)7.096s (-5.9% 🟢)1.645s91.00x
▲ VercelNitro8.938s (+118.3% 🔺)10.290s (+91.5% 🔺)0.000s (-100.0% 🟢)10.758s (+85.7% 🔺)1.819s61.64x
▲ VercelExpress⚠️missing-----

🔍 Observability: Next.js (Turbopack) | Nitro

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalNext.js (Turbopack)15/21
🐘 PostgresNitro20/21
▲ VercelNitro18/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres18/21
Next.js (Turbopack)🐘 Postgres17/21
Nitro🐘 Postgres19/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

@changeset-bot

changeset-botBot commented Apr 10, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: dc6415b

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

This PR includes changesets to release 18 packages
NameType
@workflow/swc-pluginMajor
@workflow/buildersPatch
@workflow/cliPatch
@workflow/nextPatch
@workflow/rollupPatch
@workflow/nestPatch
@workflow/astroPatch
@workflow/nitroPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/vitestPatch
workflowPatch
@workflow/world-testingPatch
@workflow/nuxtPatch
@workflow/aiPatch
@workflow/corePatch
@workflow/web-sharedPatch
@workflow/webPatch

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

vercelBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

@TooTallNate
TooTallNateforce-pushed the nr/remove-client-mode branch from aac9033 to cf9fe73CompareApril 10, 2026 17:20
Remove the `client` transform mode from the SWC compiler plugin. The
`client` and `step` modes were nearly identical — both preserved step
function bodies, replaced workflow bodies with throw stubs, and emitted
the same JSON manifest. Step mode now absorbs all client-mode behaviors:
- Dead code elimination (previously only workflow + client)
- Hoisted variable references for object property steps
- All integrations use mode: 'step' instead of 'client'
BREAKING CHANGE: The `client` value for the SWC plugin `mode` option is
no longer accepted. Use `step` instead.
…sId registration
In dev mode, Nitro's Rollup externalizes npm packages like @workflow/core,
so the SWC transform plugin never processes files like run.js. This means
serde classes (e.g. Run) never get the classId registration IIFE, causing
serialization failures when step functions return Run instances.
Uses a Rollup resolveId hook to force workflow SDK packages to be bundled
(non-external) while leaving all other dependencies external. This is more
targeted than noExternals=true which bundles everything and causes TDZ
errors from circular imports in packages like vue-bundle-renderer/h3.
The Nitro module now also ignores .nitro/workflow/** in watchOptions so
writing generated workflow bundles does not retrigger Nitro's own dev
bundle rebuild loop.
Also wraps dev:reload workflow rebuilds and makes LocalBuilder.build()
atomic (writes to temp files, renames on success) to avoid partial output
state during HMR.
For Nuxt, also configures Vite's ssr.noExternal to bundle workflow
packages in the SSR context.

CopilotAI left a comment

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.

Pull request overview

Removes the SWC plugin’s client transform mode by merging its behavior into step mode, and updates all repository integrations, docs, and fixtures to use the new 3-mode model (Step/Workflow/Detect).

Changes:

  • Dropped Client from TransformMode, updated step mode to include client-mode behaviors (notably DCE + object-property hoisting semantics), and removed client-mode fixture runners/outputs.
  • Updated framework/tooling integrations (Next loader, Rollup, Nest CLI, Builders, CLI) to use mode: 'step' everywhere client was previously used.
  • Updated docs/spec and the SWC playground (WASM + UI/types) to remove the client output/view.

Reviewed changes

Copilot reviewed 103 out of 103 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
workbench/swc-playground/wasm/src/lib.rsRemoves client from batch transform output and runs only workflow+step.
workbench/swc-playground/lib/transform.tsUpdates TS types to drop client transform result.
workbench/swc-playground/components/swc-playground.tsxRemoves client view/panel/state in the playground UI.
packages/swc-plugin-workflow/transform/src/lib.rsRemoves Client mode and folds client behaviors into Step (DCE, hoisting/registration paths, etc.).
packages/swc-plugin-workflow/spec.mdUpdates specification to reflect 3 modes and step-mode DCE/hoisting behavior.
packages/swc-plugin-workflow/transform/tests/fixture.rsRemoves the client-mode fixture test harness.
packages/swc-plugin-workflow/transform/tests/errors.rsRemoves the client-mode errors fixture harness and updates imports.
packages/swc-plugin-workflow/transform/tests/fixture/workflow-client-property/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/workflow-arrow-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/var-named-step-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/using-declaration-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/using-declaration-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/user-named-dunder-default/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/unused-variables-and-types/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/unused-variables-and-types/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/unused-exports/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/unused-exports/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step/output-step.jsUpdates step-mode fixture to reflect new object-property hoisting behavior.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step-default-export/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step-class/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/step-with-this-arguments-super/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/step-with-imports/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/step-with-imports/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/step-arrow-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/static-method-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/static-method-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/static-getter-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/single-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/single-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/separate-export-statement/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/private-member-dce/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/private-member-dce-native/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/object-property-step/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/object-property-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/object-getter-step/output-step.jsUpdates step-mode fixture to reflect object getter/property behavior.
packages/swc-plugin-workflow/transform/tests/fixture/object-getter-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/nested-steps-in-object-constructor/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/nested-steps-in-object-constructor/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/nested-step-with-closure/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/nested-step-with-closure/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/nested-step-in-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/multiple-const-step-functions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-workflow/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-step/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/mixed-functions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/let-arrow-step-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/instance-method-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/instance-method-nested-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/instance-getter-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/expr-fn-default-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-named/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-anonymous/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-anonymous-step-only/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/destructuring/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/default-workflow-collision/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/output-workflow.jsUpdates fixture to reflect export changes under new behavior.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/output-step.jsUpdates fixture to reflect export changes under new behavior.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/input.jsUpdates input fixture to be exported (aligning outputs).
packages/swc-plugin-workflow/transform/tests/fixture/default-arrow-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/deeply-nested-step/output-step.jsUpdates step-mode fixture to reflect hoisted reference usage.
packages/swc-plugin-workflow/transform/tests/fixture/deeply-nested-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-require-namespace/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-require-destructured/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-local-const/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-imported/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/closure-typescript-expressions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/closure-new-expr-and-module-declarations/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/class-expression-binding-name/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/class-expression-binding-name-step-methods/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/anonymous-default-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step-shorthand-method/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step-shorthand-method/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/sync-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/non-async-functions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misspelled-workflow-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misspelled-step-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misplaced-module-directive/output-step.jsUpdates step-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misplaced-module-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misplaced-function-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/invalid-exports/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/invalid-default-exports-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/instance-methods/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/getter-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/next/src/loader.tsSwitches all transforms to mode: 'step'.
packages/rollup/src/index.tsSwitches Rollup integration transform mode to step.
packages/nest/src/cli.tsUpdates generated .swcrc to use mode: 'step' and help text accordingly.
packages/cli/src/commands/transform.tsRemoves client from CLI transform modes/options.
packages/builders/src/apply-swc-transform.tsUpdates API type to drop client mode.
packages/builders/src/swc-esbuild-plugin.tsUpdates SwcPluginOptions.mode type to drop client.
packages/builders/src/base-builder.tsUpdates builder SWC plugin usage from client to step.
packages/nuxt/src/module.tsForces Vite SSR bundling behavior for workflow packages and marks _vite for Nitro.
packages/nitro/src/index.tsAdds dev-only rollup force-inline plugin and dev-time dynamic loading of generated workflow bundles.
packages/nitro/src/builders.tsWrites workflow bundles to temp files first and renames into place.
.changeset/remove-client-mode.mdAdds changeset documenting the breaking removal of client mode and migration guidance.

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

Comment threadpackages/nitro/src/builders.ts Outdated
Comment threadpackages/nuxt/src/module.ts Outdated
Comment threadpackages/nitro/src/index.ts Outdated
- nitro builders: use crypto.randomUUID() for temp file suffix instead of
Date.now() to avoid collisions under rapid/concurrent build() calls,
and serialize concurrent build() calls through an internal queue so
two overlapping dev rebuilds cannot clobber each other's temp outputs.
- nitro index: use fileURLToPath() to convert file:// URLs to filesystem
paths, which correctly handles Windows paths (file:///C:/... -> C:\...)
and percent-decoding, instead of relying on new URL(...).pathname.
- nuxt module: normalize vite.ssr.noExternal to an array (preserving any
existing string/RegExp/array entry) before appending workflow package
matchers, so the force-bundle behavior is not a no-op when noExternal
is already set to a non-array value.

@VaguelySeriousVaguelySerious left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM assuming tests pass, we're only landing this on v5 right?

@TooTallNate

Copy link
Copy Markdown
MemberAuthor

@VaguelySerious correct

Sign up for freeto 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

@TooTallNate@ijjk@VaguelySerious
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

refactor(swc-plugin): remove client transform mode, merge into step mode - #1686

Merged
TooTallNate merged 3 commits into
mainfrom
nr/remove-client-mode
Apr 16, 2026
Merged

refactor(swc-plugin): remove client transform mode, merge into step mode#1686
TooTallNate merged 3 commits into
mainfrom
nr/remove-client-mode

Conversation

@TooTallNate

@TooTallNateTooTallNate commented Apr 10, 2026

Copy link
Copy Markdown
Member

Summary

  • Remove the client transform mode from the SWC compiler plugin, merging it into step mode
  • The plugin now has 3 modes (Step, Workflow, Detect) instead of 4
  • All integrations that previously used mode: 'client' now use mode: 'step'

Motivation

The client and step modes were nearly identical — both preserved step function bodies, replaced workflow bodies with throw stubs, and emitted the same JSON manifest. The only differences were:

  1. Registration mechanism: client used a simple .stepId property assignment; step used an IIFE with global Map registration
  2. Dead code elimination: client ran DCE; step did not
  3. Object property step call sites: client replaced inline functions with hoisted variable references; step kept the original inline copy

None of these differences were fundamentally necessary. Merging them simplifies the codebase by ~450 lines of Rust and removes 67 test fixture files.

What changed in step mode

  • DCE now runs — removes dead code just like it did in client mode, preserving step bodies and their dependencies
  • Object property steps use hoisted variable references at call sites so .stepId is accessible on the same function object
  • IIFE registration is unchanged — all step functions are registered in the global Map

Changed packages

PackageChange
@workflow/swc-pluginRemoved Client variant from TransformMode enum, ~450 lines of client-specific match arms
@workflow/nextloader.ts now always uses mode: 'step'
@workflow/buildersbase-builder.ts, apply-swc-transform.ts, swc-esbuild-plugin.ts — removed 'client' from types and mode values
@workflow/cliRemoved 'client' from transform command options
@workflow/rollupChanged mode: 'client' to mode: 'step'
@workflow/nestChanged mode: 'client' to mode: 'step'
@workflow/swc-playground-wasmRemoved client output from batch transform

@github-actions

github-actionsBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production923067990
✅ 💻 Local Development9940861080
✅ 📦 Local Production9940861080
✅ 🐘 Local Postgres9940861080
✅ 🪟 Windows900090
❌ 🌍 Community Worlds133980231
✅ 📋 Other252018270
Total4380983434821

❌ Failed Tests

🌍 Community Worlds (98 failed)

mongodb (15 failed):

  • readableStreamWorkflow | wrun_01KPC49NNZW9YY0KB64K6VSQHB
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KPC4AC42WBKTER23K36G2ZAT
  • webhookWorkflow | wrun_01KPC4AMQBQNMGQ4RMS3XNMX4K
  • outputStreamWorkflow no startIndex (reads all chunks)
  • outputStreamWorkflow positive startIndex (skips first chunk)
  • outputStreamWorkflow negative startIndex (reads from end)
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns correct index after stream completes
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns -1 before any chunks are written
  • outputStreamWorkflow - getTailIndex and getChunks getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KPC4DTF69CSG9SGAXK101SCA
  • fetchWorkflow | wrun_01KPC4E7RZPD314K6BKBYSXGT0
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KPC4JB5B6GKYQ4NA68WW9JFN
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • health check (CLI) - workflow health command reports healthy endpoints
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KPC4RK5F4H2A50VNYVKYDZYH

redis (15 failed):

  • readableStreamWorkflow | wrun_01KPC49NNZW9YY0KB64K6VSQHB
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KPC4AC42WBKTER23K36G2ZAT
  • webhookWorkflow | wrun_01KPC4AMQBQNMGQ4RMS3XNMX4K
  • outputStreamWorkflow no startIndex (reads all chunks)
  • outputStreamWorkflow positive startIndex (skips first chunk)
  • outputStreamWorkflow negative startIndex (reads from end)
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns correct index after stream completes
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns -1 before any chunks are written
  • outputStreamWorkflow - getTailIndex and getChunks getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KPC4DTF69CSG9SGAXK101SCA
  • fetchWorkflow | wrun_01KPC4E7RZPD314K6BKBYSXGT0
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KPC4JB5B6GKYQ4NA68WW9JFN
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • health check (CLI) - workflow health command reports healthy endpoints
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KPC4RK5F4H2A50VNYVKYDZYH

turso (68 failed):

  • addTenWorkflow | wrun_01KPC494JMXC2S698ZCV0Z1A6J
  • addTenWorkflow | wrun_01KPC494JMXC2S698ZCV0Z1A6J
  • wellKnownAgentWorkflow (.well-known/agent) | wrun_01KPC4AGDR3W8R8RXJT4B0AAA1
  • should work with react rendering in step
  • promiseAllWorkflow | wrun_01KPC49C06JB8S19BQWT39ZGY3
  • promiseRaceWorkflow | wrun_01KPC49GDW34C2CAXQED5GQ5HD
  • promiseAnyWorkflow | wrun_01KPC49JF67R2674SKNT0B531G
  • importedStepOnlyWorkflow | wrun_01KPC4ATXWJTKEXDX5AZ5QQ00W
  • readableStreamWorkflow | wrun_01KPC49NNZW9YY0KB64K6VSQHB
  • hookWorkflow | wrun_01KPC4A08KB58ENADF0R99QWRK
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KPC4AC42WBKTER23K36G2ZAT
  • webhookWorkflow | wrun_01KPC4AMQBQNMGQ4RMS3XNMX4K
  • sleepingWorkflow | wrun_01KPC4ATTECEVNJQ03J54ZFBVM
  • parallelSleepWorkflow | wrun_01KPC4B757NA7GCQPA911F04ZY
  • nullByteWorkflow | wrun_01KPC4BBA9SENAQ2793T64G2HD
  • workflowAndStepMetadataWorkflow | wrun_01KPC4BD6G7ZV66PGPFA4QPD88
  • outputStreamWorkflow no startIndex (reads all chunks)
  • outputStreamWorkflow positive startIndex (skips first chunk)
  • outputStreamWorkflow negative startIndex (reads from end)
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns correct index after stream completes
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns -1 before any chunks are written
  • outputStreamWorkflow - getTailIndex and getChunks getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KPC4DTF69CSG9SGAXK101SCA
  • fetchWorkflow | wrun_01KPC4E7RZPD314K6BKBYSXGT0
  • promiseRaceStressTestWorkflow | wrun_01KPC4EB2BAVKDBD6MS0ZQ6EA2
  • 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_01KPC4HQX6G61Z1EVG4JNP930D
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KPC4JB5B6GKYQ4NA68WW9JFN
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KPC4JYZ7FS1R557Y32RKYX4X
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KPC4KHC0489EJS7TH6H8C1FP
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_01KPC4KSEB6GVW9G0XXRPWE3J8
  • closureVariableWorkflow - nested step functions with closure variables | wrun_01KPC4KYK1XY4DHRRTHJ2T1M21
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_01KPC4M0KZH3ASYEG5R6JBWENC
  • runClassSerializationWorkflow - Run instances serialize across workflow/step boundaries | wrun_01KPC4MB45KDRW8N8D6WN06XEQ
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • health check (CLI) - workflow health command reports healthy endpoints
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_01KPC4MS5KHDWDK2F94N22ZFQW
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_01KPC4MZ6PEQNSM56KWF9FJX1E
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_01KPC4N5GZH4ZFPZPW62YEP6KV
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_01KPC4NBR68W7CSHPE7R7M4EK3
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_01KPC4NHS0ARKDVB77N2MX3CAC
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_01KPC4NQW6FWS4MXN0R48DA026
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_01KPC4NZ0FPXKMQX3X2CQ04PBG
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_01KPC4P9N2G26Q97QRYDQ0Y9YK
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_01KPC4PGZWQE4GQXWWGY0QH4J7
  • cancelRun - cancelling a running workflow | wrun_01KPC4PR5VZ7PAPEH1FB5DTEBH
  • cancelRun via CLI - cancelling a running workflow | wrun_01KPC4Q0WDH365KZXRFP7S3YXX
  • 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_01KPC4QC7VC0XAK4HG5DG72TYK
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KPC4QZCT792E4TFQ8YN5Q6BV
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KPC4R9ARDE36CTKSVKBD0BV7
  • importMetaUrlWorkflow - import.meta.url is available in step bundles | wrun_01KPC4RF7T0AJ9JST4ZEVXQBYY
  • metadataFromHelperWorkflow - getWorkflowMetadata/getStepMetadata work from module-level helper (#1577) | wrun_01KPC4RH3HCX2FND5E2Q3889HY
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KPC4RK5F4H2A50VNYVKYDZYH
  • getterStepWorkflow - getter functions with "use step" directive | wrun_01KPC4RP4RG6MQ9C0QJJXPXG6F

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro8307
✅ example8307
✅ express8307
✅ fastify8307
✅ hono8307
✅ nextjs-turbopack8802
✅ nextjs-webpack8802
✅ nitro8307
✅ nuxt8307
✅ sveltekit8307
✅ vite8307
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable8406
✅ express-stable8406
✅ fastify-stable8406
✅ hono-stable8406
✅ nextjs-turbopack-canary71019
✅ nextjs-turbopack-stable9000
✅ nextjs-webpack-canary71019
✅ nextjs-webpack-stable9000
✅ nitro-stable8406
✅ nuxt-stable8406
✅ sveltekit-stable8406
✅ vite-stable8406
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable8406
✅ express-stable8406
✅ fastify-stable8406
✅ hono-stable8406
✅ nextjs-turbopack-canary71019
✅ nextjs-turbopack-stable9000
✅ nextjs-webpack-canary71019
✅ nextjs-webpack-stable9000
✅ nitro-stable8406
✅ nuxt-stable8406
✅ sveltekit-stable8406
✅ vite-stable8406
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable8406
✅ express-stable8406
✅ fastify-stable8406
✅ hono-stable8406
✅ nextjs-turbopack-canary71019
✅ nextjs-turbopack-stable9000
✅ nextjs-webpack-canary71019
✅ nextjs-webpack-stable9000
✅ nitro-stable8406
✅ nuxt-stable8406
✅ sveltekit-stable8406
✅ vite-stable8406
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack9000
❌ 🌍 Community Worlds
AppPassedFailedSkipped
✅ mongodb-dev600
❌ mongodb56150
✅ redis-dev600
❌ redis56150
✅ turso-dev600
❌ turso3680
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable8406
✅ e2e-local-postgres-nest-stable8406
✅ e2e-local-prod-nest-stable8406

📋 View full workflow run

@github-actions

github-actionsBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

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

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express0.044s (-0.9%)1.005s (~)0.961s101.00x
💻 LocalNitro0.044s (+1.9%)1.005s (~)0.961s101.00x
💻 LocalNext.js (Turbopack)0.047s1.005s0.958s101.08x
🐘 PostgresNitro0.053s (-44.2% 🟢)1.011s (-3.1%)0.957s101.21x
🐘 PostgresNext.js (Turbopack)0.056s1.010s0.954s101.27x
🐘 PostgresExpress0.057s (-1.6%)1.011s (~)0.954s101.30x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro0.232s (-43.5% 🟢)2.120s (-15.5% 🟢)1.888s101.00x
▲ VercelNext.js (Turbopack)0.265s (+5.5% 🔺)2.026s (-13.2% 🟢)1.760s101.15x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Next.js (Turbopack)1.122s2.006s0.884s101.00x
🐘 PostgresNitro1.124s (-1.4%)2.009s (~)0.885s101.00x
💻 LocalNitro1.131s (~)2.006s (~)0.875s101.01x
💻 LocalExpress1.134s (+0.8%)2.007s (~)0.872s101.01x
🐘 PostgresNext.js (Turbopack)1.136s2.011s0.875s101.01x
🐘 PostgresExpress1.154s (+0.6%)2.010s (~)0.856s101.03x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro1.948s (-50.0% 🟢)3.730s (-36.9% 🟢)1.782s101.00x
▲ VercelNext.js (Turbopack)1.978s (-2.8%)3.253s (-15.1% 🟢)1.275s101.02x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro10.738s (-1.2%)11.025s (~)0.287s31.00x
💻 LocalNext.js (Turbopack)10.830s11.023s0.193s31.01x
🐘 PostgresExpress10.894s (-0.6%)11.025s (~)0.131s31.01x
💻 LocalNitro10.920s (~)11.022s (~)0.102s31.02x
🐘 PostgresNext.js (Turbopack)10.927s11.018s0.091s31.02x
💻 LocalExpress10.947s (~)11.024s (~)0.078s31.02x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro17.104s (-27.9% 🟢)19.463s (-22.5% 🟢)2.360s21.00x
▲ VercelNext.js (Turbopack)17.338s (~)18.457s (-4.9%)1.119s21.01x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro14.143s (-3.1%)15.027s (~)0.884s41.00x
🐘 PostgresNext.js (Turbopack)14.476s15.029s0.553s41.02x
💻 LocalNext.js (Turbopack)14.575s15.028s0.454s41.03x
🐘 PostgresExpress14.575s (~)15.026s (~)0.451s41.03x
💻 LocalNitro14.924s (-0.9%)15.029s (-6.2% 🟢)0.104s41.06x
💻 LocalExpress15.108s (+0.9%)16.032s (+6.7% 🔺)0.924s41.07x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro32.373s (-49.8% 🟢)34.553s (-48.1% 🟢)2.179s21.00x
▲ VercelNext.js (Turbopack)33.318s (-36.6% 🟢)34.394s (-37.0% 🟢)1.076s21.03x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro13.235s (-5.2% 🟢)13.880s (-3.0%)0.645s71.00x
🐘 PostgresExpress13.877s (-0.9%)14.022s (-3.9%)0.145s71.05x
🐘 PostgresNext.js (Turbopack)13.974s14.455s0.481s71.06x
💻 LocalNext.js (Turbopack)15.884s16.196s0.312s61.20x
💻 LocalNitro16.479s (-1.8%)17.030s (~)0.552s61.25x
💻 LocalExpress16.807s (+1.2%)17.031s (~)0.224s61.27x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro55.193s (-86.9% 🟢)57.639s (-86.4% 🟢)2.446s21.00x
▲ VercelNext.js (Turbopack)59.836s (-84.8% 🟢)60.966s (-84.6% 🟢)1.130s21.08x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.223s (-4.1%)2.009s (~)0.787s151.00x
🐘 PostgresExpress1.251s (-0.8%)2.010s (~)0.760s151.02x
🐘 PostgresNext.js (Turbopack)1.252s2.009s0.756s151.02x
💻 LocalNext.js (Turbopack)1.488s2.005s0.517s151.22x
💻 LocalNitro1.498s (-8.2% 🟢)2.006s (-3.3%)0.507s151.23x
💻 LocalExpress1.528s (+2.6%)2.006s (~)0.477s151.25x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.389s (-15.2% 🟢)3.777s (-12.6% 🟢)1.388s91.00x
▲ VercelNext.js (Turbopack)2.457s (-27.7% 🟢)3.702s (-25.0% 🟢)1.244s91.03x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro2.320s (-1.3%)3.009s (~)0.689s101.00x
🐘 PostgresExpress2.335s (-1.1%)3.008s (~)0.674s101.01x
🐘 PostgresNext.js (Turbopack)2.393s3.010s0.617s101.03x
💻 LocalNext.js (Turbopack)2.874s3.309s0.435s101.24x
💻 LocalNitro2.898s (-7.8% 🟢)3.453s (-11.1% 🟢)0.555s91.25x
💻 LocalExpress3.040s (+3.0%)3.759s (+8.8% 🔺)0.719s81.31x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.873s (-29.1% 🟢)4.645s (-21.5% 🟢)1.772s71.00x
▲ VercelNext.js (Turbopack)3.637s (-48.8% 🟢)5.185s (-41.8% 🟢)1.548s61.27x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro3.426s (-1.5%)4.010s (~)0.583s81.00x
🐘 PostgresExpress3.459s (-0.8%)4.010s (~)0.551s81.01x
🐘 PostgresNext.js (Turbopack)3.689s4.010s0.321s81.08x
💻 LocalNext.js (Turbopack)7.497s8.019s0.522s42.19x
💻 LocalNitro8.051s (-3.6%)8.772s (-2.8%)0.721s42.35x
💻 LocalExpress8.203s (-1.6%)9.020s (~)0.817s42.39x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro3.559s (+1.0%)5.051s (-8.7% 🟢)1.492s61.00x
▲ VercelNext.js (Turbopack)6.803s (-23.7% 🟢)8.029s (-26.7% 🟢)1.226s41.91x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.209s (-3.8%)2.009s (~)0.800s151.00x
🐘 PostgresNext.js (Turbopack)1.228s2.010s0.782s151.02x
🐘 PostgresExpress1.267s (+0.8%)2.008s (~)0.741s151.05x
💻 LocalNitro1.515s (-18.8% 🟢)2.005s (-14.3% 🟢)0.490s151.25x
💻 LocalNext.js (Turbopack)1.531s2.006s0.475s151.27x
💻 LocalExpress1.544s (-18.5% 🟢)2.006s (-15.1% 🟢)0.462s151.28x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.037s (-17.2% 🟢)3.718s (-10.8% 🟢)1.681s91.00x
▲ VercelNext.js (Turbopack)2.401s (-18.1% 🟢)3.792s (-18.3% 🟢)1.391s81.18x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro2.327s (-0.5%)3.010s (~)0.683s101.00x
🐘 PostgresExpress2.336s (~)3.010s (~)0.674s101.00x
🐘 PostgresNext.js (Turbopack)2.393s3.008s0.616s101.03x
💻 LocalNext.js (Turbopack)2.787s3.452s0.665s91.20x
💻 LocalNitro2.836s (-7.5% 🟢)3.309s (-14.9% 🟢)0.473s101.22x
💻 LocalExpress3.261s (+4.1%)4.011s (+6.6% 🔺)0.750s81.40x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.598s (-19.7% 🟢)4.042s (-20.4% 🟢)1.444s81.00x
▲ VercelNext.js (Turbopack)2.787s (-11.3% 🟢)4.209s (-6.9% 🟢)1.422s81.07x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro3.456s (-0.7%)4.011s (~)0.555s81.00x
🐘 PostgresExpress3.480s (-0.5%)4.010s (~)0.530s81.01x
🐘 PostgresNext.js (Turbopack)3.617s4.012s0.395s81.05x
💻 LocalNext.js (Turbopack)7.510s8.018s0.507s42.17x
💻 LocalNitro8.662s (-5.3% 🟢)9.275s (-7.5% 🟢)0.613s42.51x
💻 LocalExpress8.993s (+2.2%)9.273s (~)0.279s42.60x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.764s (-45.7% 🟢)4.520s (-33.7% 🟢)1.756s71.00x
▲ VercelNext.js (Turbopack)4.827s (-28.6% 🟢)6.399s (-25.1% 🟢)1.572s51.75x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.624s (-23.9% 🟢)1.006s (~)0.382s601.00x
🐘 PostgresNext.js (Turbopack)0.786s1.023s0.237s591.26x
🐘 PostgresExpress0.808s (-3.7%)1.022s (~)0.214s591.29x
💻 LocalNext.js (Turbopack)0.852s1.039s0.187s581.36x
💻 LocalNitro0.988s (+0.8%)1.158s (+5.9% 🔺)0.170s521.58x
💻 LocalExpress0.989s (~)1.250s (+16.1% 🔺)0.261s491.58x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro10.124s (-54.1% 🟢)12.026s (-49.9% 🟢)1.902s51.00x
▲ VercelNext.js (Turbopack)11.473s (-20.9% 🟢)12.880s (-19.9% 🟢)1.407s51.13x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.503s (-22.0% 🟢)2.007s (-4.4%)0.504s451.00x
🐘 PostgresExpress1.918s (-3.0%)2.100s (-7.0% 🟢)0.183s431.28x
🐘 PostgresNext.js (Turbopack)1.959s2.203s0.244s411.30x
💻 LocalNext.js (Turbopack)2.627s3.008s0.381s301.75x
💻 LocalNitro3.004s (-1.0%)3.508s (-6.7% 🟢)0.504s262.00x
💻 LocalExpress3.039s (+0.8%)3.690s (+2.9%)0.651s252.02x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)32.147s (-35.5% 🟢)33.634s (-35.0% 🟢)1.487s31.00x
▲ VercelNitro37.762s (-4.4%)39.759s (-3.7%)1.997s31.17x
▲ VercelExpress⚠️missing----

🔍 Observability: Next.js (Turbopack) | Nitro

workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro3.164s (-22.9% 🟢)3.824s (-16.9% 🟢)0.660s321.00x
🐘 PostgresNext.js (Turbopack)3.883s4.147s0.264s291.23x
🐘 PostgresExpress3.890s (-2.5%)4.110s (-5.9% 🟢)0.219s301.23x
💻 LocalNext.js (Turbopack)8.566s9.018s0.452s142.71x
💻 LocalExpress9.269s (+0.6%)10.019s (~)0.749s122.93x
💻 LocalNitro9.497s (+2.1%)10.101s (+0.8%)0.604s123.00x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro77.978s (-19.5% 🟢)79.827s (-18.9% 🟢)1.850s21.00x
▲ VercelNext.js (Turbopack)89.255s (-16.7% 🟢)90.555s (-16.9% 🟢)1.300s21.14x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.235s (-16.9% 🟢)1.007s (~)0.772s601.00x
🐘 PostgresNext.js (Turbopack)0.256s1.008s0.751s601.09x
🐘 PostgresExpress0.285s (+0.8%)1.007s (~)0.723s601.21x
💻 LocalNext.js (Turbopack)0.575s1.004s0.430s602.44x
💻 LocalExpress0.615s (+9.8% 🔺)1.022s (+1.7%)0.407s592.61x
💻 LocalNitro0.668s (+10.5% 🔺)1.095s (+7.2% 🔺)0.427s552.84x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro1.858s (+11.9% 🔺)3.442s (+2.7%)1.584s181.00x
▲ VercelNext.js (Turbopack)5.248s (+159.5% 🔺)6.681s (+76.1% 🔺)1.432s92.82x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.383s (-22.8% 🟢)1.006s (~)0.623s901.00x
🐘 PostgresExpress0.488s (-4.2%)1.007s (~)0.519s901.27x
🐘 PostgresNext.js (Turbopack)0.503s1.007s0.503s901.31x
💻 LocalNitro2.463s (-3.0%)3.009s (~)0.546s306.43x
💻 LocalExpress2.591s (+3.1%)3.009s (~)0.418s306.76x
💻 LocalNext.js (Turbopack)2.594s3.008s0.414s306.77x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro5.501s (+70.5% 🔺)7.445s (+54.4% 🔺)1.944s131.00x
▲ VercelNext.js (Turbopack)8.725s (+146.8% 🔺)10.373s (+99.7% 🔺)1.648s91.59x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.614s (-22.3% 🟢)1.007s (~)0.393s1201.00x
🐘 PostgresNext.js (Turbopack)0.800s1.008s0.208s1201.30x
🐘 PostgresExpress0.802s (-2.0%)1.016s (~)0.214s1191.31x
💻 LocalNext.js (Turbopack)10.669s11.392s0.723s1117.38x
💻 LocalNitro10.798s (-3.5%)11.300s (-3.1%)0.501s1117.59x
💻 LocalExpress11.456s (+2.4%)12.032s (+0.8%)0.576s1018.66x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro9.424s (+22.0% 🔺)11.667s (+24.1% 🔺)2.243s111.00x
▲ VercelNext.js (Turbopack)15.660s (+51.6% 🔺)16.985s (+38.2% 🔺)1.325s81.66x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.177s (-13.8% 🟢)0.997s (~)0.001s (-20.0% 🟢)1.011s (~)0.834s101.00x
💻 LocalNext.js (Turbopack)0.188s1.003s0.011s1.017s0.830s101.06x
🐘 PostgresNext.js (Turbopack)0.192s1.001s0.002s1.011s0.818s101.09x
💻 LocalNitro0.201s (-6.2% 🟢)1.004s (~)0.011s (-9.6% 🟢)1.017s (~)0.817s101.13x
💻 LocalExpress0.204s (+2.5%)1.004s (~)0.013s (+8.3% 🔺)1.020s (~)0.816s101.15x
🐘 PostgresExpress0.204s (~)1.001s (~)0.002s (+6.2% 🔺)1.011s (~)0.806s101.16x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)1.554s (-77.3% 🟢)2.748s (-68.2% 🟢)0.996s (+57.7% 🔺)4.134s (-57.8% 🟢)2.581s101.00x
▲ VercelNitro1.705s (-55.5% 🟢)2.818s (-46.6% 🟢)1.037s (+39.8% 🔺)4.300s (-33.7% 🟢)2.594s101.10x
▲ VercelExpress⚠️missing-----

🔍 Observability: Next.js (Turbopack) | Nitro

stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.531s (-14.9% 🟢)1.008s (~)0.004s (-14.3% 🟢)1.022s (~)0.491s591.00x
🐘 PostgresExpress0.607s (-3.6%)1.006s (~)0.004s (+3.1%)1.023s (~)0.416s591.14x
🐘 PostgresNext.js (Turbopack)0.617s1.008s0.003s1.020s0.402s591.16x
💻 LocalNitro0.742s (-11.6% 🟢)1.012s (~)0.009s (-2.5%)1.023s (-8.3% 🟢)0.281s591.40x
💻 LocalNext.js (Turbopack)0.806s1.011s0.013s1.120s0.313s541.52x
💻 LocalExpress0.956s (+26.2% 🔺)1.012s (-1.6%)0.010s (+5.4% 🔺)1.229s (+18.2% 🔺)0.273s491.80x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro4.889s (-83.4% 🟢)6.748s (-78.1% 🟢)0.465s (+315.1% 🔺)7.635s (-76.0% 🟢)2.746s81.00x
▲ VercelNext.js (Turbopack)14.674s (-13.3% 🟢)15.526s (-14.9% 🟢)0.211s (~)16.076s (-15.1% 🟢)1.403s53.00x
▲ VercelExpress⚠️missing-----

🔍 Observability: Nitro | Next.js (Turbopack)

10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.938s1.112s0.000s1.119s0.182s541.00x
🐘 PostgresNitro0.944s (-2.6%)1.177s (-5.7% 🟢)0.000s (+41.2% 🔺)1.190s (-5.4% 🟢)0.246s511.01x
🐘 PostgresExpress0.974s (+1.4%)1.219s (-4.6%)0.000s (+87.8% 🔺)1.243s (-4.9%)0.269s491.04x
💻 LocalNitro1.214s (-0.7%)2.021s (~)0.000s (+33.3% 🔺)2.022s (~)0.808s301.30x
💻 LocalExpress1.238s (+1.0%)2.020s (~)0.000s (-10.0% 🟢)2.022s (~)0.785s301.32x
💻 LocalNext.js (Turbopack)1.296s2.019s0.000s2.023s0.727s301.38x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro6.050s (+98.3% 🔺)7.665s (+74.5% 🔺)0.000s (-100.0% 🟢)8.112s (+68.7% 🔺)2.062s81.00x
▲ VercelNext.js (Turbopack)7.695s (-24.4% 🟢)7.641s (-33.7% 🟢)0.000s (NaN%)9.028s (-25.1% 🟢)1.333s71.27x
▲ VercelExpress⚠️missing-----

🔍 Observability: Nitro | Next.js (Turbopack)

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

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.720s (-4.0%)2.104s (-1.7%)0.000s (+93.1% 🔺)2.112s (-2.9%)0.392s291.00x
🐘 PostgresExpress1.727s (-2.5%)2.104s (-3.4%)0.000s (NaN%)2.113s (-3.9%)0.386s291.00x
🐘 PostgresNext.js (Turbopack)1.888s2.182s0.000s2.189s0.301s281.10x
💻 LocalNitro3.502s (+3.4%)4.035s (~)0.001s (+50.0% 🔺)4.038s (~)0.536s152.04x
💻 LocalExpress3.589s (+3.5%)4.030s (~)0.000s (-58.3% 🟢)4.033s (~)0.444s152.09x
💻 LocalNext.js (Turbopack)3.746s4.166s0.000s4.170s0.424s152.18x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)5.451s (-3.0%)6.756s (-3.2%)0.000s (-100.0% 🟢)7.096s (-5.9% 🟢)1.645s91.00x
▲ VercelNitro8.938s (+118.3% 🔺)10.290s (+91.5% 🔺)0.000s (-100.0% 🟢)10.758s (+85.7% 🔺)1.819s61.64x
▲ VercelExpress⚠️missing-----

🔍 Observability: Next.js (Turbopack) | Nitro

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalNext.js (Turbopack)15/21
🐘 PostgresNitro20/21
▲ VercelNitro18/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres18/21
Next.js (Turbopack)🐘 Postgres17/21
Nitro🐘 Postgres19/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

@changeset-bot

changeset-botBot commented Apr 10, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: dc6415b

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

This PR includes changesets to release 18 packages
NameType
@workflow/swc-pluginMajor
@workflow/buildersPatch
@workflow/cliPatch
@workflow/nextPatch
@workflow/rollupPatch
@workflow/nestPatch
@workflow/astroPatch
@workflow/nitroPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/vitestPatch
workflowPatch
@workflow/world-testingPatch
@workflow/nuxtPatch
@workflow/aiPatch
@workflow/corePatch
@workflow/web-sharedPatch
@workflow/webPatch

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

vercelBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

@TooTallNate
TooTallNateforce-pushed the nr/remove-client-mode branch from aac9033 to cf9fe73CompareApril 10, 2026 17:20
Remove the `client` transform mode from the SWC compiler plugin. The
`client` and `step` modes were nearly identical — both preserved step
function bodies, replaced workflow bodies with throw stubs, and emitted
the same JSON manifest. Step mode now absorbs all client-mode behaviors:
- Dead code elimination (previously only workflow + client)
- Hoisted variable references for object property steps
- All integrations use mode: 'step' instead of 'client'
BREAKING CHANGE: The `client` value for the SWC plugin `mode` option is
no longer accepted. Use `step` instead.
…sId registration
In dev mode, Nitro's Rollup externalizes npm packages like @workflow/core,
so the SWC transform plugin never processes files like run.js. This means
serde classes (e.g. Run) never get the classId registration IIFE, causing
serialization failures when step functions return Run instances.
Uses a Rollup resolveId hook to force workflow SDK packages to be bundled
(non-external) while leaving all other dependencies external. This is more
targeted than noExternals=true which bundles everything and causes TDZ
errors from circular imports in packages like vue-bundle-renderer/h3.
The Nitro module now also ignores .nitro/workflow/** in watchOptions so
writing generated workflow bundles does not retrigger Nitro's own dev
bundle rebuild loop.
Also wraps dev:reload workflow rebuilds and makes LocalBuilder.build()
atomic (writes to temp files, renames on success) to avoid partial output
state during HMR.
For Nuxt, also configures Vite's ssr.noExternal to bundle workflow
packages in the SSR context.

CopilotAI left a comment

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.

Pull request overview

Removes the SWC plugin’s client transform mode by merging its behavior into step mode, and updates all repository integrations, docs, and fixtures to use the new 3-mode model (Step/Workflow/Detect).

Changes:

  • Dropped Client from TransformMode, updated step mode to include client-mode behaviors (notably DCE + object-property hoisting semantics), and removed client-mode fixture runners/outputs.
  • Updated framework/tooling integrations (Next loader, Rollup, Nest CLI, Builders, CLI) to use mode: 'step' everywhere client was previously used.
  • Updated docs/spec and the SWC playground (WASM + UI/types) to remove the client output/view.

Reviewed changes

Copilot reviewed 103 out of 103 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
workbench/swc-playground/wasm/src/lib.rsRemoves client from batch transform output and runs only workflow+step.
workbench/swc-playground/lib/transform.tsUpdates TS types to drop client transform result.
workbench/swc-playground/components/swc-playground.tsxRemoves client view/panel/state in the playground UI.
packages/swc-plugin-workflow/transform/src/lib.rsRemoves Client mode and folds client behaviors into Step (DCE, hoisting/registration paths, etc.).
packages/swc-plugin-workflow/spec.mdUpdates specification to reflect 3 modes and step-mode DCE/hoisting behavior.
packages/swc-plugin-workflow/transform/tests/fixture.rsRemoves the client-mode fixture test harness.
packages/swc-plugin-workflow/transform/tests/errors.rsRemoves the client-mode errors fixture harness and updates imports.
packages/swc-plugin-workflow/transform/tests/fixture/workflow-client-property/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/workflow-arrow-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/var-named-step-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/using-declaration-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/using-declaration-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/user-named-dunder-default/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/unused-variables-and-types/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/unused-variables-and-types/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/unused-exports/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/unused-exports/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step/output-step.jsUpdates step-mode fixture to reflect new object-property hoisting behavior.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step-default-export/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step-class/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/step-with-this-arguments-super/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/step-with-imports/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/step-with-imports/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/step-arrow-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/static-method-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/static-method-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/static-getter-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/single-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/single-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/separate-export-statement/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/private-member-dce/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/private-member-dce-native/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/object-property-step/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/object-property-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/object-getter-step/output-step.jsUpdates step-mode fixture to reflect object getter/property behavior.
packages/swc-plugin-workflow/transform/tests/fixture/object-getter-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/nested-steps-in-object-constructor/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/nested-steps-in-object-constructor/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/nested-step-with-closure/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/nested-step-with-closure/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/nested-step-in-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/multiple-const-step-functions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-workflow/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-step/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/mixed-functions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/let-arrow-step-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/instance-method-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/instance-method-nested-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/instance-getter-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/expr-fn-default-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-named/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-anonymous/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-anonymous-step-only/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/destructuring/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/default-workflow-collision/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/output-workflow.jsUpdates fixture to reflect export changes under new behavior.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/output-step.jsUpdates fixture to reflect export changes under new behavior.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/input.jsUpdates input fixture to be exported (aligning outputs).
packages/swc-plugin-workflow/transform/tests/fixture/default-arrow-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/deeply-nested-step/output-step.jsUpdates step-mode fixture to reflect hoisted reference usage.
packages/swc-plugin-workflow/transform/tests/fixture/deeply-nested-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-require-namespace/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-require-destructured/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-local-const/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-imported/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/closure-typescript-expressions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/closure-new-expr-and-module-declarations/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/class-expression-binding-name/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/class-expression-binding-name-step-methods/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/anonymous-default-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step-shorthand-method/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step-shorthand-method/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/sync-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/non-async-functions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misspelled-workflow-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misspelled-step-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misplaced-module-directive/output-step.jsUpdates step-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misplaced-module-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misplaced-function-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/invalid-exports/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/invalid-default-exports-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/instance-methods/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/getter-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/next/src/loader.tsSwitches all transforms to mode: 'step'.
packages/rollup/src/index.tsSwitches Rollup integration transform mode to step.
packages/nest/src/cli.tsUpdates generated .swcrc to use mode: 'step' and help text accordingly.
packages/cli/src/commands/transform.tsRemoves client from CLI transform modes/options.
packages/builders/src/apply-swc-transform.tsUpdates API type to drop client mode.
packages/builders/src/swc-esbuild-plugin.tsUpdates SwcPluginOptions.mode type to drop client.
packages/builders/src/base-builder.tsUpdates builder SWC plugin usage from client to step.
packages/nuxt/src/module.tsForces Vite SSR bundling behavior for workflow packages and marks _vite for Nitro.
packages/nitro/src/index.tsAdds dev-only rollup force-inline plugin and dev-time dynamic loading of generated workflow bundles.
packages/nitro/src/builders.tsWrites workflow bundles to temp files first and renames into place.
.changeset/remove-client-mode.mdAdds changeset documenting the breaking removal of client mode and migration guidance.

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

Comment threadpackages/nitro/src/builders.ts Outdated
Comment threadpackages/nuxt/src/module.ts Outdated
Comment threadpackages/nitro/src/index.ts Outdated
- nitro builders: use crypto.randomUUID() for temp file suffix instead of
Date.now() to avoid collisions under rapid/concurrent build() calls,
and serialize concurrent build() calls through an internal queue so
two overlapping dev rebuilds cannot clobber each other's temp outputs.
- nitro index: use fileURLToPath() to convert file:// URLs to filesystem
paths, which correctly handles Windows paths (file:///C:/... -> C:\...)
and percent-decoding, instead of relying on new URL(...).pathname.
- nuxt module: normalize vite.ssr.noExternal to an array (preserving any
existing string/RegExp/array entry) before appending workflow package
matchers, so the force-bundle behavior is not a no-op when noExternal
is already set to a non-array value.

@VaguelySeriousVaguelySerious left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM assuming tests pass, we're only landing this on v5 right?

@TooTallNate

Copy link
Copy Markdown
MemberAuthor

@VaguelySerious correct

Sign up for freeto 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

@TooTallNate@ijjk@VaguelySerious
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

refactor(swc-plugin): remove client transform mode, merge into step mode - #1686

Merged
TooTallNate merged 3 commits into
mainfrom
nr/remove-client-mode
Apr 16, 2026
Merged

refactor(swc-plugin): remove client transform mode, merge into step mode#1686
TooTallNate merged 3 commits into
mainfrom
nr/remove-client-mode

Conversation

@TooTallNate

@TooTallNateTooTallNate commented Apr 10, 2026

Copy link
Copy Markdown
Member

Summary

  • Remove the client transform mode from the SWC compiler plugin, merging it into step mode
  • The plugin now has 3 modes (Step, Workflow, Detect) instead of 4
  • All integrations that previously used mode: 'client' now use mode: 'step'

Motivation

The client and step modes were nearly identical — both preserved step function bodies, replaced workflow bodies with throw stubs, and emitted the same JSON manifest. The only differences were:

  1. Registration mechanism: client used a simple .stepId property assignment; step used an IIFE with global Map registration
  2. Dead code elimination: client ran DCE; step did not
  3. Object property step call sites: client replaced inline functions with hoisted variable references; step kept the original inline copy

None of these differences were fundamentally necessary. Merging them simplifies the codebase by ~450 lines of Rust and removes 67 test fixture files.

What changed in step mode

  • DCE now runs — removes dead code just like it did in client mode, preserving step bodies and their dependencies
  • Object property steps use hoisted variable references at call sites so .stepId is accessible on the same function object
  • IIFE registration is unchanged — all step functions are registered in the global Map

Changed packages

PackageChange
@workflow/swc-pluginRemoved Client variant from TransformMode enum, ~450 lines of client-specific match arms
@workflow/nextloader.ts now always uses mode: 'step'
@workflow/buildersbase-builder.ts, apply-swc-transform.ts, swc-esbuild-plugin.ts — removed 'client' from types and mode values
@workflow/cliRemoved 'client' from transform command options
@workflow/rollupChanged mode: 'client' to mode: 'step'
@workflow/nestChanged mode: 'client' to mode: 'step'
@workflow/swc-playground-wasmRemoved client output from batch transform

@github-actions

github-actionsBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production923067990
✅ 💻 Local Development9940861080
✅ 📦 Local Production9940861080
✅ 🐘 Local Postgres9940861080
✅ 🪟 Windows900090
❌ 🌍 Community Worlds133980231
✅ 📋 Other252018270
Total4380983434821

❌ Failed Tests

🌍 Community Worlds (98 failed)

mongodb (15 failed):

  • readableStreamWorkflow | wrun_01KPC49NNZW9YY0KB64K6VSQHB
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KPC4AC42WBKTER23K36G2ZAT
  • webhookWorkflow | wrun_01KPC4AMQBQNMGQ4RMS3XNMX4K
  • outputStreamWorkflow no startIndex (reads all chunks)
  • outputStreamWorkflow positive startIndex (skips first chunk)
  • outputStreamWorkflow negative startIndex (reads from end)
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns correct index after stream completes
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns -1 before any chunks are written
  • outputStreamWorkflow - getTailIndex and getChunks getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KPC4DTF69CSG9SGAXK101SCA
  • fetchWorkflow | wrun_01KPC4E7RZPD314K6BKBYSXGT0
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KPC4JB5B6GKYQ4NA68WW9JFN
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • health check (CLI) - workflow health command reports healthy endpoints
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KPC4RK5F4H2A50VNYVKYDZYH

redis (15 failed):

  • readableStreamWorkflow | wrun_01KPC49NNZW9YY0KB64K6VSQHB
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KPC4AC42WBKTER23K36G2ZAT
  • webhookWorkflow | wrun_01KPC4AMQBQNMGQ4RMS3XNMX4K
  • outputStreamWorkflow no startIndex (reads all chunks)
  • outputStreamWorkflow positive startIndex (skips first chunk)
  • outputStreamWorkflow negative startIndex (reads from end)
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns correct index after stream completes
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns -1 before any chunks are written
  • outputStreamWorkflow - getTailIndex and getChunks getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KPC4DTF69CSG9SGAXK101SCA
  • fetchWorkflow | wrun_01KPC4E7RZPD314K6BKBYSXGT0
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KPC4JB5B6GKYQ4NA68WW9JFN
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • health check (CLI) - workflow health command reports healthy endpoints
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KPC4RK5F4H2A50VNYVKYDZYH

turso (68 failed):

  • addTenWorkflow | wrun_01KPC494JMXC2S698ZCV0Z1A6J
  • addTenWorkflow | wrun_01KPC494JMXC2S698ZCV0Z1A6J
  • wellKnownAgentWorkflow (.well-known/agent) | wrun_01KPC4AGDR3W8R8RXJT4B0AAA1
  • should work with react rendering in step
  • promiseAllWorkflow | wrun_01KPC49C06JB8S19BQWT39ZGY3
  • promiseRaceWorkflow | wrun_01KPC49GDW34C2CAXQED5GQ5HD
  • promiseAnyWorkflow | wrun_01KPC49JF67R2674SKNT0B531G
  • importedStepOnlyWorkflow | wrun_01KPC4ATXWJTKEXDX5AZ5QQ00W
  • readableStreamWorkflow | wrun_01KPC49NNZW9YY0KB64K6VSQHB
  • hookWorkflow | wrun_01KPC4A08KB58ENADF0R99QWRK
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KPC4AC42WBKTER23K36G2ZAT
  • webhookWorkflow | wrun_01KPC4AMQBQNMGQ4RMS3XNMX4K
  • sleepingWorkflow | wrun_01KPC4ATTECEVNJQ03J54ZFBVM
  • parallelSleepWorkflow | wrun_01KPC4B757NA7GCQPA911F04ZY
  • nullByteWorkflow | wrun_01KPC4BBA9SENAQ2793T64G2HD
  • workflowAndStepMetadataWorkflow | wrun_01KPC4BD6G7ZV66PGPFA4QPD88
  • outputStreamWorkflow no startIndex (reads all chunks)
  • outputStreamWorkflow positive startIndex (skips first chunk)
  • outputStreamWorkflow negative startIndex (reads from end)
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns correct index after stream completes
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns -1 before any chunks are written
  • outputStreamWorkflow - getTailIndex and getChunks getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KPC4DTF69CSG9SGAXK101SCA
  • fetchWorkflow | wrun_01KPC4E7RZPD314K6BKBYSXGT0
  • promiseRaceStressTestWorkflow | wrun_01KPC4EB2BAVKDBD6MS0ZQ6EA2
  • 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_01KPC4HQX6G61Z1EVG4JNP930D
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KPC4JB5B6GKYQ4NA68WW9JFN
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KPC4JYZ7FS1R557Y32RKYX4X
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KPC4KHC0489EJS7TH6H8C1FP
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_01KPC4KSEB6GVW9G0XXRPWE3J8
  • closureVariableWorkflow - nested step functions with closure variables | wrun_01KPC4KYK1XY4DHRRTHJ2T1M21
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_01KPC4M0KZH3ASYEG5R6JBWENC
  • runClassSerializationWorkflow - Run instances serialize across workflow/step boundaries | wrun_01KPC4MB45KDRW8N8D6WN06XEQ
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • health check (CLI) - workflow health command reports healthy endpoints
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_01KPC4MS5KHDWDK2F94N22ZFQW
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_01KPC4MZ6PEQNSM56KWF9FJX1E
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_01KPC4N5GZH4ZFPZPW62YEP6KV
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_01KPC4NBR68W7CSHPE7R7M4EK3
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_01KPC4NHS0ARKDVB77N2MX3CAC
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_01KPC4NQW6FWS4MXN0R48DA026
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_01KPC4NZ0FPXKMQX3X2CQ04PBG
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_01KPC4P9N2G26Q97QRYDQ0Y9YK
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_01KPC4PGZWQE4GQXWWGY0QH4J7
  • cancelRun - cancelling a running workflow | wrun_01KPC4PR5VZ7PAPEH1FB5DTEBH
  • cancelRun via CLI - cancelling a running workflow | wrun_01KPC4Q0WDH365KZXRFP7S3YXX
  • 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_01KPC4QC7VC0XAK4HG5DG72TYK
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KPC4QZCT792E4TFQ8YN5Q6BV
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KPC4R9ARDE36CTKSVKBD0BV7
  • importMetaUrlWorkflow - import.meta.url is available in step bundles | wrun_01KPC4RF7T0AJ9JST4ZEVXQBYY
  • metadataFromHelperWorkflow - getWorkflowMetadata/getStepMetadata work from module-level helper (#1577) | wrun_01KPC4RH3HCX2FND5E2Q3889HY
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KPC4RK5F4H2A50VNYVKYDZYH
  • getterStepWorkflow - getter functions with "use step" directive | wrun_01KPC4RP4RG6MQ9C0QJJXPXG6F

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro8307
✅ example8307
✅ express8307
✅ fastify8307
✅ hono8307
✅ nextjs-turbopack8802
✅ nextjs-webpack8802
✅ nitro8307
✅ nuxt8307
✅ sveltekit8307
✅ vite8307
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable8406
✅ express-stable8406
✅ fastify-stable8406
✅ hono-stable8406
✅ nextjs-turbopack-canary71019
✅ nextjs-turbopack-stable9000
✅ nextjs-webpack-canary71019
✅ nextjs-webpack-stable9000
✅ nitro-stable8406
✅ nuxt-stable8406
✅ sveltekit-stable8406
✅ vite-stable8406
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable8406
✅ express-stable8406
✅ fastify-stable8406
✅ hono-stable8406
✅ nextjs-turbopack-canary71019
✅ nextjs-turbopack-stable9000
✅ nextjs-webpack-canary71019
✅ nextjs-webpack-stable9000
✅ nitro-stable8406
✅ nuxt-stable8406
✅ sveltekit-stable8406
✅ vite-stable8406
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable8406
✅ express-stable8406
✅ fastify-stable8406
✅ hono-stable8406
✅ nextjs-turbopack-canary71019
✅ nextjs-turbopack-stable9000
✅ nextjs-webpack-canary71019
✅ nextjs-webpack-stable9000
✅ nitro-stable8406
✅ nuxt-stable8406
✅ sveltekit-stable8406
✅ vite-stable8406
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack9000
❌ 🌍 Community Worlds
AppPassedFailedSkipped
✅ mongodb-dev600
❌ mongodb56150
✅ redis-dev600
❌ redis56150
✅ turso-dev600
❌ turso3680
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable8406
✅ e2e-local-postgres-nest-stable8406
✅ e2e-local-prod-nest-stable8406

📋 View full workflow run

@github-actions

github-actionsBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

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

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express0.044s (-0.9%)1.005s (~)0.961s101.00x
💻 LocalNitro0.044s (+1.9%)1.005s (~)0.961s101.00x
💻 LocalNext.js (Turbopack)0.047s1.005s0.958s101.08x
🐘 PostgresNitro0.053s (-44.2% 🟢)1.011s (-3.1%)0.957s101.21x
🐘 PostgresNext.js (Turbopack)0.056s1.010s0.954s101.27x
🐘 PostgresExpress0.057s (-1.6%)1.011s (~)0.954s101.30x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro0.232s (-43.5% 🟢)2.120s (-15.5% 🟢)1.888s101.00x
▲ VercelNext.js (Turbopack)0.265s (+5.5% 🔺)2.026s (-13.2% 🟢)1.760s101.15x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Next.js (Turbopack)1.122s2.006s0.884s101.00x
🐘 PostgresNitro1.124s (-1.4%)2.009s (~)0.885s101.00x
💻 LocalNitro1.131s (~)2.006s (~)0.875s101.01x
💻 LocalExpress1.134s (+0.8%)2.007s (~)0.872s101.01x
🐘 PostgresNext.js (Turbopack)1.136s2.011s0.875s101.01x
🐘 PostgresExpress1.154s (+0.6%)2.010s (~)0.856s101.03x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro1.948s (-50.0% 🟢)3.730s (-36.9% 🟢)1.782s101.00x
▲ VercelNext.js (Turbopack)1.978s (-2.8%)3.253s (-15.1% 🟢)1.275s101.02x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro10.738s (-1.2%)11.025s (~)0.287s31.00x
💻 LocalNext.js (Turbopack)10.830s11.023s0.193s31.01x
🐘 PostgresExpress10.894s (-0.6%)11.025s (~)0.131s31.01x
💻 LocalNitro10.920s (~)11.022s (~)0.102s31.02x
🐘 PostgresNext.js (Turbopack)10.927s11.018s0.091s31.02x
💻 LocalExpress10.947s (~)11.024s (~)0.078s31.02x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro17.104s (-27.9% 🟢)19.463s (-22.5% 🟢)2.360s21.00x
▲ VercelNext.js (Turbopack)17.338s (~)18.457s (-4.9%)1.119s21.01x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro14.143s (-3.1%)15.027s (~)0.884s41.00x
🐘 PostgresNext.js (Turbopack)14.476s15.029s0.553s41.02x
💻 LocalNext.js (Turbopack)14.575s15.028s0.454s41.03x
🐘 PostgresExpress14.575s (~)15.026s (~)0.451s41.03x
💻 LocalNitro14.924s (-0.9%)15.029s (-6.2% 🟢)0.104s41.06x
💻 LocalExpress15.108s (+0.9%)16.032s (+6.7% 🔺)0.924s41.07x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro32.373s (-49.8% 🟢)34.553s (-48.1% 🟢)2.179s21.00x
▲ VercelNext.js (Turbopack)33.318s (-36.6% 🟢)34.394s (-37.0% 🟢)1.076s21.03x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro13.235s (-5.2% 🟢)13.880s (-3.0%)0.645s71.00x
🐘 PostgresExpress13.877s (-0.9%)14.022s (-3.9%)0.145s71.05x
🐘 PostgresNext.js (Turbopack)13.974s14.455s0.481s71.06x
💻 LocalNext.js (Turbopack)15.884s16.196s0.312s61.20x
💻 LocalNitro16.479s (-1.8%)17.030s (~)0.552s61.25x
💻 LocalExpress16.807s (+1.2%)17.031s (~)0.224s61.27x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro55.193s (-86.9% 🟢)57.639s (-86.4% 🟢)2.446s21.00x
▲ VercelNext.js (Turbopack)59.836s (-84.8% 🟢)60.966s (-84.6% 🟢)1.130s21.08x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.223s (-4.1%)2.009s (~)0.787s151.00x
🐘 PostgresExpress1.251s (-0.8%)2.010s (~)0.760s151.02x
🐘 PostgresNext.js (Turbopack)1.252s2.009s0.756s151.02x
💻 LocalNext.js (Turbopack)1.488s2.005s0.517s151.22x
💻 LocalNitro1.498s (-8.2% 🟢)2.006s (-3.3%)0.507s151.23x
💻 LocalExpress1.528s (+2.6%)2.006s (~)0.477s151.25x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.389s (-15.2% 🟢)3.777s (-12.6% 🟢)1.388s91.00x
▲ VercelNext.js (Turbopack)2.457s (-27.7% 🟢)3.702s (-25.0% 🟢)1.244s91.03x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro2.320s (-1.3%)3.009s (~)0.689s101.00x
🐘 PostgresExpress2.335s (-1.1%)3.008s (~)0.674s101.01x
🐘 PostgresNext.js (Turbopack)2.393s3.010s0.617s101.03x
💻 LocalNext.js (Turbopack)2.874s3.309s0.435s101.24x
💻 LocalNitro2.898s (-7.8% 🟢)3.453s (-11.1% 🟢)0.555s91.25x
💻 LocalExpress3.040s (+3.0%)3.759s (+8.8% 🔺)0.719s81.31x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.873s (-29.1% 🟢)4.645s (-21.5% 🟢)1.772s71.00x
▲ VercelNext.js (Turbopack)3.637s (-48.8% 🟢)5.185s (-41.8% 🟢)1.548s61.27x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro3.426s (-1.5%)4.010s (~)0.583s81.00x
🐘 PostgresExpress3.459s (-0.8%)4.010s (~)0.551s81.01x
🐘 PostgresNext.js (Turbopack)3.689s4.010s0.321s81.08x
💻 LocalNext.js (Turbopack)7.497s8.019s0.522s42.19x
💻 LocalNitro8.051s (-3.6%)8.772s (-2.8%)0.721s42.35x
💻 LocalExpress8.203s (-1.6%)9.020s (~)0.817s42.39x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro3.559s (+1.0%)5.051s (-8.7% 🟢)1.492s61.00x
▲ VercelNext.js (Turbopack)6.803s (-23.7% 🟢)8.029s (-26.7% 🟢)1.226s41.91x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.209s (-3.8%)2.009s (~)0.800s151.00x
🐘 PostgresNext.js (Turbopack)1.228s2.010s0.782s151.02x
🐘 PostgresExpress1.267s (+0.8%)2.008s (~)0.741s151.05x
💻 LocalNitro1.515s (-18.8% 🟢)2.005s (-14.3% 🟢)0.490s151.25x
💻 LocalNext.js (Turbopack)1.531s2.006s0.475s151.27x
💻 LocalExpress1.544s (-18.5% 🟢)2.006s (-15.1% 🟢)0.462s151.28x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.037s (-17.2% 🟢)3.718s (-10.8% 🟢)1.681s91.00x
▲ VercelNext.js (Turbopack)2.401s (-18.1% 🟢)3.792s (-18.3% 🟢)1.391s81.18x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro2.327s (-0.5%)3.010s (~)0.683s101.00x
🐘 PostgresExpress2.336s (~)3.010s (~)0.674s101.00x
🐘 PostgresNext.js (Turbopack)2.393s3.008s0.616s101.03x
💻 LocalNext.js (Turbopack)2.787s3.452s0.665s91.20x
💻 LocalNitro2.836s (-7.5% 🟢)3.309s (-14.9% 🟢)0.473s101.22x
💻 LocalExpress3.261s (+4.1%)4.011s (+6.6% 🔺)0.750s81.40x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.598s (-19.7% 🟢)4.042s (-20.4% 🟢)1.444s81.00x
▲ VercelNext.js (Turbopack)2.787s (-11.3% 🟢)4.209s (-6.9% 🟢)1.422s81.07x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro3.456s (-0.7%)4.011s (~)0.555s81.00x
🐘 PostgresExpress3.480s (-0.5%)4.010s (~)0.530s81.01x
🐘 PostgresNext.js (Turbopack)3.617s4.012s0.395s81.05x
💻 LocalNext.js (Turbopack)7.510s8.018s0.507s42.17x
💻 LocalNitro8.662s (-5.3% 🟢)9.275s (-7.5% 🟢)0.613s42.51x
💻 LocalExpress8.993s (+2.2%)9.273s (~)0.279s42.60x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.764s (-45.7% 🟢)4.520s (-33.7% 🟢)1.756s71.00x
▲ VercelNext.js (Turbopack)4.827s (-28.6% 🟢)6.399s (-25.1% 🟢)1.572s51.75x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.624s (-23.9% 🟢)1.006s (~)0.382s601.00x
🐘 PostgresNext.js (Turbopack)0.786s1.023s0.237s591.26x
🐘 PostgresExpress0.808s (-3.7%)1.022s (~)0.214s591.29x
💻 LocalNext.js (Turbopack)0.852s1.039s0.187s581.36x
💻 LocalNitro0.988s (+0.8%)1.158s (+5.9% 🔺)0.170s521.58x
💻 LocalExpress0.989s (~)1.250s (+16.1% 🔺)0.261s491.58x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro10.124s (-54.1% 🟢)12.026s (-49.9% 🟢)1.902s51.00x
▲ VercelNext.js (Turbopack)11.473s (-20.9% 🟢)12.880s (-19.9% 🟢)1.407s51.13x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.503s (-22.0% 🟢)2.007s (-4.4%)0.504s451.00x
🐘 PostgresExpress1.918s (-3.0%)2.100s (-7.0% 🟢)0.183s431.28x
🐘 PostgresNext.js (Turbopack)1.959s2.203s0.244s411.30x
💻 LocalNext.js (Turbopack)2.627s3.008s0.381s301.75x
💻 LocalNitro3.004s (-1.0%)3.508s (-6.7% 🟢)0.504s262.00x
💻 LocalExpress3.039s (+0.8%)3.690s (+2.9%)0.651s252.02x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)32.147s (-35.5% 🟢)33.634s (-35.0% 🟢)1.487s31.00x
▲ VercelNitro37.762s (-4.4%)39.759s (-3.7%)1.997s31.17x
▲ VercelExpress⚠️missing----

🔍 Observability: Next.js (Turbopack) | Nitro

workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro3.164s (-22.9% 🟢)3.824s (-16.9% 🟢)0.660s321.00x
🐘 PostgresNext.js (Turbopack)3.883s4.147s0.264s291.23x
🐘 PostgresExpress3.890s (-2.5%)4.110s (-5.9% 🟢)0.219s301.23x
💻 LocalNext.js (Turbopack)8.566s9.018s0.452s142.71x
💻 LocalExpress9.269s (+0.6%)10.019s (~)0.749s122.93x
💻 LocalNitro9.497s (+2.1%)10.101s (+0.8%)0.604s123.00x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro77.978s (-19.5% 🟢)79.827s (-18.9% 🟢)1.850s21.00x
▲ VercelNext.js (Turbopack)89.255s (-16.7% 🟢)90.555s (-16.9% 🟢)1.300s21.14x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.235s (-16.9% 🟢)1.007s (~)0.772s601.00x
🐘 PostgresNext.js (Turbopack)0.256s1.008s0.751s601.09x
🐘 PostgresExpress0.285s (+0.8%)1.007s (~)0.723s601.21x
💻 LocalNext.js (Turbopack)0.575s1.004s0.430s602.44x
💻 LocalExpress0.615s (+9.8% 🔺)1.022s (+1.7%)0.407s592.61x
💻 LocalNitro0.668s (+10.5% 🔺)1.095s (+7.2% 🔺)0.427s552.84x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro1.858s (+11.9% 🔺)3.442s (+2.7%)1.584s181.00x
▲ VercelNext.js (Turbopack)5.248s (+159.5% 🔺)6.681s (+76.1% 🔺)1.432s92.82x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.383s (-22.8% 🟢)1.006s (~)0.623s901.00x
🐘 PostgresExpress0.488s (-4.2%)1.007s (~)0.519s901.27x
🐘 PostgresNext.js (Turbopack)0.503s1.007s0.503s901.31x
💻 LocalNitro2.463s (-3.0%)3.009s (~)0.546s306.43x
💻 LocalExpress2.591s (+3.1%)3.009s (~)0.418s306.76x
💻 LocalNext.js (Turbopack)2.594s3.008s0.414s306.77x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro5.501s (+70.5% 🔺)7.445s (+54.4% 🔺)1.944s131.00x
▲ VercelNext.js (Turbopack)8.725s (+146.8% 🔺)10.373s (+99.7% 🔺)1.648s91.59x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.614s (-22.3% 🟢)1.007s (~)0.393s1201.00x
🐘 PostgresNext.js (Turbopack)0.800s1.008s0.208s1201.30x
🐘 PostgresExpress0.802s (-2.0%)1.016s (~)0.214s1191.31x
💻 LocalNext.js (Turbopack)10.669s11.392s0.723s1117.38x
💻 LocalNitro10.798s (-3.5%)11.300s (-3.1%)0.501s1117.59x
💻 LocalExpress11.456s (+2.4%)12.032s (+0.8%)0.576s1018.66x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro9.424s (+22.0% 🔺)11.667s (+24.1% 🔺)2.243s111.00x
▲ VercelNext.js (Turbopack)15.660s (+51.6% 🔺)16.985s (+38.2% 🔺)1.325s81.66x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.177s (-13.8% 🟢)0.997s (~)0.001s (-20.0% 🟢)1.011s (~)0.834s101.00x
💻 LocalNext.js (Turbopack)0.188s1.003s0.011s1.017s0.830s101.06x
🐘 PostgresNext.js (Turbopack)0.192s1.001s0.002s1.011s0.818s101.09x
💻 LocalNitro0.201s (-6.2% 🟢)1.004s (~)0.011s (-9.6% 🟢)1.017s (~)0.817s101.13x
💻 LocalExpress0.204s (+2.5%)1.004s (~)0.013s (+8.3% 🔺)1.020s (~)0.816s101.15x
🐘 PostgresExpress0.204s (~)1.001s (~)0.002s (+6.2% 🔺)1.011s (~)0.806s101.16x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)1.554s (-77.3% 🟢)2.748s (-68.2% 🟢)0.996s (+57.7% 🔺)4.134s (-57.8% 🟢)2.581s101.00x
▲ VercelNitro1.705s (-55.5% 🟢)2.818s (-46.6% 🟢)1.037s (+39.8% 🔺)4.300s (-33.7% 🟢)2.594s101.10x
▲ VercelExpress⚠️missing-----

🔍 Observability: Next.js (Turbopack) | Nitro

stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.531s (-14.9% 🟢)1.008s (~)0.004s (-14.3% 🟢)1.022s (~)0.491s591.00x
🐘 PostgresExpress0.607s (-3.6%)1.006s (~)0.004s (+3.1%)1.023s (~)0.416s591.14x
🐘 PostgresNext.js (Turbopack)0.617s1.008s0.003s1.020s0.402s591.16x
💻 LocalNitro0.742s (-11.6% 🟢)1.012s (~)0.009s (-2.5%)1.023s (-8.3% 🟢)0.281s591.40x
💻 LocalNext.js (Turbopack)0.806s1.011s0.013s1.120s0.313s541.52x
💻 LocalExpress0.956s (+26.2% 🔺)1.012s (-1.6%)0.010s (+5.4% 🔺)1.229s (+18.2% 🔺)0.273s491.80x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro4.889s (-83.4% 🟢)6.748s (-78.1% 🟢)0.465s (+315.1% 🔺)7.635s (-76.0% 🟢)2.746s81.00x
▲ VercelNext.js (Turbopack)14.674s (-13.3% 🟢)15.526s (-14.9% 🟢)0.211s (~)16.076s (-15.1% 🟢)1.403s53.00x
▲ VercelExpress⚠️missing-----

🔍 Observability: Nitro | Next.js (Turbopack)

10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.938s1.112s0.000s1.119s0.182s541.00x
🐘 PostgresNitro0.944s (-2.6%)1.177s (-5.7% 🟢)0.000s (+41.2% 🔺)1.190s (-5.4% 🟢)0.246s511.01x
🐘 PostgresExpress0.974s (+1.4%)1.219s (-4.6%)0.000s (+87.8% 🔺)1.243s (-4.9%)0.269s491.04x
💻 LocalNitro1.214s (-0.7%)2.021s (~)0.000s (+33.3% 🔺)2.022s (~)0.808s301.30x
💻 LocalExpress1.238s (+1.0%)2.020s (~)0.000s (-10.0% 🟢)2.022s (~)0.785s301.32x
💻 LocalNext.js (Turbopack)1.296s2.019s0.000s2.023s0.727s301.38x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro6.050s (+98.3% 🔺)7.665s (+74.5% 🔺)0.000s (-100.0% 🟢)8.112s (+68.7% 🔺)2.062s81.00x
▲ VercelNext.js (Turbopack)7.695s (-24.4% 🟢)7.641s (-33.7% 🟢)0.000s (NaN%)9.028s (-25.1% 🟢)1.333s71.27x
▲ VercelExpress⚠️missing-----

🔍 Observability: Nitro | Next.js (Turbopack)

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

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.720s (-4.0%)2.104s (-1.7%)0.000s (+93.1% 🔺)2.112s (-2.9%)0.392s291.00x
🐘 PostgresExpress1.727s (-2.5%)2.104s (-3.4%)0.000s (NaN%)2.113s (-3.9%)0.386s291.00x
🐘 PostgresNext.js (Turbopack)1.888s2.182s0.000s2.189s0.301s281.10x
💻 LocalNitro3.502s (+3.4%)4.035s (~)0.001s (+50.0% 🔺)4.038s (~)0.536s152.04x
💻 LocalExpress3.589s (+3.5%)4.030s (~)0.000s (-58.3% 🟢)4.033s (~)0.444s152.09x
💻 LocalNext.js (Turbopack)3.746s4.166s0.000s4.170s0.424s152.18x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)5.451s (-3.0%)6.756s (-3.2%)0.000s (-100.0% 🟢)7.096s (-5.9% 🟢)1.645s91.00x
▲ VercelNitro8.938s (+118.3% 🔺)10.290s (+91.5% 🔺)0.000s (-100.0% 🟢)10.758s (+85.7% 🔺)1.819s61.64x
▲ VercelExpress⚠️missing-----

🔍 Observability: Next.js (Turbopack) | Nitro

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalNext.js (Turbopack)15/21
🐘 PostgresNitro20/21
▲ VercelNitro18/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres18/21
Next.js (Turbopack)🐘 Postgres17/21
Nitro🐘 Postgres19/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

@changeset-bot

changeset-botBot commented Apr 10, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: dc6415b

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

This PR includes changesets to release 18 packages
NameType
@workflow/swc-pluginMajor
@workflow/buildersPatch
@workflow/cliPatch
@workflow/nextPatch
@workflow/rollupPatch
@workflow/nestPatch
@workflow/astroPatch
@workflow/nitroPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/vitestPatch
workflowPatch
@workflow/world-testingPatch
@workflow/nuxtPatch
@workflow/aiPatch
@workflow/corePatch
@workflow/web-sharedPatch
@workflow/webPatch

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

vercelBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

@TooTallNate
TooTallNateforce-pushed the nr/remove-client-mode branch from aac9033 to cf9fe73CompareApril 10, 2026 17:20
Remove the `client` transform mode from the SWC compiler plugin. The
`client` and `step` modes were nearly identical — both preserved step
function bodies, replaced workflow bodies with throw stubs, and emitted
the same JSON manifest. Step mode now absorbs all client-mode behaviors:
- Dead code elimination (previously only workflow + client)
- Hoisted variable references for object property steps
- All integrations use mode: 'step' instead of 'client'
BREAKING CHANGE: The `client` value for the SWC plugin `mode` option is
no longer accepted. Use `step` instead.
…sId registration
In dev mode, Nitro's Rollup externalizes npm packages like @workflow/core,
so the SWC transform plugin never processes files like run.js. This means
serde classes (e.g. Run) never get the classId registration IIFE, causing
serialization failures when step functions return Run instances.
Uses a Rollup resolveId hook to force workflow SDK packages to be bundled
(non-external) while leaving all other dependencies external. This is more
targeted than noExternals=true which bundles everything and causes TDZ
errors from circular imports in packages like vue-bundle-renderer/h3.
The Nitro module now also ignores .nitro/workflow/** in watchOptions so
writing generated workflow bundles does not retrigger Nitro's own dev
bundle rebuild loop.
Also wraps dev:reload workflow rebuilds and makes LocalBuilder.build()
atomic (writes to temp files, renames on success) to avoid partial output
state during HMR.
For Nuxt, also configures Vite's ssr.noExternal to bundle workflow
packages in the SSR context.

CopilotAI left a comment

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.

Pull request overview

Removes the SWC plugin’s client transform mode by merging its behavior into step mode, and updates all repository integrations, docs, and fixtures to use the new 3-mode model (Step/Workflow/Detect).

Changes:

  • Dropped Client from TransformMode, updated step mode to include client-mode behaviors (notably DCE + object-property hoisting semantics), and removed client-mode fixture runners/outputs.
  • Updated framework/tooling integrations (Next loader, Rollup, Nest CLI, Builders, CLI) to use mode: 'step' everywhere client was previously used.
  • Updated docs/spec and the SWC playground (WASM + UI/types) to remove the client output/view.

Reviewed changes

Copilot reviewed 103 out of 103 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
workbench/swc-playground/wasm/src/lib.rsRemoves client from batch transform output and runs only workflow+step.
workbench/swc-playground/lib/transform.tsUpdates TS types to drop client transform result.
workbench/swc-playground/components/swc-playground.tsxRemoves client view/panel/state in the playground UI.
packages/swc-plugin-workflow/transform/src/lib.rsRemoves Client mode and folds client behaviors into Step (DCE, hoisting/registration paths, etc.).
packages/swc-plugin-workflow/spec.mdUpdates specification to reflect 3 modes and step-mode DCE/hoisting behavior.
packages/swc-plugin-workflow/transform/tests/fixture.rsRemoves the client-mode fixture test harness.
packages/swc-plugin-workflow/transform/tests/errors.rsRemoves the client-mode errors fixture harness and updates imports.
packages/swc-plugin-workflow/transform/tests/fixture/workflow-client-property/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/workflow-arrow-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/var-named-step-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/using-declaration-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/using-declaration-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/user-named-dunder-default/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/unused-variables-and-types/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/unused-variables-and-types/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/unused-exports/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/unused-exports/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step/output-step.jsUpdates step-mode fixture to reflect new object-property hoisting behavior.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step-default-export/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step-class/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/step-with-this-arguments-super/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/step-with-imports/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/step-with-imports/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/step-arrow-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/static-method-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/static-method-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/static-getter-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/single-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/single-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/separate-export-statement/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/private-member-dce/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/private-member-dce-native/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/object-property-step/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/object-property-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/object-getter-step/output-step.jsUpdates step-mode fixture to reflect object getter/property behavior.
packages/swc-plugin-workflow/transform/tests/fixture/object-getter-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/nested-steps-in-object-constructor/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/nested-steps-in-object-constructor/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/nested-step-with-closure/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/nested-step-with-closure/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/nested-step-in-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/multiple-const-step-functions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-workflow/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-step/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/mixed-functions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/let-arrow-step-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/instance-method-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/instance-method-nested-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/instance-getter-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/expr-fn-default-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-named/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-anonymous/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-anonymous-step-only/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/destructuring/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/default-workflow-collision/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/output-workflow.jsUpdates fixture to reflect export changes under new behavior.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/output-step.jsUpdates fixture to reflect export changes under new behavior.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/input.jsUpdates input fixture to be exported (aligning outputs).
packages/swc-plugin-workflow/transform/tests/fixture/default-arrow-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/deeply-nested-step/output-step.jsUpdates step-mode fixture to reflect hoisted reference usage.
packages/swc-plugin-workflow/transform/tests/fixture/deeply-nested-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-require-namespace/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-require-destructured/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-local-const/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-imported/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/closure-typescript-expressions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/closure-new-expr-and-module-declarations/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/class-expression-binding-name/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/class-expression-binding-name-step-methods/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/anonymous-default-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step-shorthand-method/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step-shorthand-method/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/sync-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/non-async-functions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misspelled-workflow-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misspelled-step-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misplaced-module-directive/output-step.jsUpdates step-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misplaced-module-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misplaced-function-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/invalid-exports/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/invalid-default-exports-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/instance-methods/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/getter-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/next/src/loader.tsSwitches all transforms to mode: 'step'.
packages/rollup/src/index.tsSwitches Rollup integration transform mode to step.
packages/nest/src/cli.tsUpdates generated .swcrc to use mode: 'step' and help text accordingly.
packages/cli/src/commands/transform.tsRemoves client from CLI transform modes/options.
packages/builders/src/apply-swc-transform.tsUpdates API type to drop client mode.
packages/builders/src/swc-esbuild-plugin.tsUpdates SwcPluginOptions.mode type to drop client.
packages/builders/src/base-builder.tsUpdates builder SWC plugin usage from client to step.
packages/nuxt/src/module.tsForces Vite SSR bundling behavior for workflow packages and marks _vite for Nitro.
packages/nitro/src/index.tsAdds dev-only rollup force-inline plugin and dev-time dynamic loading of generated workflow bundles.
packages/nitro/src/builders.tsWrites workflow bundles to temp files first and renames into place.
.changeset/remove-client-mode.mdAdds changeset documenting the breaking removal of client mode and migration guidance.

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

Comment threadpackages/nitro/src/builders.ts Outdated
Comment threadpackages/nuxt/src/module.ts Outdated
Comment threadpackages/nitro/src/index.ts Outdated
- nitro builders: use crypto.randomUUID() for temp file suffix instead of
Date.now() to avoid collisions under rapid/concurrent build() calls,
and serialize concurrent build() calls through an internal queue so
two overlapping dev rebuilds cannot clobber each other's temp outputs.
- nitro index: use fileURLToPath() to convert file:// URLs to filesystem
paths, which correctly handles Windows paths (file:///C:/... -> C:\...)
and percent-decoding, instead of relying on new URL(...).pathname.
- nuxt module: normalize vite.ssr.noExternal to an array (preserving any
existing string/RegExp/array entry) before appending workflow package
matchers, so the force-bundle behavior is not a no-op when noExternal
is already set to a non-array value.

@VaguelySeriousVaguelySerious left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM assuming tests pass, we're only landing this on v5 right?

@TooTallNate

Copy link
Copy Markdown
MemberAuthor

@VaguelySerious correct

Sign up for freeto 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

@TooTallNate@ijjk@VaguelySerious
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

refactor(swc-plugin): remove client transform mode, merge into step mode - #1686

Merged
TooTallNate merged 3 commits into
mainfrom
nr/remove-client-mode
Apr 16, 2026
Merged

refactor(swc-plugin): remove client transform mode, merge into step mode#1686
TooTallNate merged 3 commits into
mainfrom
nr/remove-client-mode

Conversation

@TooTallNate

@TooTallNateTooTallNate commented Apr 10, 2026

Copy link
Copy Markdown
Member

Summary

  • Remove the client transform mode from the SWC compiler plugin, merging it into step mode
  • The plugin now has 3 modes (Step, Workflow, Detect) instead of 4
  • All integrations that previously used mode: 'client' now use mode: 'step'

Motivation

The client and step modes were nearly identical — both preserved step function bodies, replaced workflow bodies with throw stubs, and emitted the same JSON manifest. The only differences were:

  1. Registration mechanism: client used a simple .stepId property assignment; step used an IIFE with global Map registration
  2. Dead code elimination: client ran DCE; step did not
  3. Object property step call sites: client replaced inline functions with hoisted variable references; step kept the original inline copy

None of these differences were fundamentally necessary. Merging them simplifies the codebase by ~450 lines of Rust and removes 67 test fixture files.

What changed in step mode

  • DCE now runs — removes dead code just like it did in client mode, preserving step bodies and their dependencies
  • Object property steps use hoisted variable references at call sites so .stepId is accessible on the same function object
  • IIFE registration is unchanged — all step functions are registered in the global Map

Changed packages

PackageChange
@workflow/swc-pluginRemoved Client variant from TransformMode enum, ~450 lines of client-specific match arms
@workflow/nextloader.ts now always uses mode: 'step'
@workflow/buildersbase-builder.ts, apply-swc-transform.ts, swc-esbuild-plugin.ts — removed 'client' from types and mode values
@workflow/cliRemoved 'client' from transform command options
@workflow/rollupChanged mode: 'client' to mode: 'step'
@workflow/nestChanged mode: 'client' to mode: 'step'
@workflow/swc-playground-wasmRemoved client output from batch transform

@github-actions

github-actionsBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production923067990
✅ 💻 Local Development9940861080
✅ 📦 Local Production9940861080
✅ 🐘 Local Postgres9940861080
✅ 🪟 Windows900090
❌ 🌍 Community Worlds133980231
✅ 📋 Other252018270
Total4380983434821

❌ Failed Tests

🌍 Community Worlds (98 failed)

mongodb (15 failed):

  • readableStreamWorkflow | wrun_01KPC49NNZW9YY0KB64K6VSQHB
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KPC4AC42WBKTER23K36G2ZAT
  • webhookWorkflow | wrun_01KPC4AMQBQNMGQ4RMS3XNMX4K
  • outputStreamWorkflow no startIndex (reads all chunks)
  • outputStreamWorkflow positive startIndex (skips first chunk)
  • outputStreamWorkflow negative startIndex (reads from end)
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns correct index after stream completes
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns -1 before any chunks are written
  • outputStreamWorkflow - getTailIndex and getChunks getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KPC4DTF69CSG9SGAXK101SCA
  • fetchWorkflow | wrun_01KPC4E7RZPD314K6BKBYSXGT0
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KPC4JB5B6GKYQ4NA68WW9JFN
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • health check (CLI) - workflow health command reports healthy endpoints
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KPC4RK5F4H2A50VNYVKYDZYH

redis (15 failed):

  • readableStreamWorkflow | wrun_01KPC49NNZW9YY0KB64K6VSQHB
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KPC4AC42WBKTER23K36G2ZAT
  • webhookWorkflow | wrun_01KPC4AMQBQNMGQ4RMS3XNMX4K
  • outputStreamWorkflow no startIndex (reads all chunks)
  • outputStreamWorkflow positive startIndex (skips first chunk)
  • outputStreamWorkflow negative startIndex (reads from end)
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns correct index after stream completes
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns -1 before any chunks are written
  • outputStreamWorkflow - getTailIndex and getChunks getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KPC4DTF69CSG9SGAXK101SCA
  • fetchWorkflow | wrun_01KPC4E7RZPD314K6BKBYSXGT0
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KPC4JB5B6GKYQ4NA68WW9JFN
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • health check (CLI) - workflow health command reports healthy endpoints
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KPC4RK5F4H2A50VNYVKYDZYH

turso (68 failed):

  • addTenWorkflow | wrun_01KPC494JMXC2S698ZCV0Z1A6J
  • addTenWorkflow | wrun_01KPC494JMXC2S698ZCV0Z1A6J
  • wellKnownAgentWorkflow (.well-known/agent) | wrun_01KPC4AGDR3W8R8RXJT4B0AAA1
  • should work with react rendering in step
  • promiseAllWorkflow | wrun_01KPC49C06JB8S19BQWT39ZGY3
  • promiseRaceWorkflow | wrun_01KPC49GDW34C2CAXQED5GQ5HD
  • promiseAnyWorkflow | wrun_01KPC49JF67R2674SKNT0B531G
  • importedStepOnlyWorkflow | wrun_01KPC4ATXWJTKEXDX5AZ5QQ00W
  • readableStreamWorkflow | wrun_01KPC49NNZW9YY0KB64K6VSQHB
  • hookWorkflow | wrun_01KPC4A08KB58ENADF0R99QWRK
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KPC4AC42WBKTER23K36G2ZAT
  • webhookWorkflow | wrun_01KPC4AMQBQNMGQ4RMS3XNMX4K
  • sleepingWorkflow | wrun_01KPC4ATTECEVNJQ03J54ZFBVM
  • parallelSleepWorkflow | wrun_01KPC4B757NA7GCQPA911F04ZY
  • nullByteWorkflow | wrun_01KPC4BBA9SENAQ2793T64G2HD
  • workflowAndStepMetadataWorkflow | wrun_01KPC4BD6G7ZV66PGPFA4QPD88
  • outputStreamWorkflow no startIndex (reads all chunks)
  • outputStreamWorkflow positive startIndex (skips first chunk)
  • outputStreamWorkflow negative startIndex (reads from end)
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns correct index after stream completes
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns -1 before any chunks are written
  • outputStreamWorkflow - getTailIndex and getChunks getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KPC4DTF69CSG9SGAXK101SCA
  • fetchWorkflow | wrun_01KPC4E7RZPD314K6BKBYSXGT0
  • promiseRaceStressTestWorkflow | wrun_01KPC4EB2BAVKDBD6MS0ZQ6EA2
  • 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_01KPC4HQX6G61Z1EVG4JNP930D
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KPC4JB5B6GKYQ4NA68WW9JFN
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KPC4JYZ7FS1R557Y32RKYX4X
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KPC4KHC0489EJS7TH6H8C1FP
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_01KPC4KSEB6GVW9G0XXRPWE3J8
  • closureVariableWorkflow - nested step functions with closure variables | wrun_01KPC4KYK1XY4DHRRTHJ2T1M21
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_01KPC4M0KZH3ASYEG5R6JBWENC
  • runClassSerializationWorkflow - Run instances serialize across workflow/step boundaries | wrun_01KPC4MB45KDRW8N8D6WN06XEQ
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • health check (CLI) - workflow health command reports healthy endpoints
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_01KPC4MS5KHDWDK2F94N22ZFQW
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_01KPC4MZ6PEQNSM56KWF9FJX1E
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_01KPC4N5GZH4ZFPZPW62YEP6KV
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_01KPC4NBR68W7CSHPE7R7M4EK3
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_01KPC4NHS0ARKDVB77N2MX3CAC
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_01KPC4NQW6FWS4MXN0R48DA026
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_01KPC4NZ0FPXKMQX3X2CQ04PBG
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_01KPC4P9N2G26Q97QRYDQ0Y9YK
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_01KPC4PGZWQE4GQXWWGY0QH4J7
  • cancelRun - cancelling a running workflow | wrun_01KPC4PR5VZ7PAPEH1FB5DTEBH
  • cancelRun via CLI - cancelling a running workflow | wrun_01KPC4Q0WDH365KZXRFP7S3YXX
  • 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_01KPC4QC7VC0XAK4HG5DG72TYK
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KPC4QZCT792E4TFQ8YN5Q6BV
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KPC4R9ARDE36CTKSVKBD0BV7
  • importMetaUrlWorkflow - import.meta.url is available in step bundles | wrun_01KPC4RF7T0AJ9JST4ZEVXQBYY
  • metadataFromHelperWorkflow - getWorkflowMetadata/getStepMetadata work from module-level helper (#1577) | wrun_01KPC4RH3HCX2FND5E2Q3889HY
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KPC4RK5F4H2A50VNYVKYDZYH
  • getterStepWorkflow - getter functions with "use step" directive | wrun_01KPC4RP4RG6MQ9C0QJJXPXG6F

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro8307
✅ example8307
✅ express8307
✅ fastify8307
✅ hono8307
✅ nextjs-turbopack8802
✅ nextjs-webpack8802
✅ nitro8307
✅ nuxt8307
✅ sveltekit8307
✅ vite8307
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable8406
✅ express-stable8406
✅ fastify-stable8406
✅ hono-stable8406
✅ nextjs-turbopack-canary71019
✅ nextjs-turbopack-stable9000
✅ nextjs-webpack-canary71019
✅ nextjs-webpack-stable9000
✅ nitro-stable8406
✅ nuxt-stable8406
✅ sveltekit-stable8406
✅ vite-stable8406
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable8406
✅ express-stable8406
✅ fastify-stable8406
✅ hono-stable8406
✅ nextjs-turbopack-canary71019
✅ nextjs-turbopack-stable9000
✅ nextjs-webpack-canary71019
✅ nextjs-webpack-stable9000
✅ nitro-stable8406
✅ nuxt-stable8406
✅ sveltekit-stable8406
✅ vite-stable8406
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable8406
✅ express-stable8406
✅ fastify-stable8406
✅ hono-stable8406
✅ nextjs-turbopack-canary71019
✅ nextjs-turbopack-stable9000
✅ nextjs-webpack-canary71019
✅ nextjs-webpack-stable9000
✅ nitro-stable8406
✅ nuxt-stable8406
✅ sveltekit-stable8406
✅ vite-stable8406
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack9000
❌ 🌍 Community Worlds
AppPassedFailedSkipped
✅ mongodb-dev600
❌ mongodb56150
✅ redis-dev600
❌ redis56150
✅ turso-dev600
❌ turso3680
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable8406
✅ e2e-local-postgres-nest-stable8406
✅ e2e-local-prod-nest-stable8406

📋 View full workflow run

@github-actions

github-actionsBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

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

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express0.044s (-0.9%)1.005s (~)0.961s101.00x
💻 LocalNitro0.044s (+1.9%)1.005s (~)0.961s101.00x
💻 LocalNext.js (Turbopack)0.047s1.005s0.958s101.08x
🐘 PostgresNitro0.053s (-44.2% 🟢)1.011s (-3.1%)0.957s101.21x
🐘 PostgresNext.js (Turbopack)0.056s1.010s0.954s101.27x
🐘 PostgresExpress0.057s (-1.6%)1.011s (~)0.954s101.30x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro0.232s (-43.5% 🟢)2.120s (-15.5% 🟢)1.888s101.00x
▲ VercelNext.js (Turbopack)0.265s (+5.5% 🔺)2.026s (-13.2% 🟢)1.760s101.15x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Next.js (Turbopack)1.122s2.006s0.884s101.00x
🐘 PostgresNitro1.124s (-1.4%)2.009s (~)0.885s101.00x
💻 LocalNitro1.131s (~)2.006s (~)0.875s101.01x
💻 LocalExpress1.134s (+0.8%)2.007s (~)0.872s101.01x
🐘 PostgresNext.js (Turbopack)1.136s2.011s0.875s101.01x
🐘 PostgresExpress1.154s (+0.6%)2.010s (~)0.856s101.03x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro1.948s (-50.0% 🟢)3.730s (-36.9% 🟢)1.782s101.00x
▲ VercelNext.js (Turbopack)1.978s (-2.8%)3.253s (-15.1% 🟢)1.275s101.02x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro10.738s (-1.2%)11.025s (~)0.287s31.00x
💻 LocalNext.js (Turbopack)10.830s11.023s0.193s31.01x
🐘 PostgresExpress10.894s (-0.6%)11.025s (~)0.131s31.01x
💻 LocalNitro10.920s (~)11.022s (~)0.102s31.02x
🐘 PostgresNext.js (Turbopack)10.927s11.018s0.091s31.02x
💻 LocalExpress10.947s (~)11.024s (~)0.078s31.02x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro17.104s (-27.9% 🟢)19.463s (-22.5% 🟢)2.360s21.00x
▲ VercelNext.js (Turbopack)17.338s (~)18.457s (-4.9%)1.119s21.01x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro14.143s (-3.1%)15.027s (~)0.884s41.00x
🐘 PostgresNext.js (Turbopack)14.476s15.029s0.553s41.02x
💻 LocalNext.js (Turbopack)14.575s15.028s0.454s41.03x
🐘 PostgresExpress14.575s (~)15.026s (~)0.451s41.03x
💻 LocalNitro14.924s (-0.9%)15.029s (-6.2% 🟢)0.104s41.06x
💻 LocalExpress15.108s (+0.9%)16.032s (+6.7% 🔺)0.924s41.07x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro32.373s (-49.8% 🟢)34.553s (-48.1% 🟢)2.179s21.00x
▲ VercelNext.js (Turbopack)33.318s (-36.6% 🟢)34.394s (-37.0% 🟢)1.076s21.03x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro13.235s (-5.2% 🟢)13.880s (-3.0%)0.645s71.00x
🐘 PostgresExpress13.877s (-0.9%)14.022s (-3.9%)0.145s71.05x
🐘 PostgresNext.js (Turbopack)13.974s14.455s0.481s71.06x
💻 LocalNext.js (Turbopack)15.884s16.196s0.312s61.20x
💻 LocalNitro16.479s (-1.8%)17.030s (~)0.552s61.25x
💻 LocalExpress16.807s (+1.2%)17.031s (~)0.224s61.27x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro55.193s (-86.9% 🟢)57.639s (-86.4% 🟢)2.446s21.00x
▲ VercelNext.js (Turbopack)59.836s (-84.8% 🟢)60.966s (-84.6% 🟢)1.130s21.08x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.223s (-4.1%)2.009s (~)0.787s151.00x
🐘 PostgresExpress1.251s (-0.8%)2.010s (~)0.760s151.02x
🐘 PostgresNext.js (Turbopack)1.252s2.009s0.756s151.02x
💻 LocalNext.js (Turbopack)1.488s2.005s0.517s151.22x
💻 LocalNitro1.498s (-8.2% 🟢)2.006s (-3.3%)0.507s151.23x
💻 LocalExpress1.528s (+2.6%)2.006s (~)0.477s151.25x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.389s (-15.2% 🟢)3.777s (-12.6% 🟢)1.388s91.00x
▲ VercelNext.js (Turbopack)2.457s (-27.7% 🟢)3.702s (-25.0% 🟢)1.244s91.03x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro2.320s (-1.3%)3.009s (~)0.689s101.00x
🐘 PostgresExpress2.335s (-1.1%)3.008s (~)0.674s101.01x
🐘 PostgresNext.js (Turbopack)2.393s3.010s0.617s101.03x
💻 LocalNext.js (Turbopack)2.874s3.309s0.435s101.24x
💻 LocalNitro2.898s (-7.8% 🟢)3.453s (-11.1% 🟢)0.555s91.25x
💻 LocalExpress3.040s (+3.0%)3.759s (+8.8% 🔺)0.719s81.31x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.873s (-29.1% 🟢)4.645s (-21.5% 🟢)1.772s71.00x
▲ VercelNext.js (Turbopack)3.637s (-48.8% 🟢)5.185s (-41.8% 🟢)1.548s61.27x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro3.426s (-1.5%)4.010s (~)0.583s81.00x
🐘 PostgresExpress3.459s (-0.8%)4.010s (~)0.551s81.01x
🐘 PostgresNext.js (Turbopack)3.689s4.010s0.321s81.08x
💻 LocalNext.js (Turbopack)7.497s8.019s0.522s42.19x
💻 LocalNitro8.051s (-3.6%)8.772s (-2.8%)0.721s42.35x
💻 LocalExpress8.203s (-1.6%)9.020s (~)0.817s42.39x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro3.559s (+1.0%)5.051s (-8.7% 🟢)1.492s61.00x
▲ VercelNext.js (Turbopack)6.803s (-23.7% 🟢)8.029s (-26.7% 🟢)1.226s41.91x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.209s (-3.8%)2.009s (~)0.800s151.00x
🐘 PostgresNext.js (Turbopack)1.228s2.010s0.782s151.02x
🐘 PostgresExpress1.267s (+0.8%)2.008s (~)0.741s151.05x
💻 LocalNitro1.515s (-18.8% 🟢)2.005s (-14.3% 🟢)0.490s151.25x
💻 LocalNext.js (Turbopack)1.531s2.006s0.475s151.27x
💻 LocalExpress1.544s (-18.5% 🟢)2.006s (-15.1% 🟢)0.462s151.28x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.037s (-17.2% 🟢)3.718s (-10.8% 🟢)1.681s91.00x
▲ VercelNext.js (Turbopack)2.401s (-18.1% 🟢)3.792s (-18.3% 🟢)1.391s81.18x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro2.327s (-0.5%)3.010s (~)0.683s101.00x
🐘 PostgresExpress2.336s (~)3.010s (~)0.674s101.00x
🐘 PostgresNext.js (Turbopack)2.393s3.008s0.616s101.03x
💻 LocalNext.js (Turbopack)2.787s3.452s0.665s91.20x
💻 LocalNitro2.836s (-7.5% 🟢)3.309s (-14.9% 🟢)0.473s101.22x
💻 LocalExpress3.261s (+4.1%)4.011s (+6.6% 🔺)0.750s81.40x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.598s (-19.7% 🟢)4.042s (-20.4% 🟢)1.444s81.00x
▲ VercelNext.js (Turbopack)2.787s (-11.3% 🟢)4.209s (-6.9% 🟢)1.422s81.07x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro3.456s (-0.7%)4.011s (~)0.555s81.00x
🐘 PostgresExpress3.480s (-0.5%)4.010s (~)0.530s81.01x
🐘 PostgresNext.js (Turbopack)3.617s4.012s0.395s81.05x
💻 LocalNext.js (Turbopack)7.510s8.018s0.507s42.17x
💻 LocalNitro8.662s (-5.3% 🟢)9.275s (-7.5% 🟢)0.613s42.51x
💻 LocalExpress8.993s (+2.2%)9.273s (~)0.279s42.60x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.764s (-45.7% 🟢)4.520s (-33.7% 🟢)1.756s71.00x
▲ VercelNext.js (Turbopack)4.827s (-28.6% 🟢)6.399s (-25.1% 🟢)1.572s51.75x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.624s (-23.9% 🟢)1.006s (~)0.382s601.00x
🐘 PostgresNext.js (Turbopack)0.786s1.023s0.237s591.26x
🐘 PostgresExpress0.808s (-3.7%)1.022s (~)0.214s591.29x
💻 LocalNext.js (Turbopack)0.852s1.039s0.187s581.36x
💻 LocalNitro0.988s (+0.8%)1.158s (+5.9% 🔺)0.170s521.58x
💻 LocalExpress0.989s (~)1.250s (+16.1% 🔺)0.261s491.58x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro10.124s (-54.1% 🟢)12.026s (-49.9% 🟢)1.902s51.00x
▲ VercelNext.js (Turbopack)11.473s (-20.9% 🟢)12.880s (-19.9% 🟢)1.407s51.13x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.503s (-22.0% 🟢)2.007s (-4.4%)0.504s451.00x
🐘 PostgresExpress1.918s (-3.0%)2.100s (-7.0% 🟢)0.183s431.28x
🐘 PostgresNext.js (Turbopack)1.959s2.203s0.244s411.30x
💻 LocalNext.js (Turbopack)2.627s3.008s0.381s301.75x
💻 LocalNitro3.004s (-1.0%)3.508s (-6.7% 🟢)0.504s262.00x
💻 LocalExpress3.039s (+0.8%)3.690s (+2.9%)0.651s252.02x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)32.147s (-35.5% 🟢)33.634s (-35.0% 🟢)1.487s31.00x
▲ VercelNitro37.762s (-4.4%)39.759s (-3.7%)1.997s31.17x
▲ VercelExpress⚠️missing----

🔍 Observability: Next.js (Turbopack) | Nitro

workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro3.164s (-22.9% 🟢)3.824s (-16.9% 🟢)0.660s321.00x
🐘 PostgresNext.js (Turbopack)3.883s4.147s0.264s291.23x
🐘 PostgresExpress3.890s (-2.5%)4.110s (-5.9% 🟢)0.219s301.23x
💻 LocalNext.js (Turbopack)8.566s9.018s0.452s142.71x
💻 LocalExpress9.269s (+0.6%)10.019s (~)0.749s122.93x
💻 LocalNitro9.497s (+2.1%)10.101s (+0.8%)0.604s123.00x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro77.978s (-19.5% 🟢)79.827s (-18.9% 🟢)1.850s21.00x
▲ VercelNext.js (Turbopack)89.255s (-16.7% 🟢)90.555s (-16.9% 🟢)1.300s21.14x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.235s (-16.9% 🟢)1.007s (~)0.772s601.00x
🐘 PostgresNext.js (Turbopack)0.256s1.008s0.751s601.09x
🐘 PostgresExpress0.285s (+0.8%)1.007s (~)0.723s601.21x
💻 LocalNext.js (Turbopack)0.575s1.004s0.430s602.44x
💻 LocalExpress0.615s (+9.8% 🔺)1.022s (+1.7%)0.407s592.61x
💻 LocalNitro0.668s (+10.5% 🔺)1.095s (+7.2% 🔺)0.427s552.84x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro1.858s (+11.9% 🔺)3.442s (+2.7%)1.584s181.00x
▲ VercelNext.js (Turbopack)5.248s (+159.5% 🔺)6.681s (+76.1% 🔺)1.432s92.82x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.383s (-22.8% 🟢)1.006s (~)0.623s901.00x
🐘 PostgresExpress0.488s (-4.2%)1.007s (~)0.519s901.27x
🐘 PostgresNext.js (Turbopack)0.503s1.007s0.503s901.31x
💻 LocalNitro2.463s (-3.0%)3.009s (~)0.546s306.43x
💻 LocalExpress2.591s (+3.1%)3.009s (~)0.418s306.76x
💻 LocalNext.js (Turbopack)2.594s3.008s0.414s306.77x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro5.501s (+70.5% 🔺)7.445s (+54.4% 🔺)1.944s131.00x
▲ VercelNext.js (Turbopack)8.725s (+146.8% 🔺)10.373s (+99.7% 🔺)1.648s91.59x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.614s (-22.3% 🟢)1.007s (~)0.393s1201.00x
🐘 PostgresNext.js (Turbopack)0.800s1.008s0.208s1201.30x
🐘 PostgresExpress0.802s (-2.0%)1.016s (~)0.214s1191.31x
💻 LocalNext.js (Turbopack)10.669s11.392s0.723s1117.38x
💻 LocalNitro10.798s (-3.5%)11.300s (-3.1%)0.501s1117.59x
💻 LocalExpress11.456s (+2.4%)12.032s (+0.8%)0.576s1018.66x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro9.424s (+22.0% 🔺)11.667s (+24.1% 🔺)2.243s111.00x
▲ VercelNext.js (Turbopack)15.660s (+51.6% 🔺)16.985s (+38.2% 🔺)1.325s81.66x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.177s (-13.8% 🟢)0.997s (~)0.001s (-20.0% 🟢)1.011s (~)0.834s101.00x
💻 LocalNext.js (Turbopack)0.188s1.003s0.011s1.017s0.830s101.06x
🐘 PostgresNext.js (Turbopack)0.192s1.001s0.002s1.011s0.818s101.09x
💻 LocalNitro0.201s (-6.2% 🟢)1.004s (~)0.011s (-9.6% 🟢)1.017s (~)0.817s101.13x
💻 LocalExpress0.204s (+2.5%)1.004s (~)0.013s (+8.3% 🔺)1.020s (~)0.816s101.15x
🐘 PostgresExpress0.204s (~)1.001s (~)0.002s (+6.2% 🔺)1.011s (~)0.806s101.16x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)1.554s (-77.3% 🟢)2.748s (-68.2% 🟢)0.996s (+57.7% 🔺)4.134s (-57.8% 🟢)2.581s101.00x
▲ VercelNitro1.705s (-55.5% 🟢)2.818s (-46.6% 🟢)1.037s (+39.8% 🔺)4.300s (-33.7% 🟢)2.594s101.10x
▲ VercelExpress⚠️missing-----

🔍 Observability: Next.js (Turbopack) | Nitro

stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.531s (-14.9% 🟢)1.008s (~)0.004s (-14.3% 🟢)1.022s (~)0.491s591.00x
🐘 PostgresExpress0.607s (-3.6%)1.006s (~)0.004s (+3.1%)1.023s (~)0.416s591.14x
🐘 PostgresNext.js (Turbopack)0.617s1.008s0.003s1.020s0.402s591.16x
💻 LocalNitro0.742s (-11.6% 🟢)1.012s (~)0.009s (-2.5%)1.023s (-8.3% 🟢)0.281s591.40x
💻 LocalNext.js (Turbopack)0.806s1.011s0.013s1.120s0.313s541.52x
💻 LocalExpress0.956s (+26.2% 🔺)1.012s (-1.6%)0.010s (+5.4% 🔺)1.229s (+18.2% 🔺)0.273s491.80x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro4.889s (-83.4% 🟢)6.748s (-78.1% 🟢)0.465s (+315.1% 🔺)7.635s (-76.0% 🟢)2.746s81.00x
▲ VercelNext.js (Turbopack)14.674s (-13.3% 🟢)15.526s (-14.9% 🟢)0.211s (~)16.076s (-15.1% 🟢)1.403s53.00x
▲ VercelExpress⚠️missing-----

🔍 Observability: Nitro | Next.js (Turbopack)

10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.938s1.112s0.000s1.119s0.182s541.00x
🐘 PostgresNitro0.944s (-2.6%)1.177s (-5.7% 🟢)0.000s (+41.2% 🔺)1.190s (-5.4% 🟢)0.246s511.01x
🐘 PostgresExpress0.974s (+1.4%)1.219s (-4.6%)0.000s (+87.8% 🔺)1.243s (-4.9%)0.269s491.04x
💻 LocalNitro1.214s (-0.7%)2.021s (~)0.000s (+33.3% 🔺)2.022s (~)0.808s301.30x
💻 LocalExpress1.238s (+1.0%)2.020s (~)0.000s (-10.0% 🟢)2.022s (~)0.785s301.32x
💻 LocalNext.js (Turbopack)1.296s2.019s0.000s2.023s0.727s301.38x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro6.050s (+98.3% 🔺)7.665s (+74.5% 🔺)0.000s (-100.0% 🟢)8.112s (+68.7% 🔺)2.062s81.00x
▲ VercelNext.js (Turbopack)7.695s (-24.4% 🟢)7.641s (-33.7% 🟢)0.000s (NaN%)9.028s (-25.1% 🟢)1.333s71.27x
▲ VercelExpress⚠️missing-----

🔍 Observability: Nitro | Next.js (Turbopack)

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

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.720s (-4.0%)2.104s (-1.7%)0.000s (+93.1% 🔺)2.112s (-2.9%)0.392s291.00x
🐘 PostgresExpress1.727s (-2.5%)2.104s (-3.4%)0.000s (NaN%)2.113s (-3.9%)0.386s291.00x
🐘 PostgresNext.js (Turbopack)1.888s2.182s0.000s2.189s0.301s281.10x
💻 LocalNitro3.502s (+3.4%)4.035s (~)0.001s (+50.0% 🔺)4.038s (~)0.536s152.04x
💻 LocalExpress3.589s (+3.5%)4.030s (~)0.000s (-58.3% 🟢)4.033s (~)0.444s152.09x
💻 LocalNext.js (Turbopack)3.746s4.166s0.000s4.170s0.424s152.18x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)5.451s (-3.0%)6.756s (-3.2%)0.000s (-100.0% 🟢)7.096s (-5.9% 🟢)1.645s91.00x
▲ VercelNitro8.938s (+118.3% 🔺)10.290s (+91.5% 🔺)0.000s (-100.0% 🟢)10.758s (+85.7% 🔺)1.819s61.64x
▲ VercelExpress⚠️missing-----

🔍 Observability: Next.js (Turbopack) | Nitro

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalNext.js (Turbopack)15/21
🐘 PostgresNitro20/21
▲ VercelNitro18/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres18/21
Next.js (Turbopack)🐘 Postgres17/21
Nitro🐘 Postgres19/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

@changeset-bot

changeset-botBot commented Apr 10, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: dc6415b

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

This PR includes changesets to release 18 packages
NameType
@workflow/swc-pluginMajor
@workflow/buildersPatch
@workflow/cliPatch
@workflow/nextPatch
@workflow/rollupPatch
@workflow/nestPatch
@workflow/astroPatch
@workflow/nitroPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/vitestPatch
workflowPatch
@workflow/world-testingPatch
@workflow/nuxtPatch
@workflow/aiPatch
@workflow/corePatch
@workflow/web-sharedPatch
@workflow/webPatch

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

vercelBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

@TooTallNate
TooTallNateforce-pushed the nr/remove-client-mode branch from aac9033 to cf9fe73CompareApril 10, 2026 17:20
Remove the `client` transform mode from the SWC compiler plugin. The
`client` and `step` modes were nearly identical — both preserved step
function bodies, replaced workflow bodies with throw stubs, and emitted
the same JSON manifest. Step mode now absorbs all client-mode behaviors:
- Dead code elimination (previously only workflow + client)
- Hoisted variable references for object property steps
- All integrations use mode: 'step' instead of 'client'
BREAKING CHANGE: The `client` value for the SWC plugin `mode` option is
no longer accepted. Use `step` instead.
…sId registration
In dev mode, Nitro's Rollup externalizes npm packages like @workflow/core,
so the SWC transform plugin never processes files like run.js. This means
serde classes (e.g. Run) never get the classId registration IIFE, causing
serialization failures when step functions return Run instances.
Uses a Rollup resolveId hook to force workflow SDK packages to be bundled
(non-external) while leaving all other dependencies external. This is more
targeted than noExternals=true which bundles everything and causes TDZ
errors from circular imports in packages like vue-bundle-renderer/h3.
The Nitro module now also ignores .nitro/workflow/** in watchOptions so
writing generated workflow bundles does not retrigger Nitro's own dev
bundle rebuild loop.
Also wraps dev:reload workflow rebuilds and makes LocalBuilder.build()
atomic (writes to temp files, renames on success) to avoid partial output
state during HMR.
For Nuxt, also configures Vite's ssr.noExternal to bundle workflow
packages in the SSR context.

CopilotAI left a comment

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.

Pull request overview

Removes the SWC plugin’s client transform mode by merging its behavior into step mode, and updates all repository integrations, docs, and fixtures to use the new 3-mode model (Step/Workflow/Detect).

Changes:

  • Dropped Client from TransformMode, updated step mode to include client-mode behaviors (notably DCE + object-property hoisting semantics), and removed client-mode fixture runners/outputs.
  • Updated framework/tooling integrations (Next loader, Rollup, Nest CLI, Builders, CLI) to use mode: 'step' everywhere client was previously used.
  • Updated docs/spec and the SWC playground (WASM + UI/types) to remove the client output/view.

Reviewed changes

Copilot reviewed 103 out of 103 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
workbench/swc-playground/wasm/src/lib.rsRemoves client from batch transform output and runs only workflow+step.
workbench/swc-playground/lib/transform.tsUpdates TS types to drop client transform result.
workbench/swc-playground/components/swc-playground.tsxRemoves client view/panel/state in the playground UI.
packages/swc-plugin-workflow/transform/src/lib.rsRemoves Client mode and folds client behaviors into Step (DCE, hoisting/registration paths, etc.).
packages/swc-plugin-workflow/spec.mdUpdates specification to reflect 3 modes and step-mode DCE/hoisting behavior.
packages/swc-plugin-workflow/transform/tests/fixture.rsRemoves the client-mode fixture test harness.
packages/swc-plugin-workflow/transform/tests/errors.rsRemoves the client-mode errors fixture harness and updates imports.
packages/swc-plugin-workflow/transform/tests/fixture/workflow-client-property/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/workflow-arrow-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/var-named-step-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/using-declaration-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/using-declaration-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/user-named-dunder-default/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/unused-variables-and-types/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/unused-variables-and-types/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/unused-exports/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/unused-exports/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step/output-step.jsUpdates step-mode fixture to reflect new object-property hoisting behavior.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step-default-export/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step-class/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/step-with-this-arguments-super/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/step-with-imports/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/step-with-imports/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/step-arrow-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/static-method-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/static-method-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/static-getter-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/single-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/single-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/separate-export-statement/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/private-member-dce/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/private-member-dce-native/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/object-property-step/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/object-property-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/object-getter-step/output-step.jsUpdates step-mode fixture to reflect object getter/property behavior.
packages/swc-plugin-workflow/transform/tests/fixture/object-getter-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/nested-steps-in-object-constructor/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/nested-steps-in-object-constructor/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/nested-step-with-closure/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/nested-step-with-closure/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/nested-step-in-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/multiple-const-step-functions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-workflow/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-step/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/mixed-functions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/let-arrow-step-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/instance-method-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/instance-method-nested-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/instance-getter-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/expr-fn-default-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-named/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-anonymous/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-anonymous-step-only/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/destructuring/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/default-workflow-collision/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/output-workflow.jsUpdates fixture to reflect export changes under new behavior.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/output-step.jsUpdates fixture to reflect export changes under new behavior.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/input.jsUpdates input fixture to be exported (aligning outputs).
packages/swc-plugin-workflow/transform/tests/fixture/default-arrow-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/deeply-nested-step/output-step.jsUpdates step-mode fixture to reflect hoisted reference usage.
packages/swc-plugin-workflow/transform/tests/fixture/deeply-nested-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-require-namespace/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-require-destructured/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-local-const/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-imported/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/closure-typescript-expressions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/closure-new-expr-and-module-declarations/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/class-expression-binding-name/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/class-expression-binding-name-step-methods/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/anonymous-default-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step-shorthand-method/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step-shorthand-method/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/sync-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/non-async-functions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misspelled-workflow-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misspelled-step-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misplaced-module-directive/output-step.jsUpdates step-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misplaced-module-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misplaced-function-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/invalid-exports/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/invalid-default-exports-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/instance-methods/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/getter-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/next/src/loader.tsSwitches all transforms to mode: 'step'.
packages/rollup/src/index.tsSwitches Rollup integration transform mode to step.
packages/nest/src/cli.tsUpdates generated .swcrc to use mode: 'step' and help text accordingly.
packages/cli/src/commands/transform.tsRemoves client from CLI transform modes/options.
packages/builders/src/apply-swc-transform.tsUpdates API type to drop client mode.
packages/builders/src/swc-esbuild-plugin.tsUpdates SwcPluginOptions.mode type to drop client.
packages/builders/src/base-builder.tsUpdates builder SWC plugin usage from client to step.
packages/nuxt/src/module.tsForces Vite SSR bundling behavior for workflow packages and marks _vite for Nitro.
packages/nitro/src/index.tsAdds dev-only rollup force-inline plugin and dev-time dynamic loading of generated workflow bundles.
packages/nitro/src/builders.tsWrites workflow bundles to temp files first and renames into place.
.changeset/remove-client-mode.mdAdds changeset documenting the breaking removal of client mode and migration guidance.

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

Comment threadpackages/nitro/src/builders.ts Outdated
Comment threadpackages/nuxt/src/module.ts Outdated
Comment threadpackages/nitro/src/index.ts Outdated
- nitro builders: use crypto.randomUUID() for temp file suffix instead of
Date.now() to avoid collisions under rapid/concurrent build() calls,
and serialize concurrent build() calls through an internal queue so
two overlapping dev rebuilds cannot clobber each other's temp outputs.
- nitro index: use fileURLToPath() to convert file:// URLs to filesystem
paths, which correctly handles Windows paths (file:///C:/... -> C:\...)
and percent-decoding, instead of relying on new URL(...).pathname.
- nuxt module: normalize vite.ssr.noExternal to an array (preserving any
existing string/RegExp/array entry) before appending workflow package
matchers, so the force-bundle behavior is not a no-op when noExternal
is already set to a non-array value.

@VaguelySeriousVaguelySerious left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM assuming tests pass, we're only landing this on v5 right?

@TooTallNate

Copy link
Copy Markdown
MemberAuthor

@VaguelySerious correct

Sign up for freeto 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

@TooTallNate@ijjk@VaguelySerious
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

refactor(swc-plugin): remove client transform mode, merge into step mode - #1686

Merged
TooTallNate merged 3 commits into
mainfrom
nr/remove-client-mode
Apr 16, 2026
Merged

refactor(swc-plugin): remove client transform mode, merge into step mode#1686
TooTallNate merged 3 commits into
mainfrom
nr/remove-client-mode

Conversation

@TooTallNate

@TooTallNateTooTallNate commented Apr 10, 2026

Copy link
Copy Markdown
Member

Summary

  • Remove the client transform mode from the SWC compiler plugin, merging it into step mode
  • The plugin now has 3 modes (Step, Workflow, Detect) instead of 4
  • All integrations that previously used mode: 'client' now use mode: 'step'

Motivation

The client and step modes were nearly identical — both preserved step function bodies, replaced workflow bodies with throw stubs, and emitted the same JSON manifest. The only differences were:

  1. Registration mechanism: client used a simple .stepId property assignment; step used an IIFE with global Map registration
  2. Dead code elimination: client ran DCE; step did not
  3. Object property step call sites: client replaced inline functions with hoisted variable references; step kept the original inline copy

None of these differences were fundamentally necessary. Merging them simplifies the codebase by ~450 lines of Rust and removes 67 test fixture files.

What changed in step mode

  • DCE now runs — removes dead code just like it did in client mode, preserving step bodies and their dependencies
  • Object property steps use hoisted variable references at call sites so .stepId is accessible on the same function object
  • IIFE registration is unchanged — all step functions are registered in the global Map

Changed packages

PackageChange
@workflow/swc-pluginRemoved Client variant from TransformMode enum, ~450 lines of client-specific match arms
@workflow/nextloader.ts now always uses mode: 'step'
@workflow/buildersbase-builder.ts, apply-swc-transform.ts, swc-esbuild-plugin.ts — removed 'client' from types and mode values
@workflow/cliRemoved 'client' from transform command options
@workflow/rollupChanged mode: 'client' to mode: 'step'
@workflow/nestChanged mode: 'client' to mode: 'step'
@workflow/swc-playground-wasmRemoved client output from batch transform

@github-actions

github-actionsBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production923067990
✅ 💻 Local Development9940861080
✅ 📦 Local Production9940861080
✅ 🐘 Local Postgres9940861080
✅ 🪟 Windows900090
❌ 🌍 Community Worlds133980231
✅ 📋 Other252018270
Total4380983434821

❌ Failed Tests

🌍 Community Worlds (98 failed)

mongodb (15 failed):

  • readableStreamWorkflow | wrun_01KPC49NNZW9YY0KB64K6VSQHB
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KPC4AC42WBKTER23K36G2ZAT
  • webhookWorkflow | wrun_01KPC4AMQBQNMGQ4RMS3XNMX4K
  • outputStreamWorkflow no startIndex (reads all chunks)
  • outputStreamWorkflow positive startIndex (skips first chunk)
  • outputStreamWorkflow negative startIndex (reads from end)
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns correct index after stream completes
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns -1 before any chunks are written
  • outputStreamWorkflow - getTailIndex and getChunks getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KPC4DTF69CSG9SGAXK101SCA
  • fetchWorkflow | wrun_01KPC4E7RZPD314K6BKBYSXGT0
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KPC4JB5B6GKYQ4NA68WW9JFN
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • health check (CLI) - workflow health command reports healthy endpoints
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KPC4RK5F4H2A50VNYVKYDZYH

redis (15 failed):

  • readableStreamWorkflow | wrun_01KPC49NNZW9YY0KB64K6VSQHB
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KPC4AC42WBKTER23K36G2ZAT
  • webhookWorkflow | wrun_01KPC4AMQBQNMGQ4RMS3XNMX4K
  • outputStreamWorkflow no startIndex (reads all chunks)
  • outputStreamWorkflow positive startIndex (skips first chunk)
  • outputStreamWorkflow negative startIndex (reads from end)
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns correct index after stream completes
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns -1 before any chunks are written
  • outputStreamWorkflow - getTailIndex and getChunks getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KPC4DTF69CSG9SGAXK101SCA
  • fetchWorkflow | wrun_01KPC4E7RZPD314K6BKBYSXGT0
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KPC4JB5B6GKYQ4NA68WW9JFN
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • health check (CLI) - workflow health command reports healthy endpoints
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KPC4RK5F4H2A50VNYVKYDZYH

turso (68 failed):

  • addTenWorkflow | wrun_01KPC494JMXC2S698ZCV0Z1A6J
  • addTenWorkflow | wrun_01KPC494JMXC2S698ZCV0Z1A6J
  • wellKnownAgentWorkflow (.well-known/agent) | wrun_01KPC4AGDR3W8R8RXJT4B0AAA1
  • should work with react rendering in step
  • promiseAllWorkflow | wrun_01KPC49C06JB8S19BQWT39ZGY3
  • promiseRaceWorkflow | wrun_01KPC49GDW34C2CAXQED5GQ5HD
  • promiseAnyWorkflow | wrun_01KPC49JF67R2674SKNT0B531G
  • importedStepOnlyWorkflow | wrun_01KPC4ATXWJTKEXDX5AZ5QQ00W
  • readableStreamWorkflow | wrun_01KPC49NNZW9YY0KB64K6VSQHB
  • hookWorkflow | wrun_01KPC4A08KB58ENADF0R99QWRK
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KPC4AC42WBKTER23K36G2ZAT
  • webhookWorkflow | wrun_01KPC4AMQBQNMGQ4RMS3XNMX4K
  • sleepingWorkflow | wrun_01KPC4ATTECEVNJQ03J54ZFBVM
  • parallelSleepWorkflow | wrun_01KPC4B757NA7GCQPA911F04ZY
  • nullByteWorkflow | wrun_01KPC4BBA9SENAQ2793T64G2HD
  • workflowAndStepMetadataWorkflow | wrun_01KPC4BD6G7ZV66PGPFA4QPD88
  • outputStreamWorkflow no startIndex (reads all chunks)
  • outputStreamWorkflow positive startIndex (skips first chunk)
  • outputStreamWorkflow negative startIndex (reads from end)
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns correct index after stream completes
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns -1 before any chunks are written
  • outputStreamWorkflow - getTailIndex and getChunks getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KPC4DTF69CSG9SGAXK101SCA
  • fetchWorkflow | wrun_01KPC4E7RZPD314K6BKBYSXGT0
  • promiseRaceStressTestWorkflow | wrun_01KPC4EB2BAVKDBD6MS0ZQ6EA2
  • 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_01KPC4HQX6G61Z1EVG4JNP930D
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KPC4JB5B6GKYQ4NA68WW9JFN
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KPC4JYZ7FS1R557Y32RKYX4X
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KPC4KHC0489EJS7TH6H8C1FP
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_01KPC4KSEB6GVW9G0XXRPWE3J8
  • closureVariableWorkflow - nested step functions with closure variables | wrun_01KPC4KYK1XY4DHRRTHJ2T1M21
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_01KPC4M0KZH3ASYEG5R6JBWENC
  • runClassSerializationWorkflow - Run instances serialize across workflow/step boundaries | wrun_01KPC4MB45KDRW8N8D6WN06XEQ
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • health check (CLI) - workflow health command reports healthy endpoints
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_01KPC4MS5KHDWDK2F94N22ZFQW
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_01KPC4MZ6PEQNSM56KWF9FJX1E
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_01KPC4N5GZH4ZFPZPW62YEP6KV
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_01KPC4NBR68W7CSHPE7R7M4EK3
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_01KPC4NHS0ARKDVB77N2MX3CAC
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_01KPC4NQW6FWS4MXN0R48DA026
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_01KPC4NZ0FPXKMQX3X2CQ04PBG
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_01KPC4P9N2G26Q97QRYDQ0Y9YK
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_01KPC4PGZWQE4GQXWWGY0QH4J7
  • cancelRun - cancelling a running workflow | wrun_01KPC4PR5VZ7PAPEH1FB5DTEBH
  • cancelRun via CLI - cancelling a running workflow | wrun_01KPC4Q0WDH365KZXRFP7S3YXX
  • 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_01KPC4QC7VC0XAK4HG5DG72TYK
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KPC4QZCT792E4TFQ8YN5Q6BV
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KPC4R9ARDE36CTKSVKBD0BV7
  • importMetaUrlWorkflow - import.meta.url is available in step bundles | wrun_01KPC4RF7T0AJ9JST4ZEVXQBYY
  • metadataFromHelperWorkflow - getWorkflowMetadata/getStepMetadata work from module-level helper (#1577) | wrun_01KPC4RH3HCX2FND5E2Q3889HY
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KPC4RK5F4H2A50VNYVKYDZYH
  • getterStepWorkflow - getter functions with "use step" directive | wrun_01KPC4RP4RG6MQ9C0QJJXPXG6F

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro8307
✅ example8307
✅ express8307
✅ fastify8307
✅ hono8307
✅ nextjs-turbopack8802
✅ nextjs-webpack8802
✅ nitro8307
✅ nuxt8307
✅ sveltekit8307
✅ vite8307
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable8406
✅ express-stable8406
✅ fastify-stable8406
✅ hono-stable8406
✅ nextjs-turbopack-canary71019
✅ nextjs-turbopack-stable9000
✅ nextjs-webpack-canary71019
✅ nextjs-webpack-stable9000
✅ nitro-stable8406
✅ nuxt-stable8406
✅ sveltekit-stable8406
✅ vite-stable8406
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable8406
✅ express-stable8406
✅ fastify-stable8406
✅ hono-stable8406
✅ nextjs-turbopack-canary71019
✅ nextjs-turbopack-stable9000
✅ nextjs-webpack-canary71019
✅ nextjs-webpack-stable9000
✅ nitro-stable8406
✅ nuxt-stable8406
✅ sveltekit-stable8406
✅ vite-stable8406
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable8406
✅ express-stable8406
✅ fastify-stable8406
✅ hono-stable8406
✅ nextjs-turbopack-canary71019
✅ nextjs-turbopack-stable9000
✅ nextjs-webpack-canary71019
✅ nextjs-webpack-stable9000
✅ nitro-stable8406
✅ nuxt-stable8406
✅ sveltekit-stable8406
✅ vite-stable8406
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack9000
❌ 🌍 Community Worlds
AppPassedFailedSkipped
✅ mongodb-dev600
❌ mongodb56150
✅ redis-dev600
❌ redis56150
✅ turso-dev600
❌ turso3680
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable8406
✅ e2e-local-postgres-nest-stable8406
✅ e2e-local-prod-nest-stable8406

📋 View full workflow run

@github-actions

github-actionsBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

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

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express0.044s (-0.9%)1.005s (~)0.961s101.00x
💻 LocalNitro0.044s (+1.9%)1.005s (~)0.961s101.00x
💻 LocalNext.js (Turbopack)0.047s1.005s0.958s101.08x
🐘 PostgresNitro0.053s (-44.2% 🟢)1.011s (-3.1%)0.957s101.21x
🐘 PostgresNext.js (Turbopack)0.056s1.010s0.954s101.27x
🐘 PostgresExpress0.057s (-1.6%)1.011s (~)0.954s101.30x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro0.232s (-43.5% 🟢)2.120s (-15.5% 🟢)1.888s101.00x
▲ VercelNext.js (Turbopack)0.265s (+5.5% 🔺)2.026s (-13.2% 🟢)1.760s101.15x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Next.js (Turbopack)1.122s2.006s0.884s101.00x
🐘 PostgresNitro1.124s (-1.4%)2.009s (~)0.885s101.00x
💻 LocalNitro1.131s (~)2.006s (~)0.875s101.01x
💻 LocalExpress1.134s (+0.8%)2.007s (~)0.872s101.01x
🐘 PostgresNext.js (Turbopack)1.136s2.011s0.875s101.01x
🐘 PostgresExpress1.154s (+0.6%)2.010s (~)0.856s101.03x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro1.948s (-50.0% 🟢)3.730s (-36.9% 🟢)1.782s101.00x
▲ VercelNext.js (Turbopack)1.978s (-2.8%)3.253s (-15.1% 🟢)1.275s101.02x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro10.738s (-1.2%)11.025s (~)0.287s31.00x
💻 LocalNext.js (Turbopack)10.830s11.023s0.193s31.01x
🐘 PostgresExpress10.894s (-0.6%)11.025s (~)0.131s31.01x
💻 LocalNitro10.920s (~)11.022s (~)0.102s31.02x
🐘 PostgresNext.js (Turbopack)10.927s11.018s0.091s31.02x
💻 LocalExpress10.947s (~)11.024s (~)0.078s31.02x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro17.104s (-27.9% 🟢)19.463s (-22.5% 🟢)2.360s21.00x
▲ VercelNext.js (Turbopack)17.338s (~)18.457s (-4.9%)1.119s21.01x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro14.143s (-3.1%)15.027s (~)0.884s41.00x
🐘 PostgresNext.js (Turbopack)14.476s15.029s0.553s41.02x
💻 LocalNext.js (Turbopack)14.575s15.028s0.454s41.03x
🐘 PostgresExpress14.575s (~)15.026s (~)0.451s41.03x
💻 LocalNitro14.924s (-0.9%)15.029s (-6.2% 🟢)0.104s41.06x
💻 LocalExpress15.108s (+0.9%)16.032s (+6.7% 🔺)0.924s41.07x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro32.373s (-49.8% 🟢)34.553s (-48.1% 🟢)2.179s21.00x
▲ VercelNext.js (Turbopack)33.318s (-36.6% 🟢)34.394s (-37.0% 🟢)1.076s21.03x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro13.235s (-5.2% 🟢)13.880s (-3.0%)0.645s71.00x
🐘 PostgresExpress13.877s (-0.9%)14.022s (-3.9%)0.145s71.05x
🐘 PostgresNext.js (Turbopack)13.974s14.455s0.481s71.06x
💻 LocalNext.js (Turbopack)15.884s16.196s0.312s61.20x
💻 LocalNitro16.479s (-1.8%)17.030s (~)0.552s61.25x
💻 LocalExpress16.807s (+1.2%)17.031s (~)0.224s61.27x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro55.193s (-86.9% 🟢)57.639s (-86.4% 🟢)2.446s21.00x
▲ VercelNext.js (Turbopack)59.836s (-84.8% 🟢)60.966s (-84.6% 🟢)1.130s21.08x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.223s (-4.1%)2.009s (~)0.787s151.00x
🐘 PostgresExpress1.251s (-0.8%)2.010s (~)0.760s151.02x
🐘 PostgresNext.js (Turbopack)1.252s2.009s0.756s151.02x
💻 LocalNext.js (Turbopack)1.488s2.005s0.517s151.22x
💻 LocalNitro1.498s (-8.2% 🟢)2.006s (-3.3%)0.507s151.23x
💻 LocalExpress1.528s (+2.6%)2.006s (~)0.477s151.25x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.389s (-15.2% 🟢)3.777s (-12.6% 🟢)1.388s91.00x
▲ VercelNext.js (Turbopack)2.457s (-27.7% 🟢)3.702s (-25.0% 🟢)1.244s91.03x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro2.320s (-1.3%)3.009s (~)0.689s101.00x
🐘 PostgresExpress2.335s (-1.1%)3.008s (~)0.674s101.01x
🐘 PostgresNext.js (Turbopack)2.393s3.010s0.617s101.03x
💻 LocalNext.js (Turbopack)2.874s3.309s0.435s101.24x
💻 LocalNitro2.898s (-7.8% 🟢)3.453s (-11.1% 🟢)0.555s91.25x
💻 LocalExpress3.040s (+3.0%)3.759s (+8.8% 🔺)0.719s81.31x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.873s (-29.1% 🟢)4.645s (-21.5% 🟢)1.772s71.00x
▲ VercelNext.js (Turbopack)3.637s (-48.8% 🟢)5.185s (-41.8% 🟢)1.548s61.27x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro3.426s (-1.5%)4.010s (~)0.583s81.00x
🐘 PostgresExpress3.459s (-0.8%)4.010s (~)0.551s81.01x
🐘 PostgresNext.js (Turbopack)3.689s4.010s0.321s81.08x
💻 LocalNext.js (Turbopack)7.497s8.019s0.522s42.19x
💻 LocalNitro8.051s (-3.6%)8.772s (-2.8%)0.721s42.35x
💻 LocalExpress8.203s (-1.6%)9.020s (~)0.817s42.39x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro3.559s (+1.0%)5.051s (-8.7% 🟢)1.492s61.00x
▲ VercelNext.js (Turbopack)6.803s (-23.7% 🟢)8.029s (-26.7% 🟢)1.226s41.91x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.209s (-3.8%)2.009s (~)0.800s151.00x
🐘 PostgresNext.js (Turbopack)1.228s2.010s0.782s151.02x
🐘 PostgresExpress1.267s (+0.8%)2.008s (~)0.741s151.05x
💻 LocalNitro1.515s (-18.8% 🟢)2.005s (-14.3% 🟢)0.490s151.25x
💻 LocalNext.js (Turbopack)1.531s2.006s0.475s151.27x
💻 LocalExpress1.544s (-18.5% 🟢)2.006s (-15.1% 🟢)0.462s151.28x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.037s (-17.2% 🟢)3.718s (-10.8% 🟢)1.681s91.00x
▲ VercelNext.js (Turbopack)2.401s (-18.1% 🟢)3.792s (-18.3% 🟢)1.391s81.18x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro2.327s (-0.5%)3.010s (~)0.683s101.00x
🐘 PostgresExpress2.336s (~)3.010s (~)0.674s101.00x
🐘 PostgresNext.js (Turbopack)2.393s3.008s0.616s101.03x
💻 LocalNext.js (Turbopack)2.787s3.452s0.665s91.20x
💻 LocalNitro2.836s (-7.5% 🟢)3.309s (-14.9% 🟢)0.473s101.22x
💻 LocalExpress3.261s (+4.1%)4.011s (+6.6% 🔺)0.750s81.40x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.598s (-19.7% 🟢)4.042s (-20.4% 🟢)1.444s81.00x
▲ VercelNext.js (Turbopack)2.787s (-11.3% 🟢)4.209s (-6.9% 🟢)1.422s81.07x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro3.456s (-0.7%)4.011s (~)0.555s81.00x
🐘 PostgresExpress3.480s (-0.5%)4.010s (~)0.530s81.01x
🐘 PostgresNext.js (Turbopack)3.617s4.012s0.395s81.05x
💻 LocalNext.js (Turbopack)7.510s8.018s0.507s42.17x
💻 LocalNitro8.662s (-5.3% 🟢)9.275s (-7.5% 🟢)0.613s42.51x
💻 LocalExpress8.993s (+2.2%)9.273s (~)0.279s42.60x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.764s (-45.7% 🟢)4.520s (-33.7% 🟢)1.756s71.00x
▲ VercelNext.js (Turbopack)4.827s (-28.6% 🟢)6.399s (-25.1% 🟢)1.572s51.75x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.624s (-23.9% 🟢)1.006s (~)0.382s601.00x
🐘 PostgresNext.js (Turbopack)0.786s1.023s0.237s591.26x
🐘 PostgresExpress0.808s (-3.7%)1.022s (~)0.214s591.29x
💻 LocalNext.js (Turbopack)0.852s1.039s0.187s581.36x
💻 LocalNitro0.988s (+0.8%)1.158s (+5.9% 🔺)0.170s521.58x
💻 LocalExpress0.989s (~)1.250s (+16.1% 🔺)0.261s491.58x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro10.124s (-54.1% 🟢)12.026s (-49.9% 🟢)1.902s51.00x
▲ VercelNext.js (Turbopack)11.473s (-20.9% 🟢)12.880s (-19.9% 🟢)1.407s51.13x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.503s (-22.0% 🟢)2.007s (-4.4%)0.504s451.00x
🐘 PostgresExpress1.918s (-3.0%)2.100s (-7.0% 🟢)0.183s431.28x
🐘 PostgresNext.js (Turbopack)1.959s2.203s0.244s411.30x
💻 LocalNext.js (Turbopack)2.627s3.008s0.381s301.75x
💻 LocalNitro3.004s (-1.0%)3.508s (-6.7% 🟢)0.504s262.00x
💻 LocalExpress3.039s (+0.8%)3.690s (+2.9%)0.651s252.02x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)32.147s (-35.5% 🟢)33.634s (-35.0% 🟢)1.487s31.00x
▲ VercelNitro37.762s (-4.4%)39.759s (-3.7%)1.997s31.17x
▲ VercelExpress⚠️missing----

🔍 Observability: Next.js (Turbopack) | Nitro

workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro3.164s (-22.9% 🟢)3.824s (-16.9% 🟢)0.660s321.00x
🐘 PostgresNext.js (Turbopack)3.883s4.147s0.264s291.23x
🐘 PostgresExpress3.890s (-2.5%)4.110s (-5.9% 🟢)0.219s301.23x
💻 LocalNext.js (Turbopack)8.566s9.018s0.452s142.71x
💻 LocalExpress9.269s (+0.6%)10.019s (~)0.749s122.93x
💻 LocalNitro9.497s (+2.1%)10.101s (+0.8%)0.604s123.00x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro77.978s (-19.5% 🟢)79.827s (-18.9% 🟢)1.850s21.00x
▲ VercelNext.js (Turbopack)89.255s (-16.7% 🟢)90.555s (-16.9% 🟢)1.300s21.14x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.235s (-16.9% 🟢)1.007s (~)0.772s601.00x
🐘 PostgresNext.js (Turbopack)0.256s1.008s0.751s601.09x
🐘 PostgresExpress0.285s (+0.8%)1.007s (~)0.723s601.21x
💻 LocalNext.js (Turbopack)0.575s1.004s0.430s602.44x
💻 LocalExpress0.615s (+9.8% 🔺)1.022s (+1.7%)0.407s592.61x
💻 LocalNitro0.668s (+10.5% 🔺)1.095s (+7.2% 🔺)0.427s552.84x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro1.858s (+11.9% 🔺)3.442s (+2.7%)1.584s181.00x
▲ VercelNext.js (Turbopack)5.248s (+159.5% 🔺)6.681s (+76.1% 🔺)1.432s92.82x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.383s (-22.8% 🟢)1.006s (~)0.623s901.00x
🐘 PostgresExpress0.488s (-4.2%)1.007s (~)0.519s901.27x
🐘 PostgresNext.js (Turbopack)0.503s1.007s0.503s901.31x
💻 LocalNitro2.463s (-3.0%)3.009s (~)0.546s306.43x
💻 LocalExpress2.591s (+3.1%)3.009s (~)0.418s306.76x
💻 LocalNext.js (Turbopack)2.594s3.008s0.414s306.77x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro5.501s (+70.5% 🔺)7.445s (+54.4% 🔺)1.944s131.00x
▲ VercelNext.js (Turbopack)8.725s (+146.8% 🔺)10.373s (+99.7% 🔺)1.648s91.59x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.614s (-22.3% 🟢)1.007s (~)0.393s1201.00x
🐘 PostgresNext.js (Turbopack)0.800s1.008s0.208s1201.30x
🐘 PostgresExpress0.802s (-2.0%)1.016s (~)0.214s1191.31x
💻 LocalNext.js (Turbopack)10.669s11.392s0.723s1117.38x
💻 LocalNitro10.798s (-3.5%)11.300s (-3.1%)0.501s1117.59x
💻 LocalExpress11.456s (+2.4%)12.032s (+0.8%)0.576s1018.66x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro9.424s (+22.0% 🔺)11.667s (+24.1% 🔺)2.243s111.00x
▲ VercelNext.js (Turbopack)15.660s (+51.6% 🔺)16.985s (+38.2% 🔺)1.325s81.66x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.177s (-13.8% 🟢)0.997s (~)0.001s (-20.0% 🟢)1.011s (~)0.834s101.00x
💻 LocalNext.js (Turbopack)0.188s1.003s0.011s1.017s0.830s101.06x
🐘 PostgresNext.js (Turbopack)0.192s1.001s0.002s1.011s0.818s101.09x
💻 LocalNitro0.201s (-6.2% 🟢)1.004s (~)0.011s (-9.6% 🟢)1.017s (~)0.817s101.13x
💻 LocalExpress0.204s (+2.5%)1.004s (~)0.013s (+8.3% 🔺)1.020s (~)0.816s101.15x
🐘 PostgresExpress0.204s (~)1.001s (~)0.002s (+6.2% 🔺)1.011s (~)0.806s101.16x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)1.554s (-77.3% 🟢)2.748s (-68.2% 🟢)0.996s (+57.7% 🔺)4.134s (-57.8% 🟢)2.581s101.00x
▲ VercelNitro1.705s (-55.5% 🟢)2.818s (-46.6% 🟢)1.037s (+39.8% 🔺)4.300s (-33.7% 🟢)2.594s101.10x
▲ VercelExpress⚠️missing-----

🔍 Observability: Next.js (Turbopack) | Nitro

stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.531s (-14.9% 🟢)1.008s (~)0.004s (-14.3% 🟢)1.022s (~)0.491s591.00x
🐘 PostgresExpress0.607s (-3.6%)1.006s (~)0.004s (+3.1%)1.023s (~)0.416s591.14x
🐘 PostgresNext.js (Turbopack)0.617s1.008s0.003s1.020s0.402s591.16x
💻 LocalNitro0.742s (-11.6% 🟢)1.012s (~)0.009s (-2.5%)1.023s (-8.3% 🟢)0.281s591.40x
💻 LocalNext.js (Turbopack)0.806s1.011s0.013s1.120s0.313s541.52x
💻 LocalExpress0.956s (+26.2% 🔺)1.012s (-1.6%)0.010s (+5.4% 🔺)1.229s (+18.2% 🔺)0.273s491.80x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro4.889s (-83.4% 🟢)6.748s (-78.1% 🟢)0.465s (+315.1% 🔺)7.635s (-76.0% 🟢)2.746s81.00x
▲ VercelNext.js (Turbopack)14.674s (-13.3% 🟢)15.526s (-14.9% 🟢)0.211s (~)16.076s (-15.1% 🟢)1.403s53.00x
▲ VercelExpress⚠️missing-----

🔍 Observability: Nitro | Next.js (Turbopack)

10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.938s1.112s0.000s1.119s0.182s541.00x
🐘 PostgresNitro0.944s (-2.6%)1.177s (-5.7% 🟢)0.000s (+41.2% 🔺)1.190s (-5.4% 🟢)0.246s511.01x
🐘 PostgresExpress0.974s (+1.4%)1.219s (-4.6%)0.000s (+87.8% 🔺)1.243s (-4.9%)0.269s491.04x
💻 LocalNitro1.214s (-0.7%)2.021s (~)0.000s (+33.3% 🔺)2.022s (~)0.808s301.30x
💻 LocalExpress1.238s (+1.0%)2.020s (~)0.000s (-10.0% 🟢)2.022s (~)0.785s301.32x
💻 LocalNext.js (Turbopack)1.296s2.019s0.000s2.023s0.727s301.38x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro6.050s (+98.3% 🔺)7.665s (+74.5% 🔺)0.000s (-100.0% 🟢)8.112s (+68.7% 🔺)2.062s81.00x
▲ VercelNext.js (Turbopack)7.695s (-24.4% 🟢)7.641s (-33.7% 🟢)0.000s (NaN%)9.028s (-25.1% 🟢)1.333s71.27x
▲ VercelExpress⚠️missing-----

🔍 Observability: Nitro | Next.js (Turbopack)

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

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.720s (-4.0%)2.104s (-1.7%)0.000s (+93.1% 🔺)2.112s (-2.9%)0.392s291.00x
🐘 PostgresExpress1.727s (-2.5%)2.104s (-3.4%)0.000s (NaN%)2.113s (-3.9%)0.386s291.00x
🐘 PostgresNext.js (Turbopack)1.888s2.182s0.000s2.189s0.301s281.10x
💻 LocalNitro3.502s (+3.4%)4.035s (~)0.001s (+50.0% 🔺)4.038s (~)0.536s152.04x
💻 LocalExpress3.589s (+3.5%)4.030s (~)0.000s (-58.3% 🟢)4.033s (~)0.444s152.09x
💻 LocalNext.js (Turbopack)3.746s4.166s0.000s4.170s0.424s152.18x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)5.451s (-3.0%)6.756s (-3.2%)0.000s (-100.0% 🟢)7.096s (-5.9% 🟢)1.645s91.00x
▲ VercelNitro8.938s (+118.3% 🔺)10.290s (+91.5% 🔺)0.000s (-100.0% 🟢)10.758s (+85.7% 🔺)1.819s61.64x
▲ VercelExpress⚠️missing-----

🔍 Observability: Next.js (Turbopack) | Nitro

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalNext.js (Turbopack)15/21
🐘 PostgresNitro20/21
▲ VercelNitro18/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres18/21
Next.js (Turbopack)🐘 Postgres17/21
Nitro🐘 Postgres19/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

@changeset-bot

changeset-botBot commented Apr 10, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: dc6415b

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

This PR includes changesets to release 18 packages
NameType
@workflow/swc-pluginMajor
@workflow/buildersPatch
@workflow/cliPatch
@workflow/nextPatch
@workflow/rollupPatch
@workflow/nestPatch
@workflow/astroPatch
@workflow/nitroPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/vitestPatch
workflowPatch
@workflow/world-testingPatch
@workflow/nuxtPatch
@workflow/aiPatch
@workflow/corePatch
@workflow/web-sharedPatch
@workflow/webPatch

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

vercelBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

@TooTallNate
TooTallNateforce-pushed the nr/remove-client-mode branch from aac9033 to cf9fe73CompareApril 10, 2026 17:20
Remove the `client` transform mode from the SWC compiler plugin. The
`client` and `step` modes were nearly identical — both preserved step
function bodies, replaced workflow bodies with throw stubs, and emitted
the same JSON manifest. Step mode now absorbs all client-mode behaviors:
- Dead code elimination (previously only workflow + client)
- Hoisted variable references for object property steps
- All integrations use mode: 'step' instead of 'client'
BREAKING CHANGE: The `client` value for the SWC plugin `mode` option is
no longer accepted. Use `step` instead.
…sId registration
In dev mode, Nitro's Rollup externalizes npm packages like @workflow/core,
so the SWC transform plugin never processes files like run.js. This means
serde classes (e.g. Run) never get the classId registration IIFE, causing
serialization failures when step functions return Run instances.
Uses a Rollup resolveId hook to force workflow SDK packages to be bundled
(non-external) while leaving all other dependencies external. This is more
targeted than noExternals=true which bundles everything and causes TDZ
errors from circular imports in packages like vue-bundle-renderer/h3.
The Nitro module now also ignores .nitro/workflow/** in watchOptions so
writing generated workflow bundles does not retrigger Nitro's own dev
bundle rebuild loop.
Also wraps dev:reload workflow rebuilds and makes LocalBuilder.build()
atomic (writes to temp files, renames on success) to avoid partial output
state during HMR.
For Nuxt, also configures Vite's ssr.noExternal to bundle workflow
packages in the SSR context.

CopilotAI left a comment

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.

Pull request overview

Removes the SWC plugin’s client transform mode by merging its behavior into step mode, and updates all repository integrations, docs, and fixtures to use the new 3-mode model (Step/Workflow/Detect).

Changes:

  • Dropped Client from TransformMode, updated step mode to include client-mode behaviors (notably DCE + object-property hoisting semantics), and removed client-mode fixture runners/outputs.
  • Updated framework/tooling integrations (Next loader, Rollup, Nest CLI, Builders, CLI) to use mode: 'step' everywhere client was previously used.
  • Updated docs/spec and the SWC playground (WASM + UI/types) to remove the client output/view.

Reviewed changes

Copilot reviewed 103 out of 103 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
workbench/swc-playground/wasm/src/lib.rsRemoves client from batch transform output and runs only workflow+step.
workbench/swc-playground/lib/transform.tsUpdates TS types to drop client transform result.
workbench/swc-playground/components/swc-playground.tsxRemoves client view/panel/state in the playground UI.
packages/swc-plugin-workflow/transform/src/lib.rsRemoves Client mode and folds client behaviors into Step (DCE, hoisting/registration paths, etc.).
packages/swc-plugin-workflow/spec.mdUpdates specification to reflect 3 modes and step-mode DCE/hoisting behavior.
packages/swc-plugin-workflow/transform/tests/fixture.rsRemoves the client-mode fixture test harness.
packages/swc-plugin-workflow/transform/tests/errors.rsRemoves the client-mode errors fixture harness and updates imports.
packages/swc-plugin-workflow/transform/tests/fixture/workflow-client-property/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/workflow-arrow-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/var-named-step-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/using-declaration-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/using-declaration-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/user-named-dunder-default/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/unused-variables-and-types/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/unused-variables-and-types/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/unused-exports/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/unused-exports/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step/output-step.jsUpdates step-mode fixture to reflect new object-property hoisting behavior.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step-default-export/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step-class/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/step-with-this-arguments-super/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/step-with-imports/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/step-with-imports/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/step-arrow-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/static-method-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/static-method-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/static-getter-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/single-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/single-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/separate-export-statement/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/private-member-dce/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/private-member-dce-native/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/object-property-step/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/object-property-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/object-getter-step/output-step.jsUpdates step-mode fixture to reflect object getter/property behavior.
packages/swc-plugin-workflow/transform/tests/fixture/object-getter-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/nested-steps-in-object-constructor/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/nested-steps-in-object-constructor/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/nested-step-with-closure/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/nested-step-with-closure/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/nested-step-in-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/multiple-const-step-functions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-workflow/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-step/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/mixed-functions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/let-arrow-step-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/instance-method-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/instance-method-nested-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/instance-getter-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/expr-fn-default-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-named/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-anonymous/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-anonymous-step-only/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/destructuring/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/default-workflow-collision/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/output-workflow.jsUpdates fixture to reflect export changes under new behavior.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/output-step.jsUpdates fixture to reflect export changes under new behavior.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/input.jsUpdates input fixture to be exported (aligning outputs).
packages/swc-plugin-workflow/transform/tests/fixture/default-arrow-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/deeply-nested-step/output-step.jsUpdates step-mode fixture to reflect hoisted reference usage.
packages/swc-plugin-workflow/transform/tests/fixture/deeply-nested-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-require-namespace/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-require-destructured/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-local-const/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-imported/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/closure-typescript-expressions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/closure-new-expr-and-module-declarations/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/class-expression-binding-name/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/class-expression-binding-name-step-methods/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/anonymous-default-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step-shorthand-method/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step-shorthand-method/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/sync-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/non-async-functions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misspelled-workflow-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misspelled-step-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misplaced-module-directive/output-step.jsUpdates step-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misplaced-module-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misplaced-function-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/invalid-exports/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/invalid-default-exports-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/instance-methods/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/getter-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/next/src/loader.tsSwitches all transforms to mode: 'step'.
packages/rollup/src/index.tsSwitches Rollup integration transform mode to step.
packages/nest/src/cli.tsUpdates generated .swcrc to use mode: 'step' and help text accordingly.
packages/cli/src/commands/transform.tsRemoves client from CLI transform modes/options.
packages/builders/src/apply-swc-transform.tsUpdates API type to drop client mode.
packages/builders/src/swc-esbuild-plugin.tsUpdates SwcPluginOptions.mode type to drop client.
packages/builders/src/base-builder.tsUpdates builder SWC plugin usage from client to step.
packages/nuxt/src/module.tsForces Vite SSR bundling behavior for workflow packages and marks _vite for Nitro.
packages/nitro/src/index.tsAdds dev-only rollup force-inline plugin and dev-time dynamic loading of generated workflow bundles.
packages/nitro/src/builders.tsWrites workflow bundles to temp files first and renames into place.
.changeset/remove-client-mode.mdAdds changeset documenting the breaking removal of client mode and migration guidance.

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

Comment threadpackages/nitro/src/builders.ts Outdated
Comment threadpackages/nuxt/src/module.ts Outdated
Comment threadpackages/nitro/src/index.ts Outdated
- nitro builders: use crypto.randomUUID() for temp file suffix instead of
Date.now() to avoid collisions under rapid/concurrent build() calls,
and serialize concurrent build() calls through an internal queue so
two overlapping dev rebuilds cannot clobber each other's temp outputs.
- nitro index: use fileURLToPath() to convert file:// URLs to filesystem
paths, which correctly handles Windows paths (file:///C:/... -> C:\...)
and percent-decoding, instead of relying on new URL(...).pathname.
- nuxt module: normalize vite.ssr.noExternal to an array (preserving any
existing string/RegExp/array entry) before appending workflow package
matchers, so the force-bundle behavior is not a no-op when noExternal
is already set to a non-array value.

@VaguelySeriousVaguelySerious left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM assuming tests pass, we're only landing this on v5 right?

@TooTallNate

Copy link
Copy Markdown
MemberAuthor

@VaguelySerious correct

Sign up for freeto 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

@TooTallNate@ijjk@VaguelySerious
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

refactor(swc-plugin): remove client transform mode, merge into step mode - #1686

Merged
TooTallNate merged 3 commits into
mainfrom
nr/remove-client-mode
Apr 16, 2026
Merged

refactor(swc-plugin): remove client transform mode, merge into step mode#1686
TooTallNate merged 3 commits into
mainfrom
nr/remove-client-mode

Conversation

@TooTallNate

@TooTallNateTooTallNate commented Apr 10, 2026

Copy link
Copy Markdown
Member

Summary

  • Remove the client transform mode from the SWC compiler plugin, merging it into step mode
  • The plugin now has 3 modes (Step, Workflow, Detect) instead of 4
  • All integrations that previously used mode: 'client' now use mode: 'step'

Motivation

The client and step modes were nearly identical — both preserved step function bodies, replaced workflow bodies with throw stubs, and emitted the same JSON manifest. The only differences were:

  1. Registration mechanism: client used a simple .stepId property assignment; step used an IIFE with global Map registration
  2. Dead code elimination: client ran DCE; step did not
  3. Object property step call sites: client replaced inline functions with hoisted variable references; step kept the original inline copy

None of these differences were fundamentally necessary. Merging them simplifies the codebase by ~450 lines of Rust and removes 67 test fixture files.

What changed in step mode

  • DCE now runs — removes dead code just like it did in client mode, preserving step bodies and their dependencies
  • Object property steps use hoisted variable references at call sites so .stepId is accessible on the same function object
  • IIFE registration is unchanged — all step functions are registered in the global Map

Changed packages

PackageChange
@workflow/swc-pluginRemoved Client variant from TransformMode enum, ~450 lines of client-specific match arms
@workflow/nextloader.ts now always uses mode: 'step'
@workflow/buildersbase-builder.ts, apply-swc-transform.ts, swc-esbuild-plugin.ts — removed 'client' from types and mode values
@workflow/cliRemoved 'client' from transform command options
@workflow/rollupChanged mode: 'client' to mode: 'step'
@workflow/nestChanged mode: 'client' to mode: 'step'
@workflow/swc-playground-wasmRemoved client output from batch transform

@github-actions

github-actionsBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production923067990
✅ 💻 Local Development9940861080
✅ 📦 Local Production9940861080
✅ 🐘 Local Postgres9940861080
✅ 🪟 Windows900090
❌ 🌍 Community Worlds133980231
✅ 📋 Other252018270
Total4380983434821

❌ Failed Tests

🌍 Community Worlds (98 failed)

mongodb (15 failed):

  • readableStreamWorkflow | wrun_01KPC49NNZW9YY0KB64K6VSQHB
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KPC4AC42WBKTER23K36G2ZAT
  • webhookWorkflow | wrun_01KPC4AMQBQNMGQ4RMS3XNMX4K
  • outputStreamWorkflow no startIndex (reads all chunks)
  • outputStreamWorkflow positive startIndex (skips first chunk)
  • outputStreamWorkflow negative startIndex (reads from end)
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns correct index after stream completes
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns -1 before any chunks are written
  • outputStreamWorkflow - getTailIndex and getChunks getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KPC4DTF69CSG9SGAXK101SCA
  • fetchWorkflow | wrun_01KPC4E7RZPD314K6BKBYSXGT0
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KPC4JB5B6GKYQ4NA68WW9JFN
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • health check (CLI) - workflow health command reports healthy endpoints
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KPC4RK5F4H2A50VNYVKYDZYH

redis (15 failed):

  • readableStreamWorkflow | wrun_01KPC49NNZW9YY0KB64K6VSQHB
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KPC4AC42WBKTER23K36G2ZAT
  • webhookWorkflow | wrun_01KPC4AMQBQNMGQ4RMS3XNMX4K
  • outputStreamWorkflow no startIndex (reads all chunks)
  • outputStreamWorkflow positive startIndex (skips first chunk)
  • outputStreamWorkflow negative startIndex (reads from end)
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns correct index after stream completes
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns -1 before any chunks are written
  • outputStreamWorkflow - getTailIndex and getChunks getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KPC4DTF69CSG9SGAXK101SCA
  • fetchWorkflow | wrun_01KPC4E7RZPD314K6BKBYSXGT0
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KPC4JB5B6GKYQ4NA68WW9JFN
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • health check (CLI) - workflow health command reports healthy endpoints
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KPC4RK5F4H2A50VNYVKYDZYH

turso (68 failed):

  • addTenWorkflow | wrun_01KPC494JMXC2S698ZCV0Z1A6J
  • addTenWorkflow | wrun_01KPC494JMXC2S698ZCV0Z1A6J
  • wellKnownAgentWorkflow (.well-known/agent) | wrun_01KPC4AGDR3W8R8RXJT4B0AAA1
  • should work with react rendering in step
  • promiseAllWorkflow | wrun_01KPC49C06JB8S19BQWT39ZGY3
  • promiseRaceWorkflow | wrun_01KPC49GDW34C2CAXQED5GQ5HD
  • promiseAnyWorkflow | wrun_01KPC49JF67R2674SKNT0B531G
  • importedStepOnlyWorkflow | wrun_01KPC4ATXWJTKEXDX5AZ5QQ00W
  • readableStreamWorkflow | wrun_01KPC49NNZW9YY0KB64K6VSQHB
  • hookWorkflow | wrun_01KPC4A08KB58ENADF0R99QWRK
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KPC4AC42WBKTER23K36G2ZAT
  • webhookWorkflow | wrun_01KPC4AMQBQNMGQ4RMS3XNMX4K
  • sleepingWorkflow | wrun_01KPC4ATTECEVNJQ03J54ZFBVM
  • parallelSleepWorkflow | wrun_01KPC4B757NA7GCQPA911F04ZY
  • nullByteWorkflow | wrun_01KPC4BBA9SENAQ2793T64G2HD
  • workflowAndStepMetadataWorkflow | wrun_01KPC4BD6G7ZV66PGPFA4QPD88
  • outputStreamWorkflow no startIndex (reads all chunks)
  • outputStreamWorkflow positive startIndex (skips first chunk)
  • outputStreamWorkflow negative startIndex (reads from end)
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns correct index after stream completes
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns -1 before any chunks are written
  • outputStreamWorkflow - getTailIndex and getChunks getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KPC4DTF69CSG9SGAXK101SCA
  • fetchWorkflow | wrun_01KPC4E7RZPD314K6BKBYSXGT0
  • promiseRaceStressTestWorkflow | wrun_01KPC4EB2BAVKDBD6MS0ZQ6EA2
  • 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_01KPC4HQX6G61Z1EVG4JNP930D
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KPC4JB5B6GKYQ4NA68WW9JFN
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KPC4JYZ7FS1R557Y32RKYX4X
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KPC4KHC0489EJS7TH6H8C1FP
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_01KPC4KSEB6GVW9G0XXRPWE3J8
  • closureVariableWorkflow - nested step functions with closure variables | wrun_01KPC4KYK1XY4DHRRTHJ2T1M21
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_01KPC4M0KZH3ASYEG5R6JBWENC
  • runClassSerializationWorkflow - Run instances serialize across workflow/step boundaries | wrun_01KPC4MB45KDRW8N8D6WN06XEQ
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • health check (CLI) - workflow health command reports healthy endpoints
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_01KPC4MS5KHDWDK2F94N22ZFQW
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_01KPC4MZ6PEQNSM56KWF9FJX1E
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_01KPC4N5GZH4ZFPZPW62YEP6KV
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_01KPC4NBR68W7CSHPE7R7M4EK3
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_01KPC4NHS0ARKDVB77N2MX3CAC
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_01KPC4NQW6FWS4MXN0R48DA026
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_01KPC4NZ0FPXKMQX3X2CQ04PBG
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_01KPC4P9N2G26Q97QRYDQ0Y9YK
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_01KPC4PGZWQE4GQXWWGY0QH4J7
  • cancelRun - cancelling a running workflow | wrun_01KPC4PR5VZ7PAPEH1FB5DTEBH
  • cancelRun via CLI - cancelling a running workflow | wrun_01KPC4Q0WDH365KZXRFP7S3YXX
  • 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_01KPC4QC7VC0XAK4HG5DG72TYK
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KPC4QZCT792E4TFQ8YN5Q6BV
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KPC4R9ARDE36CTKSVKBD0BV7
  • importMetaUrlWorkflow - import.meta.url is available in step bundles | wrun_01KPC4RF7T0AJ9JST4ZEVXQBYY
  • metadataFromHelperWorkflow - getWorkflowMetadata/getStepMetadata work from module-level helper (#1577) | wrun_01KPC4RH3HCX2FND5E2Q3889HY
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KPC4RK5F4H2A50VNYVKYDZYH
  • getterStepWorkflow - getter functions with "use step" directive | wrun_01KPC4RP4RG6MQ9C0QJJXPXG6F

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro8307
✅ example8307
✅ express8307
✅ fastify8307
✅ hono8307
✅ nextjs-turbopack8802
✅ nextjs-webpack8802
✅ nitro8307
✅ nuxt8307
✅ sveltekit8307
✅ vite8307
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable8406
✅ express-stable8406
✅ fastify-stable8406
✅ hono-stable8406
✅ nextjs-turbopack-canary71019
✅ nextjs-turbopack-stable9000
✅ nextjs-webpack-canary71019
✅ nextjs-webpack-stable9000
✅ nitro-stable8406
✅ nuxt-stable8406
✅ sveltekit-stable8406
✅ vite-stable8406
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable8406
✅ express-stable8406
✅ fastify-stable8406
✅ hono-stable8406
✅ nextjs-turbopack-canary71019
✅ nextjs-turbopack-stable9000
✅ nextjs-webpack-canary71019
✅ nextjs-webpack-stable9000
✅ nitro-stable8406
✅ nuxt-stable8406
✅ sveltekit-stable8406
✅ vite-stable8406
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable8406
✅ express-stable8406
✅ fastify-stable8406
✅ hono-stable8406
✅ nextjs-turbopack-canary71019
✅ nextjs-turbopack-stable9000
✅ nextjs-webpack-canary71019
✅ nextjs-webpack-stable9000
✅ nitro-stable8406
✅ nuxt-stable8406
✅ sveltekit-stable8406
✅ vite-stable8406
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack9000
❌ 🌍 Community Worlds
AppPassedFailedSkipped
✅ mongodb-dev600
❌ mongodb56150
✅ redis-dev600
❌ redis56150
✅ turso-dev600
❌ turso3680
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable8406
✅ e2e-local-postgres-nest-stable8406
✅ e2e-local-prod-nest-stable8406

📋 View full workflow run

@github-actions

github-actionsBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

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

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express0.044s (-0.9%)1.005s (~)0.961s101.00x
💻 LocalNitro0.044s (+1.9%)1.005s (~)0.961s101.00x
💻 LocalNext.js (Turbopack)0.047s1.005s0.958s101.08x
🐘 PostgresNitro0.053s (-44.2% 🟢)1.011s (-3.1%)0.957s101.21x
🐘 PostgresNext.js (Turbopack)0.056s1.010s0.954s101.27x
🐘 PostgresExpress0.057s (-1.6%)1.011s (~)0.954s101.30x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro0.232s (-43.5% 🟢)2.120s (-15.5% 🟢)1.888s101.00x
▲ VercelNext.js (Turbopack)0.265s (+5.5% 🔺)2.026s (-13.2% 🟢)1.760s101.15x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Next.js (Turbopack)1.122s2.006s0.884s101.00x
🐘 PostgresNitro1.124s (-1.4%)2.009s (~)0.885s101.00x
💻 LocalNitro1.131s (~)2.006s (~)0.875s101.01x
💻 LocalExpress1.134s (+0.8%)2.007s (~)0.872s101.01x
🐘 PostgresNext.js (Turbopack)1.136s2.011s0.875s101.01x
🐘 PostgresExpress1.154s (+0.6%)2.010s (~)0.856s101.03x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro1.948s (-50.0% 🟢)3.730s (-36.9% 🟢)1.782s101.00x
▲ VercelNext.js (Turbopack)1.978s (-2.8%)3.253s (-15.1% 🟢)1.275s101.02x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro10.738s (-1.2%)11.025s (~)0.287s31.00x
💻 LocalNext.js (Turbopack)10.830s11.023s0.193s31.01x
🐘 PostgresExpress10.894s (-0.6%)11.025s (~)0.131s31.01x
💻 LocalNitro10.920s (~)11.022s (~)0.102s31.02x
🐘 PostgresNext.js (Turbopack)10.927s11.018s0.091s31.02x
💻 LocalExpress10.947s (~)11.024s (~)0.078s31.02x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro17.104s (-27.9% 🟢)19.463s (-22.5% 🟢)2.360s21.00x
▲ VercelNext.js (Turbopack)17.338s (~)18.457s (-4.9%)1.119s21.01x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro14.143s (-3.1%)15.027s (~)0.884s41.00x
🐘 PostgresNext.js (Turbopack)14.476s15.029s0.553s41.02x
💻 LocalNext.js (Turbopack)14.575s15.028s0.454s41.03x
🐘 PostgresExpress14.575s (~)15.026s (~)0.451s41.03x
💻 LocalNitro14.924s (-0.9%)15.029s (-6.2% 🟢)0.104s41.06x
💻 LocalExpress15.108s (+0.9%)16.032s (+6.7% 🔺)0.924s41.07x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro32.373s (-49.8% 🟢)34.553s (-48.1% 🟢)2.179s21.00x
▲ VercelNext.js (Turbopack)33.318s (-36.6% 🟢)34.394s (-37.0% 🟢)1.076s21.03x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro13.235s (-5.2% 🟢)13.880s (-3.0%)0.645s71.00x
🐘 PostgresExpress13.877s (-0.9%)14.022s (-3.9%)0.145s71.05x
🐘 PostgresNext.js (Turbopack)13.974s14.455s0.481s71.06x
💻 LocalNext.js (Turbopack)15.884s16.196s0.312s61.20x
💻 LocalNitro16.479s (-1.8%)17.030s (~)0.552s61.25x
💻 LocalExpress16.807s (+1.2%)17.031s (~)0.224s61.27x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro55.193s (-86.9% 🟢)57.639s (-86.4% 🟢)2.446s21.00x
▲ VercelNext.js (Turbopack)59.836s (-84.8% 🟢)60.966s (-84.6% 🟢)1.130s21.08x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.223s (-4.1%)2.009s (~)0.787s151.00x
🐘 PostgresExpress1.251s (-0.8%)2.010s (~)0.760s151.02x
🐘 PostgresNext.js (Turbopack)1.252s2.009s0.756s151.02x
💻 LocalNext.js (Turbopack)1.488s2.005s0.517s151.22x
💻 LocalNitro1.498s (-8.2% 🟢)2.006s (-3.3%)0.507s151.23x
💻 LocalExpress1.528s (+2.6%)2.006s (~)0.477s151.25x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.389s (-15.2% 🟢)3.777s (-12.6% 🟢)1.388s91.00x
▲ VercelNext.js (Turbopack)2.457s (-27.7% 🟢)3.702s (-25.0% 🟢)1.244s91.03x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro2.320s (-1.3%)3.009s (~)0.689s101.00x
🐘 PostgresExpress2.335s (-1.1%)3.008s (~)0.674s101.01x
🐘 PostgresNext.js (Turbopack)2.393s3.010s0.617s101.03x
💻 LocalNext.js (Turbopack)2.874s3.309s0.435s101.24x
💻 LocalNitro2.898s (-7.8% 🟢)3.453s (-11.1% 🟢)0.555s91.25x
💻 LocalExpress3.040s (+3.0%)3.759s (+8.8% 🔺)0.719s81.31x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.873s (-29.1% 🟢)4.645s (-21.5% 🟢)1.772s71.00x
▲ VercelNext.js (Turbopack)3.637s (-48.8% 🟢)5.185s (-41.8% 🟢)1.548s61.27x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro3.426s (-1.5%)4.010s (~)0.583s81.00x
🐘 PostgresExpress3.459s (-0.8%)4.010s (~)0.551s81.01x
🐘 PostgresNext.js (Turbopack)3.689s4.010s0.321s81.08x
💻 LocalNext.js (Turbopack)7.497s8.019s0.522s42.19x
💻 LocalNitro8.051s (-3.6%)8.772s (-2.8%)0.721s42.35x
💻 LocalExpress8.203s (-1.6%)9.020s (~)0.817s42.39x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro3.559s (+1.0%)5.051s (-8.7% 🟢)1.492s61.00x
▲ VercelNext.js (Turbopack)6.803s (-23.7% 🟢)8.029s (-26.7% 🟢)1.226s41.91x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.209s (-3.8%)2.009s (~)0.800s151.00x
🐘 PostgresNext.js (Turbopack)1.228s2.010s0.782s151.02x
🐘 PostgresExpress1.267s (+0.8%)2.008s (~)0.741s151.05x
💻 LocalNitro1.515s (-18.8% 🟢)2.005s (-14.3% 🟢)0.490s151.25x
💻 LocalNext.js (Turbopack)1.531s2.006s0.475s151.27x
💻 LocalExpress1.544s (-18.5% 🟢)2.006s (-15.1% 🟢)0.462s151.28x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.037s (-17.2% 🟢)3.718s (-10.8% 🟢)1.681s91.00x
▲ VercelNext.js (Turbopack)2.401s (-18.1% 🟢)3.792s (-18.3% 🟢)1.391s81.18x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro2.327s (-0.5%)3.010s (~)0.683s101.00x
🐘 PostgresExpress2.336s (~)3.010s (~)0.674s101.00x
🐘 PostgresNext.js (Turbopack)2.393s3.008s0.616s101.03x
💻 LocalNext.js (Turbopack)2.787s3.452s0.665s91.20x
💻 LocalNitro2.836s (-7.5% 🟢)3.309s (-14.9% 🟢)0.473s101.22x
💻 LocalExpress3.261s (+4.1%)4.011s (+6.6% 🔺)0.750s81.40x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.598s (-19.7% 🟢)4.042s (-20.4% 🟢)1.444s81.00x
▲ VercelNext.js (Turbopack)2.787s (-11.3% 🟢)4.209s (-6.9% 🟢)1.422s81.07x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro3.456s (-0.7%)4.011s (~)0.555s81.00x
🐘 PostgresExpress3.480s (-0.5%)4.010s (~)0.530s81.01x
🐘 PostgresNext.js (Turbopack)3.617s4.012s0.395s81.05x
💻 LocalNext.js (Turbopack)7.510s8.018s0.507s42.17x
💻 LocalNitro8.662s (-5.3% 🟢)9.275s (-7.5% 🟢)0.613s42.51x
💻 LocalExpress8.993s (+2.2%)9.273s (~)0.279s42.60x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.764s (-45.7% 🟢)4.520s (-33.7% 🟢)1.756s71.00x
▲ VercelNext.js (Turbopack)4.827s (-28.6% 🟢)6.399s (-25.1% 🟢)1.572s51.75x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.624s (-23.9% 🟢)1.006s (~)0.382s601.00x
🐘 PostgresNext.js (Turbopack)0.786s1.023s0.237s591.26x
🐘 PostgresExpress0.808s (-3.7%)1.022s (~)0.214s591.29x
💻 LocalNext.js (Turbopack)0.852s1.039s0.187s581.36x
💻 LocalNitro0.988s (+0.8%)1.158s (+5.9% 🔺)0.170s521.58x
💻 LocalExpress0.989s (~)1.250s (+16.1% 🔺)0.261s491.58x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro10.124s (-54.1% 🟢)12.026s (-49.9% 🟢)1.902s51.00x
▲ VercelNext.js (Turbopack)11.473s (-20.9% 🟢)12.880s (-19.9% 🟢)1.407s51.13x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.503s (-22.0% 🟢)2.007s (-4.4%)0.504s451.00x
🐘 PostgresExpress1.918s (-3.0%)2.100s (-7.0% 🟢)0.183s431.28x
🐘 PostgresNext.js (Turbopack)1.959s2.203s0.244s411.30x
💻 LocalNext.js (Turbopack)2.627s3.008s0.381s301.75x
💻 LocalNitro3.004s (-1.0%)3.508s (-6.7% 🟢)0.504s262.00x
💻 LocalExpress3.039s (+0.8%)3.690s (+2.9%)0.651s252.02x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)32.147s (-35.5% 🟢)33.634s (-35.0% 🟢)1.487s31.00x
▲ VercelNitro37.762s (-4.4%)39.759s (-3.7%)1.997s31.17x
▲ VercelExpress⚠️missing----

🔍 Observability: Next.js (Turbopack) | Nitro

workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro3.164s (-22.9% 🟢)3.824s (-16.9% 🟢)0.660s321.00x
🐘 PostgresNext.js (Turbopack)3.883s4.147s0.264s291.23x
🐘 PostgresExpress3.890s (-2.5%)4.110s (-5.9% 🟢)0.219s301.23x
💻 LocalNext.js (Turbopack)8.566s9.018s0.452s142.71x
💻 LocalExpress9.269s (+0.6%)10.019s (~)0.749s122.93x
💻 LocalNitro9.497s (+2.1%)10.101s (+0.8%)0.604s123.00x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro77.978s (-19.5% 🟢)79.827s (-18.9% 🟢)1.850s21.00x
▲ VercelNext.js (Turbopack)89.255s (-16.7% 🟢)90.555s (-16.9% 🟢)1.300s21.14x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.235s (-16.9% 🟢)1.007s (~)0.772s601.00x
🐘 PostgresNext.js (Turbopack)0.256s1.008s0.751s601.09x
🐘 PostgresExpress0.285s (+0.8%)1.007s (~)0.723s601.21x
💻 LocalNext.js (Turbopack)0.575s1.004s0.430s602.44x
💻 LocalExpress0.615s (+9.8% 🔺)1.022s (+1.7%)0.407s592.61x
💻 LocalNitro0.668s (+10.5% 🔺)1.095s (+7.2% 🔺)0.427s552.84x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro1.858s (+11.9% 🔺)3.442s (+2.7%)1.584s181.00x
▲ VercelNext.js (Turbopack)5.248s (+159.5% 🔺)6.681s (+76.1% 🔺)1.432s92.82x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.383s (-22.8% 🟢)1.006s (~)0.623s901.00x
🐘 PostgresExpress0.488s (-4.2%)1.007s (~)0.519s901.27x
🐘 PostgresNext.js (Turbopack)0.503s1.007s0.503s901.31x
💻 LocalNitro2.463s (-3.0%)3.009s (~)0.546s306.43x
💻 LocalExpress2.591s (+3.1%)3.009s (~)0.418s306.76x
💻 LocalNext.js (Turbopack)2.594s3.008s0.414s306.77x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro5.501s (+70.5% 🔺)7.445s (+54.4% 🔺)1.944s131.00x
▲ VercelNext.js (Turbopack)8.725s (+146.8% 🔺)10.373s (+99.7% 🔺)1.648s91.59x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.614s (-22.3% 🟢)1.007s (~)0.393s1201.00x
🐘 PostgresNext.js (Turbopack)0.800s1.008s0.208s1201.30x
🐘 PostgresExpress0.802s (-2.0%)1.016s (~)0.214s1191.31x
💻 LocalNext.js (Turbopack)10.669s11.392s0.723s1117.38x
💻 LocalNitro10.798s (-3.5%)11.300s (-3.1%)0.501s1117.59x
💻 LocalExpress11.456s (+2.4%)12.032s (+0.8%)0.576s1018.66x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro9.424s (+22.0% 🔺)11.667s (+24.1% 🔺)2.243s111.00x
▲ VercelNext.js (Turbopack)15.660s (+51.6% 🔺)16.985s (+38.2% 🔺)1.325s81.66x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.177s (-13.8% 🟢)0.997s (~)0.001s (-20.0% 🟢)1.011s (~)0.834s101.00x
💻 LocalNext.js (Turbopack)0.188s1.003s0.011s1.017s0.830s101.06x
🐘 PostgresNext.js (Turbopack)0.192s1.001s0.002s1.011s0.818s101.09x
💻 LocalNitro0.201s (-6.2% 🟢)1.004s (~)0.011s (-9.6% 🟢)1.017s (~)0.817s101.13x
💻 LocalExpress0.204s (+2.5%)1.004s (~)0.013s (+8.3% 🔺)1.020s (~)0.816s101.15x
🐘 PostgresExpress0.204s (~)1.001s (~)0.002s (+6.2% 🔺)1.011s (~)0.806s101.16x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)1.554s (-77.3% 🟢)2.748s (-68.2% 🟢)0.996s (+57.7% 🔺)4.134s (-57.8% 🟢)2.581s101.00x
▲ VercelNitro1.705s (-55.5% 🟢)2.818s (-46.6% 🟢)1.037s (+39.8% 🔺)4.300s (-33.7% 🟢)2.594s101.10x
▲ VercelExpress⚠️missing-----

🔍 Observability: Next.js (Turbopack) | Nitro

stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.531s (-14.9% 🟢)1.008s (~)0.004s (-14.3% 🟢)1.022s (~)0.491s591.00x
🐘 PostgresExpress0.607s (-3.6%)1.006s (~)0.004s (+3.1%)1.023s (~)0.416s591.14x
🐘 PostgresNext.js (Turbopack)0.617s1.008s0.003s1.020s0.402s591.16x
💻 LocalNitro0.742s (-11.6% 🟢)1.012s (~)0.009s (-2.5%)1.023s (-8.3% 🟢)0.281s591.40x
💻 LocalNext.js (Turbopack)0.806s1.011s0.013s1.120s0.313s541.52x
💻 LocalExpress0.956s (+26.2% 🔺)1.012s (-1.6%)0.010s (+5.4% 🔺)1.229s (+18.2% 🔺)0.273s491.80x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro4.889s (-83.4% 🟢)6.748s (-78.1% 🟢)0.465s (+315.1% 🔺)7.635s (-76.0% 🟢)2.746s81.00x
▲ VercelNext.js (Turbopack)14.674s (-13.3% 🟢)15.526s (-14.9% 🟢)0.211s (~)16.076s (-15.1% 🟢)1.403s53.00x
▲ VercelExpress⚠️missing-----

🔍 Observability: Nitro | Next.js (Turbopack)

10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.938s1.112s0.000s1.119s0.182s541.00x
🐘 PostgresNitro0.944s (-2.6%)1.177s (-5.7% 🟢)0.000s (+41.2% 🔺)1.190s (-5.4% 🟢)0.246s511.01x
🐘 PostgresExpress0.974s (+1.4%)1.219s (-4.6%)0.000s (+87.8% 🔺)1.243s (-4.9%)0.269s491.04x
💻 LocalNitro1.214s (-0.7%)2.021s (~)0.000s (+33.3% 🔺)2.022s (~)0.808s301.30x
💻 LocalExpress1.238s (+1.0%)2.020s (~)0.000s (-10.0% 🟢)2.022s (~)0.785s301.32x
💻 LocalNext.js (Turbopack)1.296s2.019s0.000s2.023s0.727s301.38x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro6.050s (+98.3% 🔺)7.665s (+74.5% 🔺)0.000s (-100.0% 🟢)8.112s (+68.7% 🔺)2.062s81.00x
▲ VercelNext.js (Turbopack)7.695s (-24.4% 🟢)7.641s (-33.7% 🟢)0.000s (NaN%)9.028s (-25.1% 🟢)1.333s71.27x
▲ VercelExpress⚠️missing-----

🔍 Observability: Nitro | Next.js (Turbopack)

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

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.720s (-4.0%)2.104s (-1.7%)0.000s (+93.1% 🔺)2.112s (-2.9%)0.392s291.00x
🐘 PostgresExpress1.727s (-2.5%)2.104s (-3.4%)0.000s (NaN%)2.113s (-3.9%)0.386s291.00x
🐘 PostgresNext.js (Turbopack)1.888s2.182s0.000s2.189s0.301s281.10x
💻 LocalNitro3.502s (+3.4%)4.035s (~)0.001s (+50.0% 🔺)4.038s (~)0.536s152.04x
💻 LocalExpress3.589s (+3.5%)4.030s (~)0.000s (-58.3% 🟢)4.033s (~)0.444s152.09x
💻 LocalNext.js (Turbopack)3.746s4.166s0.000s4.170s0.424s152.18x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)5.451s (-3.0%)6.756s (-3.2%)0.000s (-100.0% 🟢)7.096s (-5.9% 🟢)1.645s91.00x
▲ VercelNitro8.938s (+118.3% 🔺)10.290s (+91.5% 🔺)0.000s (-100.0% 🟢)10.758s (+85.7% 🔺)1.819s61.64x
▲ VercelExpress⚠️missing-----

🔍 Observability: Next.js (Turbopack) | Nitro

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalNext.js (Turbopack)15/21
🐘 PostgresNitro20/21
▲ VercelNitro18/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres18/21
Next.js (Turbopack)🐘 Postgres17/21
Nitro🐘 Postgres19/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

@changeset-bot

changeset-botBot commented Apr 10, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: dc6415b

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

This PR includes changesets to release 18 packages
NameType
@workflow/swc-pluginMajor
@workflow/buildersPatch
@workflow/cliPatch
@workflow/nextPatch
@workflow/rollupPatch
@workflow/nestPatch
@workflow/astroPatch
@workflow/nitroPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/vitestPatch
workflowPatch
@workflow/world-testingPatch
@workflow/nuxtPatch
@workflow/aiPatch
@workflow/corePatch
@workflow/web-sharedPatch
@workflow/webPatch

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

vercelBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

@TooTallNate
TooTallNateforce-pushed the nr/remove-client-mode branch from aac9033 to cf9fe73CompareApril 10, 2026 17:20
Remove the `client` transform mode from the SWC compiler plugin. The
`client` and `step` modes were nearly identical — both preserved step
function bodies, replaced workflow bodies with throw stubs, and emitted
the same JSON manifest. Step mode now absorbs all client-mode behaviors:
- Dead code elimination (previously only workflow + client)
- Hoisted variable references for object property steps
- All integrations use mode: 'step' instead of 'client'
BREAKING CHANGE: The `client` value for the SWC plugin `mode` option is
no longer accepted. Use `step` instead.
…sId registration
In dev mode, Nitro's Rollup externalizes npm packages like @workflow/core,
so the SWC transform plugin never processes files like run.js. This means
serde classes (e.g. Run) never get the classId registration IIFE, causing
serialization failures when step functions return Run instances.
Uses a Rollup resolveId hook to force workflow SDK packages to be bundled
(non-external) while leaving all other dependencies external. This is more
targeted than noExternals=true which bundles everything and causes TDZ
errors from circular imports in packages like vue-bundle-renderer/h3.
The Nitro module now also ignores .nitro/workflow/** in watchOptions so
writing generated workflow bundles does not retrigger Nitro's own dev
bundle rebuild loop.
Also wraps dev:reload workflow rebuilds and makes LocalBuilder.build()
atomic (writes to temp files, renames on success) to avoid partial output
state during HMR.
For Nuxt, also configures Vite's ssr.noExternal to bundle workflow
packages in the SSR context.

CopilotAI left a comment

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.

Pull request overview

Removes the SWC plugin’s client transform mode by merging its behavior into step mode, and updates all repository integrations, docs, and fixtures to use the new 3-mode model (Step/Workflow/Detect).

Changes:

  • Dropped Client from TransformMode, updated step mode to include client-mode behaviors (notably DCE + object-property hoisting semantics), and removed client-mode fixture runners/outputs.
  • Updated framework/tooling integrations (Next loader, Rollup, Nest CLI, Builders, CLI) to use mode: 'step' everywhere client was previously used.
  • Updated docs/spec and the SWC playground (WASM + UI/types) to remove the client output/view.

Reviewed changes

Copilot reviewed 103 out of 103 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
workbench/swc-playground/wasm/src/lib.rsRemoves client from batch transform output and runs only workflow+step.
workbench/swc-playground/lib/transform.tsUpdates TS types to drop client transform result.
workbench/swc-playground/components/swc-playground.tsxRemoves client view/panel/state in the playground UI.
packages/swc-plugin-workflow/transform/src/lib.rsRemoves Client mode and folds client behaviors into Step (DCE, hoisting/registration paths, etc.).
packages/swc-plugin-workflow/spec.mdUpdates specification to reflect 3 modes and step-mode DCE/hoisting behavior.
packages/swc-plugin-workflow/transform/tests/fixture.rsRemoves the client-mode fixture test harness.
packages/swc-plugin-workflow/transform/tests/errors.rsRemoves the client-mode errors fixture harness and updates imports.
packages/swc-plugin-workflow/transform/tests/fixture/workflow-client-property/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/workflow-arrow-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/var-named-step-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/using-declaration-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/using-declaration-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/user-named-dunder-default/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/unused-variables-and-types/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/unused-variables-and-types/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/unused-exports/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/unused-exports/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step/output-step.jsUpdates step-mode fixture to reflect new object-property hoisting behavior.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step-default-export/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step-class/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/step-with-this-arguments-super/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/step-with-imports/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/step-with-imports/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/step-arrow-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/static-method-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/static-method-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/static-getter-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/single-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/single-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/separate-export-statement/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/private-member-dce/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/private-member-dce-native/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/object-property-step/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/object-property-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/object-getter-step/output-step.jsUpdates step-mode fixture to reflect object getter/property behavior.
packages/swc-plugin-workflow/transform/tests/fixture/object-getter-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/nested-steps-in-object-constructor/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/nested-steps-in-object-constructor/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/nested-step-with-closure/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/nested-step-with-closure/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/nested-step-in-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/multiple-const-step-functions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-workflow/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-step/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/mixed-functions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/let-arrow-step-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/instance-method-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/instance-method-nested-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/instance-getter-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/expr-fn-default-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-named/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-anonymous/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-anonymous-step-only/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/destructuring/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/default-workflow-collision/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/output-workflow.jsUpdates fixture to reflect export changes under new behavior.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/output-step.jsUpdates fixture to reflect export changes under new behavior.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/input.jsUpdates input fixture to be exported (aligning outputs).
packages/swc-plugin-workflow/transform/tests/fixture/default-arrow-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/deeply-nested-step/output-step.jsUpdates step-mode fixture to reflect hoisted reference usage.
packages/swc-plugin-workflow/transform/tests/fixture/deeply-nested-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-require-namespace/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-require-destructured/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-local-const/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-imported/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/closure-typescript-expressions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/closure-new-expr-and-module-declarations/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/class-expression-binding-name/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/class-expression-binding-name-step-methods/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/anonymous-default-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step-shorthand-method/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step-shorthand-method/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/sync-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/non-async-functions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misspelled-workflow-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misspelled-step-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misplaced-module-directive/output-step.jsUpdates step-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misplaced-module-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misplaced-function-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/invalid-exports/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/invalid-default-exports-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/instance-methods/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/getter-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/next/src/loader.tsSwitches all transforms to mode: 'step'.
packages/rollup/src/index.tsSwitches Rollup integration transform mode to step.
packages/nest/src/cli.tsUpdates generated .swcrc to use mode: 'step' and help text accordingly.
packages/cli/src/commands/transform.tsRemoves client from CLI transform modes/options.
packages/builders/src/apply-swc-transform.tsUpdates API type to drop client mode.
packages/builders/src/swc-esbuild-plugin.tsUpdates SwcPluginOptions.mode type to drop client.
packages/builders/src/base-builder.tsUpdates builder SWC plugin usage from client to step.
packages/nuxt/src/module.tsForces Vite SSR bundling behavior for workflow packages and marks _vite for Nitro.
packages/nitro/src/index.tsAdds dev-only rollup force-inline plugin and dev-time dynamic loading of generated workflow bundles.
packages/nitro/src/builders.tsWrites workflow bundles to temp files first and renames into place.
.changeset/remove-client-mode.mdAdds changeset documenting the breaking removal of client mode and migration guidance.

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

Comment threadpackages/nitro/src/builders.ts Outdated
Comment threadpackages/nuxt/src/module.ts Outdated
Comment threadpackages/nitro/src/index.ts Outdated
- nitro builders: use crypto.randomUUID() for temp file suffix instead of
Date.now() to avoid collisions under rapid/concurrent build() calls,
and serialize concurrent build() calls through an internal queue so
two overlapping dev rebuilds cannot clobber each other's temp outputs.
- nitro index: use fileURLToPath() to convert file:// URLs to filesystem
paths, which correctly handles Windows paths (file:///C:/... -> C:\...)
and percent-decoding, instead of relying on new URL(...).pathname.
- nuxt module: normalize vite.ssr.noExternal to an array (preserving any
existing string/RegExp/array entry) before appending workflow package
matchers, so the force-bundle behavior is not a no-op when noExternal
is already set to a non-array value.

@VaguelySeriousVaguelySerious left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM assuming tests pass, we're only landing this on v5 right?

@TooTallNate

Copy link
Copy Markdown
MemberAuthor

@VaguelySerious correct

Sign up for freeto 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

@TooTallNate@ijjk@VaguelySerious
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

refactor(swc-plugin): remove client transform mode, merge into step mode - #1686

Merged
TooTallNate merged 3 commits into
mainfrom
nr/remove-client-mode
Apr 16, 2026
Merged

refactor(swc-plugin): remove client transform mode, merge into step mode#1686
TooTallNate merged 3 commits into
mainfrom
nr/remove-client-mode

Conversation

@TooTallNate

@TooTallNateTooTallNate commented Apr 10, 2026

Copy link
Copy Markdown
Member

Summary

  • Remove the client transform mode from the SWC compiler plugin, merging it into step mode
  • The plugin now has 3 modes (Step, Workflow, Detect) instead of 4
  • All integrations that previously used mode: 'client' now use mode: 'step'

Motivation

The client and step modes were nearly identical — both preserved step function bodies, replaced workflow bodies with throw stubs, and emitted the same JSON manifest. The only differences were:

  1. Registration mechanism: client used a simple .stepId property assignment; step used an IIFE with global Map registration
  2. Dead code elimination: client ran DCE; step did not
  3. Object property step call sites: client replaced inline functions with hoisted variable references; step kept the original inline copy

None of these differences were fundamentally necessary. Merging them simplifies the codebase by ~450 lines of Rust and removes 67 test fixture files.

What changed in step mode

  • DCE now runs — removes dead code just like it did in client mode, preserving step bodies and their dependencies
  • Object property steps use hoisted variable references at call sites so .stepId is accessible on the same function object
  • IIFE registration is unchanged — all step functions are registered in the global Map

Changed packages

PackageChange
@workflow/swc-pluginRemoved Client variant from TransformMode enum, ~450 lines of client-specific match arms
@workflow/nextloader.ts now always uses mode: 'step'
@workflow/buildersbase-builder.ts, apply-swc-transform.ts, swc-esbuild-plugin.ts — removed 'client' from types and mode values
@workflow/cliRemoved 'client' from transform command options
@workflow/rollupChanged mode: 'client' to mode: 'step'
@workflow/nestChanged mode: 'client' to mode: 'step'
@workflow/swc-playground-wasmRemoved client output from batch transform

@github-actions

github-actionsBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production923067990
✅ 💻 Local Development9940861080
✅ 📦 Local Production9940861080
✅ 🐘 Local Postgres9940861080
✅ 🪟 Windows900090
❌ 🌍 Community Worlds133980231
✅ 📋 Other252018270
Total4380983434821

❌ Failed Tests

🌍 Community Worlds (98 failed)

mongodb (15 failed):

  • readableStreamWorkflow | wrun_01KPC49NNZW9YY0KB64K6VSQHB
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KPC4AC42WBKTER23K36G2ZAT
  • webhookWorkflow | wrun_01KPC4AMQBQNMGQ4RMS3XNMX4K
  • outputStreamWorkflow no startIndex (reads all chunks)
  • outputStreamWorkflow positive startIndex (skips first chunk)
  • outputStreamWorkflow negative startIndex (reads from end)
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns correct index after stream completes
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns -1 before any chunks are written
  • outputStreamWorkflow - getTailIndex and getChunks getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KPC4DTF69CSG9SGAXK101SCA
  • fetchWorkflow | wrun_01KPC4E7RZPD314K6BKBYSXGT0
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KPC4JB5B6GKYQ4NA68WW9JFN
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • health check (CLI) - workflow health command reports healthy endpoints
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KPC4RK5F4H2A50VNYVKYDZYH

redis (15 failed):

  • readableStreamWorkflow | wrun_01KPC49NNZW9YY0KB64K6VSQHB
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KPC4AC42WBKTER23K36G2ZAT
  • webhookWorkflow | wrun_01KPC4AMQBQNMGQ4RMS3XNMX4K
  • outputStreamWorkflow no startIndex (reads all chunks)
  • outputStreamWorkflow positive startIndex (skips first chunk)
  • outputStreamWorkflow negative startIndex (reads from end)
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns correct index after stream completes
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns -1 before any chunks are written
  • outputStreamWorkflow - getTailIndex and getChunks getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KPC4DTF69CSG9SGAXK101SCA
  • fetchWorkflow | wrun_01KPC4E7RZPD314K6BKBYSXGT0
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KPC4JB5B6GKYQ4NA68WW9JFN
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • health check (CLI) - workflow health command reports healthy endpoints
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KPC4RK5F4H2A50VNYVKYDZYH

turso (68 failed):

  • addTenWorkflow | wrun_01KPC494JMXC2S698ZCV0Z1A6J
  • addTenWorkflow | wrun_01KPC494JMXC2S698ZCV0Z1A6J
  • wellKnownAgentWorkflow (.well-known/agent) | wrun_01KPC4AGDR3W8R8RXJT4B0AAA1
  • should work with react rendering in step
  • promiseAllWorkflow | wrun_01KPC49C06JB8S19BQWT39ZGY3
  • promiseRaceWorkflow | wrun_01KPC49GDW34C2CAXQED5GQ5HD
  • promiseAnyWorkflow | wrun_01KPC49JF67R2674SKNT0B531G
  • importedStepOnlyWorkflow | wrun_01KPC4ATXWJTKEXDX5AZ5QQ00W
  • readableStreamWorkflow | wrun_01KPC49NNZW9YY0KB64K6VSQHB
  • hookWorkflow | wrun_01KPC4A08KB58ENADF0R99QWRK
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KPC4AC42WBKTER23K36G2ZAT
  • webhookWorkflow | wrun_01KPC4AMQBQNMGQ4RMS3XNMX4K
  • sleepingWorkflow | wrun_01KPC4ATTECEVNJQ03J54ZFBVM
  • parallelSleepWorkflow | wrun_01KPC4B757NA7GCQPA911F04ZY
  • nullByteWorkflow | wrun_01KPC4BBA9SENAQ2793T64G2HD
  • workflowAndStepMetadataWorkflow | wrun_01KPC4BD6G7ZV66PGPFA4QPD88
  • outputStreamWorkflow no startIndex (reads all chunks)
  • outputStreamWorkflow positive startIndex (skips first chunk)
  • outputStreamWorkflow negative startIndex (reads from end)
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns correct index after stream completes
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns -1 before any chunks are written
  • outputStreamWorkflow - getTailIndex and getChunks getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KPC4DTF69CSG9SGAXK101SCA
  • fetchWorkflow | wrun_01KPC4E7RZPD314K6BKBYSXGT0
  • promiseRaceStressTestWorkflow | wrun_01KPC4EB2BAVKDBD6MS0ZQ6EA2
  • 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_01KPC4HQX6G61Z1EVG4JNP930D
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KPC4JB5B6GKYQ4NA68WW9JFN
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KPC4JYZ7FS1R557Y32RKYX4X
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KPC4KHC0489EJS7TH6H8C1FP
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_01KPC4KSEB6GVW9G0XXRPWE3J8
  • closureVariableWorkflow - nested step functions with closure variables | wrun_01KPC4KYK1XY4DHRRTHJ2T1M21
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_01KPC4M0KZH3ASYEG5R6JBWENC
  • runClassSerializationWorkflow - Run instances serialize across workflow/step boundaries | wrun_01KPC4MB45KDRW8N8D6WN06XEQ
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • health check (CLI) - workflow health command reports healthy endpoints
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_01KPC4MS5KHDWDK2F94N22ZFQW
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_01KPC4MZ6PEQNSM56KWF9FJX1E
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_01KPC4N5GZH4ZFPZPW62YEP6KV
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_01KPC4NBR68W7CSHPE7R7M4EK3
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_01KPC4NHS0ARKDVB77N2MX3CAC
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_01KPC4NQW6FWS4MXN0R48DA026
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_01KPC4NZ0FPXKMQX3X2CQ04PBG
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_01KPC4P9N2G26Q97QRYDQ0Y9YK
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_01KPC4PGZWQE4GQXWWGY0QH4J7
  • cancelRun - cancelling a running workflow | wrun_01KPC4PR5VZ7PAPEH1FB5DTEBH
  • cancelRun via CLI - cancelling a running workflow | wrun_01KPC4Q0WDH365KZXRFP7S3YXX
  • 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_01KPC4QC7VC0XAK4HG5DG72TYK
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KPC4QZCT792E4TFQ8YN5Q6BV
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KPC4R9ARDE36CTKSVKBD0BV7
  • importMetaUrlWorkflow - import.meta.url is available in step bundles | wrun_01KPC4RF7T0AJ9JST4ZEVXQBYY
  • metadataFromHelperWorkflow - getWorkflowMetadata/getStepMetadata work from module-level helper (#1577) | wrun_01KPC4RH3HCX2FND5E2Q3889HY
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KPC4RK5F4H2A50VNYVKYDZYH
  • getterStepWorkflow - getter functions with "use step" directive | wrun_01KPC4RP4RG6MQ9C0QJJXPXG6F

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro8307
✅ example8307
✅ express8307
✅ fastify8307
✅ hono8307
✅ nextjs-turbopack8802
✅ nextjs-webpack8802
✅ nitro8307
✅ nuxt8307
✅ sveltekit8307
✅ vite8307
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable8406
✅ express-stable8406
✅ fastify-stable8406
✅ hono-stable8406
✅ nextjs-turbopack-canary71019
✅ nextjs-turbopack-stable9000
✅ nextjs-webpack-canary71019
✅ nextjs-webpack-stable9000
✅ nitro-stable8406
✅ nuxt-stable8406
✅ sveltekit-stable8406
✅ vite-stable8406
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable8406
✅ express-stable8406
✅ fastify-stable8406
✅ hono-stable8406
✅ nextjs-turbopack-canary71019
✅ nextjs-turbopack-stable9000
✅ nextjs-webpack-canary71019
✅ nextjs-webpack-stable9000
✅ nitro-stable8406
✅ nuxt-stable8406
✅ sveltekit-stable8406
✅ vite-stable8406
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable8406
✅ express-stable8406
✅ fastify-stable8406
✅ hono-stable8406
✅ nextjs-turbopack-canary71019
✅ nextjs-turbopack-stable9000
✅ nextjs-webpack-canary71019
✅ nextjs-webpack-stable9000
✅ nitro-stable8406
✅ nuxt-stable8406
✅ sveltekit-stable8406
✅ vite-stable8406
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack9000
❌ 🌍 Community Worlds
AppPassedFailedSkipped
✅ mongodb-dev600
❌ mongodb56150
✅ redis-dev600
❌ redis56150
✅ turso-dev600
❌ turso3680
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable8406
✅ e2e-local-postgres-nest-stable8406
✅ e2e-local-prod-nest-stable8406

📋 View full workflow run

@github-actions

github-actionsBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

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

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express0.044s (-0.9%)1.005s (~)0.961s101.00x
💻 LocalNitro0.044s (+1.9%)1.005s (~)0.961s101.00x
💻 LocalNext.js (Turbopack)0.047s1.005s0.958s101.08x
🐘 PostgresNitro0.053s (-44.2% 🟢)1.011s (-3.1%)0.957s101.21x
🐘 PostgresNext.js (Turbopack)0.056s1.010s0.954s101.27x
🐘 PostgresExpress0.057s (-1.6%)1.011s (~)0.954s101.30x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro0.232s (-43.5% 🟢)2.120s (-15.5% 🟢)1.888s101.00x
▲ VercelNext.js (Turbopack)0.265s (+5.5% 🔺)2.026s (-13.2% 🟢)1.760s101.15x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Next.js (Turbopack)1.122s2.006s0.884s101.00x
🐘 PostgresNitro1.124s (-1.4%)2.009s (~)0.885s101.00x
💻 LocalNitro1.131s (~)2.006s (~)0.875s101.01x
💻 LocalExpress1.134s (+0.8%)2.007s (~)0.872s101.01x
🐘 PostgresNext.js (Turbopack)1.136s2.011s0.875s101.01x
🐘 PostgresExpress1.154s (+0.6%)2.010s (~)0.856s101.03x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro1.948s (-50.0% 🟢)3.730s (-36.9% 🟢)1.782s101.00x
▲ VercelNext.js (Turbopack)1.978s (-2.8%)3.253s (-15.1% 🟢)1.275s101.02x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro10.738s (-1.2%)11.025s (~)0.287s31.00x
💻 LocalNext.js (Turbopack)10.830s11.023s0.193s31.01x
🐘 PostgresExpress10.894s (-0.6%)11.025s (~)0.131s31.01x
💻 LocalNitro10.920s (~)11.022s (~)0.102s31.02x
🐘 PostgresNext.js (Turbopack)10.927s11.018s0.091s31.02x
💻 LocalExpress10.947s (~)11.024s (~)0.078s31.02x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro17.104s (-27.9% 🟢)19.463s (-22.5% 🟢)2.360s21.00x
▲ VercelNext.js (Turbopack)17.338s (~)18.457s (-4.9%)1.119s21.01x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro14.143s (-3.1%)15.027s (~)0.884s41.00x
🐘 PostgresNext.js (Turbopack)14.476s15.029s0.553s41.02x
💻 LocalNext.js (Turbopack)14.575s15.028s0.454s41.03x
🐘 PostgresExpress14.575s (~)15.026s (~)0.451s41.03x
💻 LocalNitro14.924s (-0.9%)15.029s (-6.2% 🟢)0.104s41.06x
💻 LocalExpress15.108s (+0.9%)16.032s (+6.7% 🔺)0.924s41.07x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro32.373s (-49.8% 🟢)34.553s (-48.1% 🟢)2.179s21.00x
▲ VercelNext.js (Turbopack)33.318s (-36.6% 🟢)34.394s (-37.0% 🟢)1.076s21.03x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro13.235s (-5.2% 🟢)13.880s (-3.0%)0.645s71.00x
🐘 PostgresExpress13.877s (-0.9%)14.022s (-3.9%)0.145s71.05x
🐘 PostgresNext.js (Turbopack)13.974s14.455s0.481s71.06x
💻 LocalNext.js (Turbopack)15.884s16.196s0.312s61.20x
💻 LocalNitro16.479s (-1.8%)17.030s (~)0.552s61.25x
💻 LocalExpress16.807s (+1.2%)17.031s (~)0.224s61.27x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro55.193s (-86.9% 🟢)57.639s (-86.4% 🟢)2.446s21.00x
▲ VercelNext.js (Turbopack)59.836s (-84.8% 🟢)60.966s (-84.6% 🟢)1.130s21.08x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.223s (-4.1%)2.009s (~)0.787s151.00x
🐘 PostgresExpress1.251s (-0.8%)2.010s (~)0.760s151.02x
🐘 PostgresNext.js (Turbopack)1.252s2.009s0.756s151.02x
💻 LocalNext.js (Turbopack)1.488s2.005s0.517s151.22x
💻 LocalNitro1.498s (-8.2% 🟢)2.006s (-3.3%)0.507s151.23x
💻 LocalExpress1.528s (+2.6%)2.006s (~)0.477s151.25x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.389s (-15.2% 🟢)3.777s (-12.6% 🟢)1.388s91.00x
▲ VercelNext.js (Turbopack)2.457s (-27.7% 🟢)3.702s (-25.0% 🟢)1.244s91.03x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro2.320s (-1.3%)3.009s (~)0.689s101.00x
🐘 PostgresExpress2.335s (-1.1%)3.008s (~)0.674s101.01x
🐘 PostgresNext.js (Turbopack)2.393s3.010s0.617s101.03x
💻 LocalNext.js (Turbopack)2.874s3.309s0.435s101.24x
💻 LocalNitro2.898s (-7.8% 🟢)3.453s (-11.1% 🟢)0.555s91.25x
💻 LocalExpress3.040s (+3.0%)3.759s (+8.8% 🔺)0.719s81.31x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.873s (-29.1% 🟢)4.645s (-21.5% 🟢)1.772s71.00x
▲ VercelNext.js (Turbopack)3.637s (-48.8% 🟢)5.185s (-41.8% 🟢)1.548s61.27x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro3.426s (-1.5%)4.010s (~)0.583s81.00x
🐘 PostgresExpress3.459s (-0.8%)4.010s (~)0.551s81.01x
🐘 PostgresNext.js (Turbopack)3.689s4.010s0.321s81.08x
💻 LocalNext.js (Turbopack)7.497s8.019s0.522s42.19x
💻 LocalNitro8.051s (-3.6%)8.772s (-2.8%)0.721s42.35x
💻 LocalExpress8.203s (-1.6%)9.020s (~)0.817s42.39x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro3.559s (+1.0%)5.051s (-8.7% 🟢)1.492s61.00x
▲ VercelNext.js (Turbopack)6.803s (-23.7% 🟢)8.029s (-26.7% 🟢)1.226s41.91x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.209s (-3.8%)2.009s (~)0.800s151.00x
🐘 PostgresNext.js (Turbopack)1.228s2.010s0.782s151.02x
🐘 PostgresExpress1.267s (+0.8%)2.008s (~)0.741s151.05x
💻 LocalNitro1.515s (-18.8% 🟢)2.005s (-14.3% 🟢)0.490s151.25x
💻 LocalNext.js (Turbopack)1.531s2.006s0.475s151.27x
💻 LocalExpress1.544s (-18.5% 🟢)2.006s (-15.1% 🟢)0.462s151.28x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.037s (-17.2% 🟢)3.718s (-10.8% 🟢)1.681s91.00x
▲ VercelNext.js (Turbopack)2.401s (-18.1% 🟢)3.792s (-18.3% 🟢)1.391s81.18x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro2.327s (-0.5%)3.010s (~)0.683s101.00x
🐘 PostgresExpress2.336s (~)3.010s (~)0.674s101.00x
🐘 PostgresNext.js (Turbopack)2.393s3.008s0.616s101.03x
💻 LocalNext.js (Turbopack)2.787s3.452s0.665s91.20x
💻 LocalNitro2.836s (-7.5% 🟢)3.309s (-14.9% 🟢)0.473s101.22x
💻 LocalExpress3.261s (+4.1%)4.011s (+6.6% 🔺)0.750s81.40x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.598s (-19.7% 🟢)4.042s (-20.4% 🟢)1.444s81.00x
▲ VercelNext.js (Turbopack)2.787s (-11.3% 🟢)4.209s (-6.9% 🟢)1.422s81.07x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro3.456s (-0.7%)4.011s (~)0.555s81.00x
🐘 PostgresExpress3.480s (-0.5%)4.010s (~)0.530s81.01x
🐘 PostgresNext.js (Turbopack)3.617s4.012s0.395s81.05x
💻 LocalNext.js (Turbopack)7.510s8.018s0.507s42.17x
💻 LocalNitro8.662s (-5.3% 🟢)9.275s (-7.5% 🟢)0.613s42.51x
💻 LocalExpress8.993s (+2.2%)9.273s (~)0.279s42.60x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.764s (-45.7% 🟢)4.520s (-33.7% 🟢)1.756s71.00x
▲ VercelNext.js (Turbopack)4.827s (-28.6% 🟢)6.399s (-25.1% 🟢)1.572s51.75x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.624s (-23.9% 🟢)1.006s (~)0.382s601.00x
🐘 PostgresNext.js (Turbopack)0.786s1.023s0.237s591.26x
🐘 PostgresExpress0.808s (-3.7%)1.022s (~)0.214s591.29x
💻 LocalNext.js (Turbopack)0.852s1.039s0.187s581.36x
💻 LocalNitro0.988s (+0.8%)1.158s (+5.9% 🔺)0.170s521.58x
💻 LocalExpress0.989s (~)1.250s (+16.1% 🔺)0.261s491.58x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro10.124s (-54.1% 🟢)12.026s (-49.9% 🟢)1.902s51.00x
▲ VercelNext.js (Turbopack)11.473s (-20.9% 🟢)12.880s (-19.9% 🟢)1.407s51.13x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.503s (-22.0% 🟢)2.007s (-4.4%)0.504s451.00x
🐘 PostgresExpress1.918s (-3.0%)2.100s (-7.0% 🟢)0.183s431.28x
🐘 PostgresNext.js (Turbopack)1.959s2.203s0.244s411.30x
💻 LocalNext.js (Turbopack)2.627s3.008s0.381s301.75x
💻 LocalNitro3.004s (-1.0%)3.508s (-6.7% 🟢)0.504s262.00x
💻 LocalExpress3.039s (+0.8%)3.690s (+2.9%)0.651s252.02x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)32.147s (-35.5% 🟢)33.634s (-35.0% 🟢)1.487s31.00x
▲ VercelNitro37.762s (-4.4%)39.759s (-3.7%)1.997s31.17x
▲ VercelExpress⚠️missing----

🔍 Observability: Next.js (Turbopack) | Nitro

workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro3.164s (-22.9% 🟢)3.824s (-16.9% 🟢)0.660s321.00x
🐘 PostgresNext.js (Turbopack)3.883s4.147s0.264s291.23x
🐘 PostgresExpress3.890s (-2.5%)4.110s (-5.9% 🟢)0.219s301.23x
💻 LocalNext.js (Turbopack)8.566s9.018s0.452s142.71x
💻 LocalExpress9.269s (+0.6%)10.019s (~)0.749s122.93x
💻 LocalNitro9.497s (+2.1%)10.101s (+0.8%)0.604s123.00x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro77.978s (-19.5% 🟢)79.827s (-18.9% 🟢)1.850s21.00x
▲ VercelNext.js (Turbopack)89.255s (-16.7% 🟢)90.555s (-16.9% 🟢)1.300s21.14x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.235s (-16.9% 🟢)1.007s (~)0.772s601.00x
🐘 PostgresNext.js (Turbopack)0.256s1.008s0.751s601.09x
🐘 PostgresExpress0.285s (+0.8%)1.007s (~)0.723s601.21x
💻 LocalNext.js (Turbopack)0.575s1.004s0.430s602.44x
💻 LocalExpress0.615s (+9.8% 🔺)1.022s (+1.7%)0.407s592.61x
💻 LocalNitro0.668s (+10.5% 🔺)1.095s (+7.2% 🔺)0.427s552.84x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro1.858s (+11.9% 🔺)3.442s (+2.7%)1.584s181.00x
▲ VercelNext.js (Turbopack)5.248s (+159.5% 🔺)6.681s (+76.1% 🔺)1.432s92.82x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.383s (-22.8% 🟢)1.006s (~)0.623s901.00x
🐘 PostgresExpress0.488s (-4.2%)1.007s (~)0.519s901.27x
🐘 PostgresNext.js (Turbopack)0.503s1.007s0.503s901.31x
💻 LocalNitro2.463s (-3.0%)3.009s (~)0.546s306.43x
💻 LocalExpress2.591s (+3.1%)3.009s (~)0.418s306.76x
💻 LocalNext.js (Turbopack)2.594s3.008s0.414s306.77x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro5.501s (+70.5% 🔺)7.445s (+54.4% 🔺)1.944s131.00x
▲ VercelNext.js (Turbopack)8.725s (+146.8% 🔺)10.373s (+99.7% 🔺)1.648s91.59x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.614s (-22.3% 🟢)1.007s (~)0.393s1201.00x
🐘 PostgresNext.js (Turbopack)0.800s1.008s0.208s1201.30x
🐘 PostgresExpress0.802s (-2.0%)1.016s (~)0.214s1191.31x
💻 LocalNext.js (Turbopack)10.669s11.392s0.723s1117.38x
💻 LocalNitro10.798s (-3.5%)11.300s (-3.1%)0.501s1117.59x
💻 LocalExpress11.456s (+2.4%)12.032s (+0.8%)0.576s1018.66x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro9.424s (+22.0% 🔺)11.667s (+24.1% 🔺)2.243s111.00x
▲ VercelNext.js (Turbopack)15.660s (+51.6% 🔺)16.985s (+38.2% 🔺)1.325s81.66x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.177s (-13.8% 🟢)0.997s (~)0.001s (-20.0% 🟢)1.011s (~)0.834s101.00x
💻 LocalNext.js (Turbopack)0.188s1.003s0.011s1.017s0.830s101.06x
🐘 PostgresNext.js (Turbopack)0.192s1.001s0.002s1.011s0.818s101.09x
💻 LocalNitro0.201s (-6.2% 🟢)1.004s (~)0.011s (-9.6% 🟢)1.017s (~)0.817s101.13x
💻 LocalExpress0.204s (+2.5%)1.004s (~)0.013s (+8.3% 🔺)1.020s (~)0.816s101.15x
🐘 PostgresExpress0.204s (~)1.001s (~)0.002s (+6.2% 🔺)1.011s (~)0.806s101.16x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)1.554s (-77.3% 🟢)2.748s (-68.2% 🟢)0.996s (+57.7% 🔺)4.134s (-57.8% 🟢)2.581s101.00x
▲ VercelNitro1.705s (-55.5% 🟢)2.818s (-46.6% 🟢)1.037s (+39.8% 🔺)4.300s (-33.7% 🟢)2.594s101.10x
▲ VercelExpress⚠️missing-----

🔍 Observability: Next.js (Turbopack) | Nitro

stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.531s (-14.9% 🟢)1.008s (~)0.004s (-14.3% 🟢)1.022s (~)0.491s591.00x
🐘 PostgresExpress0.607s (-3.6%)1.006s (~)0.004s (+3.1%)1.023s (~)0.416s591.14x
🐘 PostgresNext.js (Turbopack)0.617s1.008s0.003s1.020s0.402s591.16x
💻 LocalNitro0.742s (-11.6% 🟢)1.012s (~)0.009s (-2.5%)1.023s (-8.3% 🟢)0.281s591.40x
💻 LocalNext.js (Turbopack)0.806s1.011s0.013s1.120s0.313s541.52x
💻 LocalExpress0.956s (+26.2% 🔺)1.012s (-1.6%)0.010s (+5.4% 🔺)1.229s (+18.2% 🔺)0.273s491.80x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro4.889s (-83.4% 🟢)6.748s (-78.1% 🟢)0.465s (+315.1% 🔺)7.635s (-76.0% 🟢)2.746s81.00x
▲ VercelNext.js (Turbopack)14.674s (-13.3% 🟢)15.526s (-14.9% 🟢)0.211s (~)16.076s (-15.1% 🟢)1.403s53.00x
▲ VercelExpress⚠️missing-----

🔍 Observability: Nitro | Next.js (Turbopack)

10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.938s1.112s0.000s1.119s0.182s541.00x
🐘 PostgresNitro0.944s (-2.6%)1.177s (-5.7% 🟢)0.000s (+41.2% 🔺)1.190s (-5.4% 🟢)0.246s511.01x
🐘 PostgresExpress0.974s (+1.4%)1.219s (-4.6%)0.000s (+87.8% 🔺)1.243s (-4.9%)0.269s491.04x
💻 LocalNitro1.214s (-0.7%)2.021s (~)0.000s (+33.3% 🔺)2.022s (~)0.808s301.30x
💻 LocalExpress1.238s (+1.0%)2.020s (~)0.000s (-10.0% 🟢)2.022s (~)0.785s301.32x
💻 LocalNext.js (Turbopack)1.296s2.019s0.000s2.023s0.727s301.38x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro6.050s (+98.3% 🔺)7.665s (+74.5% 🔺)0.000s (-100.0% 🟢)8.112s (+68.7% 🔺)2.062s81.00x
▲ VercelNext.js (Turbopack)7.695s (-24.4% 🟢)7.641s (-33.7% 🟢)0.000s (NaN%)9.028s (-25.1% 🟢)1.333s71.27x
▲ VercelExpress⚠️missing-----

🔍 Observability: Nitro | Next.js (Turbopack)

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

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.720s (-4.0%)2.104s (-1.7%)0.000s (+93.1% 🔺)2.112s (-2.9%)0.392s291.00x
🐘 PostgresExpress1.727s (-2.5%)2.104s (-3.4%)0.000s (NaN%)2.113s (-3.9%)0.386s291.00x
🐘 PostgresNext.js (Turbopack)1.888s2.182s0.000s2.189s0.301s281.10x
💻 LocalNitro3.502s (+3.4%)4.035s (~)0.001s (+50.0% 🔺)4.038s (~)0.536s152.04x
💻 LocalExpress3.589s (+3.5%)4.030s (~)0.000s (-58.3% 🟢)4.033s (~)0.444s152.09x
💻 LocalNext.js (Turbopack)3.746s4.166s0.000s4.170s0.424s152.18x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)5.451s (-3.0%)6.756s (-3.2%)0.000s (-100.0% 🟢)7.096s (-5.9% 🟢)1.645s91.00x
▲ VercelNitro8.938s (+118.3% 🔺)10.290s (+91.5% 🔺)0.000s (-100.0% 🟢)10.758s (+85.7% 🔺)1.819s61.64x
▲ VercelExpress⚠️missing-----

🔍 Observability: Next.js (Turbopack) | Nitro

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalNext.js (Turbopack)15/21
🐘 PostgresNitro20/21
▲ VercelNitro18/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres18/21
Next.js (Turbopack)🐘 Postgres17/21
Nitro🐘 Postgres19/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

@changeset-bot

changeset-botBot commented Apr 10, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: dc6415b

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

This PR includes changesets to release 18 packages
NameType
@workflow/swc-pluginMajor
@workflow/buildersPatch
@workflow/cliPatch
@workflow/nextPatch
@workflow/rollupPatch
@workflow/nestPatch
@workflow/astroPatch
@workflow/nitroPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/vitestPatch
workflowPatch
@workflow/world-testingPatch
@workflow/nuxtPatch
@workflow/aiPatch
@workflow/corePatch
@workflow/web-sharedPatch
@workflow/webPatch

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

vercelBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

@TooTallNate
TooTallNateforce-pushed the nr/remove-client-mode branch from aac9033 to cf9fe73CompareApril 10, 2026 17:20
Remove the `client` transform mode from the SWC compiler plugin. The
`client` and `step` modes were nearly identical — both preserved step
function bodies, replaced workflow bodies with throw stubs, and emitted
the same JSON manifest. Step mode now absorbs all client-mode behaviors:
- Dead code elimination (previously only workflow + client)
- Hoisted variable references for object property steps
- All integrations use mode: 'step' instead of 'client'
BREAKING CHANGE: The `client` value for the SWC plugin `mode` option is
no longer accepted. Use `step` instead.
…sId registration
In dev mode, Nitro's Rollup externalizes npm packages like @workflow/core,
so the SWC transform plugin never processes files like run.js. This means
serde classes (e.g. Run) never get the classId registration IIFE, causing
serialization failures when step functions return Run instances.
Uses a Rollup resolveId hook to force workflow SDK packages to be bundled
(non-external) while leaving all other dependencies external. This is more
targeted than noExternals=true which bundles everything and causes TDZ
errors from circular imports in packages like vue-bundle-renderer/h3.
The Nitro module now also ignores .nitro/workflow/** in watchOptions so
writing generated workflow bundles does not retrigger Nitro's own dev
bundle rebuild loop.
Also wraps dev:reload workflow rebuilds and makes LocalBuilder.build()
atomic (writes to temp files, renames on success) to avoid partial output
state during HMR.
For Nuxt, also configures Vite's ssr.noExternal to bundle workflow
packages in the SSR context.

CopilotAI left a comment

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.

Pull request overview

Removes the SWC plugin’s client transform mode by merging its behavior into step mode, and updates all repository integrations, docs, and fixtures to use the new 3-mode model (Step/Workflow/Detect).

Changes:

  • Dropped Client from TransformMode, updated step mode to include client-mode behaviors (notably DCE + object-property hoisting semantics), and removed client-mode fixture runners/outputs.
  • Updated framework/tooling integrations (Next loader, Rollup, Nest CLI, Builders, CLI) to use mode: 'step' everywhere client was previously used.
  • Updated docs/spec and the SWC playground (WASM + UI/types) to remove the client output/view.

Reviewed changes

Copilot reviewed 103 out of 103 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
workbench/swc-playground/wasm/src/lib.rsRemoves client from batch transform output and runs only workflow+step.
workbench/swc-playground/lib/transform.tsUpdates TS types to drop client transform result.
workbench/swc-playground/components/swc-playground.tsxRemoves client view/panel/state in the playground UI.
packages/swc-plugin-workflow/transform/src/lib.rsRemoves Client mode and folds client behaviors into Step (DCE, hoisting/registration paths, etc.).
packages/swc-plugin-workflow/spec.mdUpdates specification to reflect 3 modes and step-mode DCE/hoisting behavior.
packages/swc-plugin-workflow/transform/tests/fixture.rsRemoves the client-mode fixture test harness.
packages/swc-plugin-workflow/transform/tests/errors.rsRemoves the client-mode errors fixture harness and updates imports.
packages/swc-plugin-workflow/transform/tests/fixture/workflow-client-property/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/workflow-arrow-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/var-named-step-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/using-declaration-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/using-declaration-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/user-named-dunder-default/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/unused-variables-and-types/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/unused-variables-and-types/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/unused-exports/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/unused-exports/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step/output-step.jsUpdates step-mode fixture to reflect new object-property hoisting behavior.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step-default-export/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step-class/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/step-with-this-arguments-super/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/step-with-imports/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/step-with-imports/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/step-arrow-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/static-method-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/static-method-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/static-getter-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/single-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/single-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/separate-export-statement/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/private-member-dce/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/private-member-dce-native/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/object-property-step/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/object-property-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/object-getter-step/output-step.jsUpdates step-mode fixture to reflect object getter/property behavior.
packages/swc-plugin-workflow/transform/tests/fixture/object-getter-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/nested-steps-in-object-constructor/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/nested-steps-in-object-constructor/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/nested-step-with-closure/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/nested-step-with-closure/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/nested-step-in-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/multiple-const-step-functions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-workflow/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-step/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/mixed-functions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/let-arrow-step-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/instance-method-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/instance-method-nested-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/instance-getter-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/expr-fn-default-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-named/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-anonymous/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-anonymous-step-only/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/destructuring/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/default-workflow-collision/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/output-workflow.jsUpdates fixture to reflect export changes under new behavior.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/output-step.jsUpdates fixture to reflect export changes under new behavior.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/input.jsUpdates input fixture to be exported (aligning outputs).
packages/swc-plugin-workflow/transform/tests/fixture/default-arrow-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/deeply-nested-step/output-step.jsUpdates step-mode fixture to reflect hoisted reference usage.
packages/swc-plugin-workflow/transform/tests/fixture/deeply-nested-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-require-namespace/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-require-destructured/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-local-const/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-imported/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/closure-typescript-expressions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/closure-new-expr-and-module-declarations/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/class-expression-binding-name/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/class-expression-binding-name-step-methods/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/anonymous-default-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step-shorthand-method/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step-shorthand-method/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/sync-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/non-async-functions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misspelled-workflow-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misspelled-step-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misplaced-module-directive/output-step.jsUpdates step-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misplaced-module-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misplaced-function-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/invalid-exports/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/invalid-default-exports-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/instance-methods/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/getter-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/next/src/loader.tsSwitches all transforms to mode: 'step'.
packages/rollup/src/index.tsSwitches Rollup integration transform mode to step.
packages/nest/src/cli.tsUpdates generated .swcrc to use mode: 'step' and help text accordingly.
packages/cli/src/commands/transform.tsRemoves client from CLI transform modes/options.
packages/builders/src/apply-swc-transform.tsUpdates API type to drop client mode.
packages/builders/src/swc-esbuild-plugin.tsUpdates SwcPluginOptions.mode type to drop client.
packages/builders/src/base-builder.tsUpdates builder SWC plugin usage from client to step.
packages/nuxt/src/module.tsForces Vite SSR bundling behavior for workflow packages and marks _vite for Nitro.
packages/nitro/src/index.tsAdds dev-only rollup force-inline plugin and dev-time dynamic loading of generated workflow bundles.
packages/nitro/src/builders.tsWrites workflow bundles to temp files first and renames into place.
.changeset/remove-client-mode.mdAdds changeset documenting the breaking removal of client mode and migration guidance.

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

Comment threadpackages/nitro/src/builders.ts Outdated
Comment threadpackages/nuxt/src/module.ts Outdated
Comment threadpackages/nitro/src/index.ts Outdated
- nitro builders: use crypto.randomUUID() for temp file suffix instead of
Date.now() to avoid collisions under rapid/concurrent build() calls,
and serialize concurrent build() calls through an internal queue so
two overlapping dev rebuilds cannot clobber each other's temp outputs.
- nitro index: use fileURLToPath() to convert file:// URLs to filesystem
paths, which correctly handles Windows paths (file:///C:/... -> C:\...)
and percent-decoding, instead of relying on new URL(...).pathname.
- nuxt module: normalize vite.ssr.noExternal to an array (preserving any
existing string/RegExp/array entry) before appending workflow package
matchers, so the force-bundle behavior is not a no-op when noExternal
is already set to a non-array value.

@VaguelySeriousVaguelySerious left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM assuming tests pass, we're only landing this on v5 right?

@TooTallNate

Copy link
Copy Markdown
MemberAuthor

@VaguelySerious correct

Sign up for freeto 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

@TooTallNate@ijjk@VaguelySerious
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

refactor(swc-plugin): remove client transform mode, merge into step mode - #1686

Merged
TooTallNate merged 3 commits into
mainfrom
nr/remove-client-mode
Apr 16, 2026
Merged

refactor(swc-plugin): remove client transform mode, merge into step mode#1686
TooTallNate merged 3 commits into
mainfrom
nr/remove-client-mode

Conversation

@TooTallNate

@TooTallNateTooTallNate commented Apr 10, 2026

Copy link
Copy Markdown
Member

Summary

  • Remove the client transform mode from the SWC compiler plugin, merging it into step mode
  • The plugin now has 3 modes (Step, Workflow, Detect) instead of 4
  • All integrations that previously used mode: 'client' now use mode: 'step'

Motivation

The client and step modes were nearly identical — both preserved step function bodies, replaced workflow bodies with throw stubs, and emitted the same JSON manifest. The only differences were:

  1. Registration mechanism: client used a simple .stepId property assignment; step used an IIFE with global Map registration
  2. Dead code elimination: client ran DCE; step did not
  3. Object property step call sites: client replaced inline functions with hoisted variable references; step kept the original inline copy

None of these differences were fundamentally necessary. Merging them simplifies the codebase by ~450 lines of Rust and removes 67 test fixture files.

What changed in step mode

  • DCE now runs — removes dead code just like it did in client mode, preserving step bodies and their dependencies
  • Object property steps use hoisted variable references at call sites so .stepId is accessible on the same function object
  • IIFE registration is unchanged — all step functions are registered in the global Map

Changed packages

PackageChange
@workflow/swc-pluginRemoved Client variant from TransformMode enum, ~450 lines of client-specific match arms
@workflow/nextloader.ts now always uses mode: 'step'
@workflow/buildersbase-builder.ts, apply-swc-transform.ts, swc-esbuild-plugin.ts — removed 'client' from types and mode values
@workflow/cliRemoved 'client' from transform command options
@workflow/rollupChanged mode: 'client' to mode: 'step'
@workflow/nestChanged mode: 'client' to mode: 'step'
@workflow/swc-playground-wasmRemoved client output from batch transform

@github-actions

github-actionsBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production923067990
✅ 💻 Local Development9940861080
✅ 📦 Local Production9940861080
✅ 🐘 Local Postgres9940861080
✅ 🪟 Windows900090
❌ 🌍 Community Worlds133980231
✅ 📋 Other252018270
Total4380983434821

❌ Failed Tests

🌍 Community Worlds (98 failed)

mongodb (15 failed):

  • readableStreamWorkflow | wrun_01KPC49NNZW9YY0KB64K6VSQHB
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KPC4AC42WBKTER23K36G2ZAT
  • webhookWorkflow | wrun_01KPC4AMQBQNMGQ4RMS3XNMX4K
  • outputStreamWorkflow no startIndex (reads all chunks)
  • outputStreamWorkflow positive startIndex (skips first chunk)
  • outputStreamWorkflow negative startIndex (reads from end)
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns correct index after stream completes
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns -1 before any chunks are written
  • outputStreamWorkflow - getTailIndex and getChunks getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KPC4DTF69CSG9SGAXK101SCA
  • fetchWorkflow | wrun_01KPC4E7RZPD314K6BKBYSXGT0
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KPC4JB5B6GKYQ4NA68WW9JFN
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • health check (CLI) - workflow health command reports healthy endpoints
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KPC4RK5F4H2A50VNYVKYDZYH

redis (15 failed):

  • readableStreamWorkflow | wrun_01KPC49NNZW9YY0KB64K6VSQHB
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KPC4AC42WBKTER23K36G2ZAT
  • webhookWorkflow | wrun_01KPC4AMQBQNMGQ4RMS3XNMX4K
  • outputStreamWorkflow no startIndex (reads all chunks)
  • outputStreamWorkflow positive startIndex (skips first chunk)
  • outputStreamWorkflow negative startIndex (reads from end)
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns correct index after stream completes
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns -1 before any chunks are written
  • outputStreamWorkflow - getTailIndex and getChunks getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KPC4DTF69CSG9SGAXK101SCA
  • fetchWorkflow | wrun_01KPC4E7RZPD314K6BKBYSXGT0
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KPC4JB5B6GKYQ4NA68WW9JFN
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • health check (CLI) - workflow health command reports healthy endpoints
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KPC4RK5F4H2A50VNYVKYDZYH

turso (68 failed):

  • addTenWorkflow | wrun_01KPC494JMXC2S698ZCV0Z1A6J
  • addTenWorkflow | wrun_01KPC494JMXC2S698ZCV0Z1A6J
  • wellKnownAgentWorkflow (.well-known/agent) | wrun_01KPC4AGDR3W8R8RXJT4B0AAA1
  • should work with react rendering in step
  • promiseAllWorkflow | wrun_01KPC49C06JB8S19BQWT39ZGY3
  • promiseRaceWorkflow | wrun_01KPC49GDW34C2CAXQED5GQ5HD
  • promiseAnyWorkflow | wrun_01KPC49JF67R2674SKNT0B531G
  • importedStepOnlyWorkflow | wrun_01KPC4ATXWJTKEXDX5AZ5QQ00W
  • readableStreamWorkflow | wrun_01KPC49NNZW9YY0KB64K6VSQHB
  • hookWorkflow | wrun_01KPC4A08KB58ENADF0R99QWRK
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KPC4AC42WBKTER23K36G2ZAT
  • webhookWorkflow | wrun_01KPC4AMQBQNMGQ4RMS3XNMX4K
  • sleepingWorkflow | wrun_01KPC4ATTECEVNJQ03J54ZFBVM
  • parallelSleepWorkflow | wrun_01KPC4B757NA7GCQPA911F04ZY
  • nullByteWorkflow | wrun_01KPC4BBA9SENAQ2793T64G2HD
  • workflowAndStepMetadataWorkflow | wrun_01KPC4BD6G7ZV66PGPFA4QPD88
  • outputStreamWorkflow no startIndex (reads all chunks)
  • outputStreamWorkflow positive startIndex (skips first chunk)
  • outputStreamWorkflow negative startIndex (reads from end)
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns correct index after stream completes
  • outputStreamWorkflow - getTailIndex and getChunks getTailIndex returns -1 before any chunks are written
  • outputStreamWorkflow - getTailIndex and getChunks getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KPC4DTF69CSG9SGAXK101SCA
  • fetchWorkflow | wrun_01KPC4E7RZPD314K6BKBYSXGT0
  • promiseRaceStressTestWorkflow | wrun_01KPC4EB2BAVKDBD6MS0ZQ6EA2
  • 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_01KPC4HQX6G61Z1EVG4JNP930D
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KPC4JB5B6GKYQ4NA68WW9JFN
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KPC4JYZ7FS1R557Y32RKYX4X
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KPC4KHC0489EJS7TH6H8C1FP
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_01KPC4KSEB6GVW9G0XXRPWE3J8
  • closureVariableWorkflow - nested step functions with closure variables | wrun_01KPC4KYK1XY4DHRRTHJ2T1M21
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_01KPC4M0KZH3ASYEG5R6JBWENC
  • runClassSerializationWorkflow - Run instances serialize across workflow/step boundaries | wrun_01KPC4MB45KDRW8N8D6WN06XEQ
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • health check (CLI) - workflow health command reports healthy endpoints
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_01KPC4MS5KHDWDK2F94N22ZFQW
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_01KPC4MZ6PEQNSM56KWF9FJX1E
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_01KPC4N5GZH4ZFPZPW62YEP6KV
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_01KPC4NBR68W7CSHPE7R7M4EK3
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_01KPC4NHS0ARKDVB77N2MX3CAC
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_01KPC4NQW6FWS4MXN0R48DA026
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_01KPC4NZ0FPXKMQX3X2CQ04PBG
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_01KPC4P9N2G26Q97QRYDQ0Y9YK
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_01KPC4PGZWQE4GQXWWGY0QH4J7
  • cancelRun - cancelling a running workflow | wrun_01KPC4PR5VZ7PAPEH1FB5DTEBH
  • cancelRun via CLI - cancelling a running workflow | wrun_01KPC4Q0WDH365KZXRFP7S3YXX
  • 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_01KPC4QC7VC0XAK4HG5DG72TYK
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KPC4QZCT792E4TFQ8YN5Q6BV
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KPC4R9ARDE36CTKSVKBD0BV7
  • importMetaUrlWorkflow - import.meta.url is available in step bundles | wrun_01KPC4RF7T0AJ9JST4ZEVXQBYY
  • metadataFromHelperWorkflow - getWorkflowMetadata/getStepMetadata work from module-level helper (#1577) | wrun_01KPC4RH3HCX2FND5E2Q3889HY
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KPC4RK5F4H2A50VNYVKYDZYH
  • getterStepWorkflow - getter functions with "use step" directive | wrun_01KPC4RP4RG6MQ9C0QJJXPXG6F

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro8307
✅ example8307
✅ express8307
✅ fastify8307
✅ hono8307
✅ nextjs-turbopack8802
✅ nextjs-webpack8802
✅ nitro8307
✅ nuxt8307
✅ sveltekit8307
✅ vite8307
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable8406
✅ express-stable8406
✅ fastify-stable8406
✅ hono-stable8406
✅ nextjs-turbopack-canary71019
✅ nextjs-turbopack-stable9000
✅ nextjs-webpack-canary71019
✅ nextjs-webpack-stable9000
✅ nitro-stable8406
✅ nuxt-stable8406
✅ sveltekit-stable8406
✅ vite-stable8406
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable8406
✅ express-stable8406
✅ fastify-stable8406
✅ hono-stable8406
✅ nextjs-turbopack-canary71019
✅ nextjs-turbopack-stable9000
✅ nextjs-webpack-canary71019
✅ nextjs-webpack-stable9000
✅ nitro-stable8406
✅ nuxt-stable8406
✅ sveltekit-stable8406
✅ vite-stable8406
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable8406
✅ express-stable8406
✅ fastify-stable8406
✅ hono-stable8406
✅ nextjs-turbopack-canary71019
✅ nextjs-turbopack-stable9000
✅ nextjs-webpack-canary71019
✅ nextjs-webpack-stable9000
✅ nitro-stable8406
✅ nuxt-stable8406
✅ sveltekit-stable8406
✅ vite-stable8406
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack9000
❌ 🌍 Community Worlds
AppPassedFailedSkipped
✅ mongodb-dev600
❌ mongodb56150
✅ redis-dev600
❌ redis56150
✅ turso-dev600
❌ turso3680
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable8406
✅ e2e-local-postgres-nest-stable8406
✅ e2e-local-prod-nest-stable8406

📋 View full workflow run

@github-actions

github-actionsBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

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

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express0.044s (-0.9%)1.005s (~)0.961s101.00x
💻 LocalNitro0.044s (+1.9%)1.005s (~)0.961s101.00x
💻 LocalNext.js (Turbopack)0.047s1.005s0.958s101.08x
🐘 PostgresNitro0.053s (-44.2% 🟢)1.011s (-3.1%)0.957s101.21x
🐘 PostgresNext.js (Turbopack)0.056s1.010s0.954s101.27x
🐘 PostgresExpress0.057s (-1.6%)1.011s (~)0.954s101.30x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro0.232s (-43.5% 🟢)2.120s (-15.5% 🟢)1.888s101.00x
▲ VercelNext.js (Turbopack)0.265s (+5.5% 🔺)2.026s (-13.2% 🟢)1.760s101.15x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Next.js (Turbopack)1.122s2.006s0.884s101.00x
🐘 PostgresNitro1.124s (-1.4%)2.009s (~)0.885s101.00x
💻 LocalNitro1.131s (~)2.006s (~)0.875s101.01x
💻 LocalExpress1.134s (+0.8%)2.007s (~)0.872s101.01x
🐘 PostgresNext.js (Turbopack)1.136s2.011s0.875s101.01x
🐘 PostgresExpress1.154s (+0.6%)2.010s (~)0.856s101.03x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro1.948s (-50.0% 🟢)3.730s (-36.9% 🟢)1.782s101.00x
▲ VercelNext.js (Turbopack)1.978s (-2.8%)3.253s (-15.1% 🟢)1.275s101.02x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro10.738s (-1.2%)11.025s (~)0.287s31.00x
💻 LocalNext.js (Turbopack)10.830s11.023s0.193s31.01x
🐘 PostgresExpress10.894s (-0.6%)11.025s (~)0.131s31.01x
💻 LocalNitro10.920s (~)11.022s (~)0.102s31.02x
🐘 PostgresNext.js (Turbopack)10.927s11.018s0.091s31.02x
💻 LocalExpress10.947s (~)11.024s (~)0.078s31.02x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro17.104s (-27.9% 🟢)19.463s (-22.5% 🟢)2.360s21.00x
▲ VercelNext.js (Turbopack)17.338s (~)18.457s (-4.9%)1.119s21.01x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro14.143s (-3.1%)15.027s (~)0.884s41.00x
🐘 PostgresNext.js (Turbopack)14.476s15.029s0.553s41.02x
💻 LocalNext.js (Turbopack)14.575s15.028s0.454s41.03x
🐘 PostgresExpress14.575s (~)15.026s (~)0.451s41.03x
💻 LocalNitro14.924s (-0.9%)15.029s (-6.2% 🟢)0.104s41.06x
💻 LocalExpress15.108s (+0.9%)16.032s (+6.7% 🔺)0.924s41.07x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro32.373s (-49.8% 🟢)34.553s (-48.1% 🟢)2.179s21.00x
▲ VercelNext.js (Turbopack)33.318s (-36.6% 🟢)34.394s (-37.0% 🟢)1.076s21.03x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro13.235s (-5.2% 🟢)13.880s (-3.0%)0.645s71.00x
🐘 PostgresExpress13.877s (-0.9%)14.022s (-3.9%)0.145s71.05x
🐘 PostgresNext.js (Turbopack)13.974s14.455s0.481s71.06x
💻 LocalNext.js (Turbopack)15.884s16.196s0.312s61.20x
💻 LocalNitro16.479s (-1.8%)17.030s (~)0.552s61.25x
💻 LocalExpress16.807s (+1.2%)17.031s (~)0.224s61.27x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro55.193s (-86.9% 🟢)57.639s (-86.4% 🟢)2.446s21.00x
▲ VercelNext.js (Turbopack)59.836s (-84.8% 🟢)60.966s (-84.6% 🟢)1.130s21.08x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.223s (-4.1%)2.009s (~)0.787s151.00x
🐘 PostgresExpress1.251s (-0.8%)2.010s (~)0.760s151.02x
🐘 PostgresNext.js (Turbopack)1.252s2.009s0.756s151.02x
💻 LocalNext.js (Turbopack)1.488s2.005s0.517s151.22x
💻 LocalNitro1.498s (-8.2% 🟢)2.006s (-3.3%)0.507s151.23x
💻 LocalExpress1.528s (+2.6%)2.006s (~)0.477s151.25x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.389s (-15.2% 🟢)3.777s (-12.6% 🟢)1.388s91.00x
▲ VercelNext.js (Turbopack)2.457s (-27.7% 🟢)3.702s (-25.0% 🟢)1.244s91.03x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro2.320s (-1.3%)3.009s (~)0.689s101.00x
🐘 PostgresExpress2.335s (-1.1%)3.008s (~)0.674s101.01x
🐘 PostgresNext.js (Turbopack)2.393s3.010s0.617s101.03x
💻 LocalNext.js (Turbopack)2.874s3.309s0.435s101.24x
💻 LocalNitro2.898s (-7.8% 🟢)3.453s (-11.1% 🟢)0.555s91.25x
💻 LocalExpress3.040s (+3.0%)3.759s (+8.8% 🔺)0.719s81.31x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.873s (-29.1% 🟢)4.645s (-21.5% 🟢)1.772s71.00x
▲ VercelNext.js (Turbopack)3.637s (-48.8% 🟢)5.185s (-41.8% 🟢)1.548s61.27x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro3.426s (-1.5%)4.010s (~)0.583s81.00x
🐘 PostgresExpress3.459s (-0.8%)4.010s (~)0.551s81.01x
🐘 PostgresNext.js (Turbopack)3.689s4.010s0.321s81.08x
💻 LocalNext.js (Turbopack)7.497s8.019s0.522s42.19x
💻 LocalNitro8.051s (-3.6%)8.772s (-2.8%)0.721s42.35x
💻 LocalExpress8.203s (-1.6%)9.020s (~)0.817s42.39x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro3.559s (+1.0%)5.051s (-8.7% 🟢)1.492s61.00x
▲ VercelNext.js (Turbopack)6.803s (-23.7% 🟢)8.029s (-26.7% 🟢)1.226s41.91x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.209s (-3.8%)2.009s (~)0.800s151.00x
🐘 PostgresNext.js (Turbopack)1.228s2.010s0.782s151.02x
🐘 PostgresExpress1.267s (+0.8%)2.008s (~)0.741s151.05x
💻 LocalNitro1.515s (-18.8% 🟢)2.005s (-14.3% 🟢)0.490s151.25x
💻 LocalNext.js (Turbopack)1.531s2.006s0.475s151.27x
💻 LocalExpress1.544s (-18.5% 🟢)2.006s (-15.1% 🟢)0.462s151.28x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.037s (-17.2% 🟢)3.718s (-10.8% 🟢)1.681s91.00x
▲ VercelNext.js (Turbopack)2.401s (-18.1% 🟢)3.792s (-18.3% 🟢)1.391s81.18x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro2.327s (-0.5%)3.010s (~)0.683s101.00x
🐘 PostgresExpress2.336s (~)3.010s (~)0.674s101.00x
🐘 PostgresNext.js (Turbopack)2.393s3.008s0.616s101.03x
💻 LocalNext.js (Turbopack)2.787s3.452s0.665s91.20x
💻 LocalNitro2.836s (-7.5% 🟢)3.309s (-14.9% 🟢)0.473s101.22x
💻 LocalExpress3.261s (+4.1%)4.011s (+6.6% 🔺)0.750s81.40x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.598s (-19.7% 🟢)4.042s (-20.4% 🟢)1.444s81.00x
▲ VercelNext.js (Turbopack)2.787s (-11.3% 🟢)4.209s (-6.9% 🟢)1.422s81.07x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro3.456s (-0.7%)4.011s (~)0.555s81.00x
🐘 PostgresExpress3.480s (-0.5%)4.010s (~)0.530s81.01x
🐘 PostgresNext.js (Turbopack)3.617s4.012s0.395s81.05x
💻 LocalNext.js (Turbopack)7.510s8.018s0.507s42.17x
💻 LocalNitro8.662s (-5.3% 🟢)9.275s (-7.5% 🟢)0.613s42.51x
💻 LocalExpress8.993s (+2.2%)9.273s (~)0.279s42.60x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.764s (-45.7% 🟢)4.520s (-33.7% 🟢)1.756s71.00x
▲ VercelNext.js (Turbopack)4.827s (-28.6% 🟢)6.399s (-25.1% 🟢)1.572s51.75x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.624s (-23.9% 🟢)1.006s (~)0.382s601.00x
🐘 PostgresNext.js (Turbopack)0.786s1.023s0.237s591.26x
🐘 PostgresExpress0.808s (-3.7%)1.022s (~)0.214s591.29x
💻 LocalNext.js (Turbopack)0.852s1.039s0.187s581.36x
💻 LocalNitro0.988s (+0.8%)1.158s (+5.9% 🔺)0.170s521.58x
💻 LocalExpress0.989s (~)1.250s (+16.1% 🔺)0.261s491.58x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro10.124s (-54.1% 🟢)12.026s (-49.9% 🟢)1.902s51.00x
▲ VercelNext.js (Turbopack)11.473s (-20.9% 🟢)12.880s (-19.9% 🟢)1.407s51.13x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.503s (-22.0% 🟢)2.007s (-4.4%)0.504s451.00x
🐘 PostgresExpress1.918s (-3.0%)2.100s (-7.0% 🟢)0.183s431.28x
🐘 PostgresNext.js (Turbopack)1.959s2.203s0.244s411.30x
💻 LocalNext.js (Turbopack)2.627s3.008s0.381s301.75x
💻 LocalNitro3.004s (-1.0%)3.508s (-6.7% 🟢)0.504s262.00x
💻 LocalExpress3.039s (+0.8%)3.690s (+2.9%)0.651s252.02x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)32.147s (-35.5% 🟢)33.634s (-35.0% 🟢)1.487s31.00x
▲ VercelNitro37.762s (-4.4%)39.759s (-3.7%)1.997s31.17x
▲ VercelExpress⚠️missing----

🔍 Observability: Next.js (Turbopack) | Nitro

workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro3.164s (-22.9% 🟢)3.824s (-16.9% 🟢)0.660s321.00x
🐘 PostgresNext.js (Turbopack)3.883s4.147s0.264s291.23x
🐘 PostgresExpress3.890s (-2.5%)4.110s (-5.9% 🟢)0.219s301.23x
💻 LocalNext.js (Turbopack)8.566s9.018s0.452s142.71x
💻 LocalExpress9.269s (+0.6%)10.019s (~)0.749s122.93x
💻 LocalNitro9.497s (+2.1%)10.101s (+0.8%)0.604s123.00x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro77.978s (-19.5% 🟢)79.827s (-18.9% 🟢)1.850s21.00x
▲ VercelNext.js (Turbopack)89.255s (-16.7% 🟢)90.555s (-16.9% 🟢)1.300s21.14x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.235s (-16.9% 🟢)1.007s (~)0.772s601.00x
🐘 PostgresNext.js (Turbopack)0.256s1.008s0.751s601.09x
🐘 PostgresExpress0.285s (+0.8%)1.007s (~)0.723s601.21x
💻 LocalNext.js (Turbopack)0.575s1.004s0.430s602.44x
💻 LocalExpress0.615s (+9.8% 🔺)1.022s (+1.7%)0.407s592.61x
💻 LocalNitro0.668s (+10.5% 🔺)1.095s (+7.2% 🔺)0.427s552.84x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro1.858s (+11.9% 🔺)3.442s (+2.7%)1.584s181.00x
▲ VercelNext.js (Turbopack)5.248s (+159.5% 🔺)6.681s (+76.1% 🔺)1.432s92.82x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.383s (-22.8% 🟢)1.006s (~)0.623s901.00x
🐘 PostgresExpress0.488s (-4.2%)1.007s (~)0.519s901.27x
🐘 PostgresNext.js (Turbopack)0.503s1.007s0.503s901.31x
💻 LocalNitro2.463s (-3.0%)3.009s (~)0.546s306.43x
💻 LocalExpress2.591s (+3.1%)3.009s (~)0.418s306.76x
💻 LocalNext.js (Turbopack)2.594s3.008s0.414s306.77x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro5.501s (+70.5% 🔺)7.445s (+54.4% 🔺)1.944s131.00x
▲ VercelNext.js (Turbopack)8.725s (+146.8% 🔺)10.373s (+99.7% 🔺)1.648s91.59x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.614s (-22.3% 🟢)1.007s (~)0.393s1201.00x
🐘 PostgresNext.js (Turbopack)0.800s1.008s0.208s1201.30x
🐘 PostgresExpress0.802s (-2.0%)1.016s (~)0.214s1191.31x
💻 LocalNext.js (Turbopack)10.669s11.392s0.723s1117.38x
💻 LocalNitro10.798s (-3.5%)11.300s (-3.1%)0.501s1117.59x
💻 LocalExpress11.456s (+2.4%)12.032s (+0.8%)0.576s1018.66x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro9.424s (+22.0% 🔺)11.667s (+24.1% 🔺)2.243s111.00x
▲ VercelNext.js (Turbopack)15.660s (+51.6% 🔺)16.985s (+38.2% 🔺)1.325s81.66x
▲ VercelExpress⚠️missing----

🔍 Observability: Nitro | Next.js (Turbopack)

Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.177s (-13.8% 🟢)0.997s (~)0.001s (-20.0% 🟢)1.011s (~)0.834s101.00x
💻 LocalNext.js (Turbopack)0.188s1.003s0.011s1.017s0.830s101.06x
🐘 PostgresNext.js (Turbopack)0.192s1.001s0.002s1.011s0.818s101.09x
💻 LocalNitro0.201s (-6.2% 🟢)1.004s (~)0.011s (-9.6% 🟢)1.017s (~)0.817s101.13x
💻 LocalExpress0.204s (+2.5%)1.004s (~)0.013s (+8.3% 🔺)1.020s (~)0.816s101.15x
🐘 PostgresExpress0.204s (~)1.001s (~)0.002s (+6.2% 🔺)1.011s (~)0.806s101.16x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)1.554s (-77.3% 🟢)2.748s (-68.2% 🟢)0.996s (+57.7% 🔺)4.134s (-57.8% 🟢)2.581s101.00x
▲ VercelNitro1.705s (-55.5% 🟢)2.818s (-46.6% 🟢)1.037s (+39.8% 🔺)4.300s (-33.7% 🟢)2.594s101.10x
▲ VercelExpress⚠️missing-----

🔍 Observability: Next.js (Turbopack) | Nitro

stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.531s (-14.9% 🟢)1.008s (~)0.004s (-14.3% 🟢)1.022s (~)0.491s591.00x
🐘 PostgresExpress0.607s (-3.6%)1.006s (~)0.004s (+3.1%)1.023s (~)0.416s591.14x
🐘 PostgresNext.js (Turbopack)0.617s1.008s0.003s1.020s0.402s591.16x
💻 LocalNitro0.742s (-11.6% 🟢)1.012s (~)0.009s (-2.5%)1.023s (-8.3% 🟢)0.281s591.40x
💻 LocalNext.js (Turbopack)0.806s1.011s0.013s1.120s0.313s541.52x
💻 LocalExpress0.956s (+26.2% 🔺)1.012s (-1.6%)0.010s (+5.4% 🔺)1.229s (+18.2% 🔺)0.273s491.80x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro4.889s (-83.4% 🟢)6.748s (-78.1% 🟢)0.465s (+315.1% 🔺)7.635s (-76.0% 🟢)2.746s81.00x
▲ VercelNext.js (Turbopack)14.674s (-13.3% 🟢)15.526s (-14.9% 🟢)0.211s (~)16.076s (-15.1% 🟢)1.403s53.00x
▲ VercelExpress⚠️missing-----

🔍 Observability: Nitro | Next.js (Turbopack)

10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Next.js (Turbopack)0.938s1.112s0.000s1.119s0.182s541.00x
🐘 PostgresNitro0.944s (-2.6%)1.177s (-5.7% 🟢)0.000s (+41.2% 🔺)1.190s (-5.4% 🟢)0.246s511.01x
🐘 PostgresExpress0.974s (+1.4%)1.219s (-4.6%)0.000s (+87.8% 🔺)1.243s (-4.9%)0.269s491.04x
💻 LocalNitro1.214s (-0.7%)2.021s (~)0.000s (+33.3% 🔺)2.022s (~)0.808s301.30x
💻 LocalExpress1.238s (+1.0%)2.020s (~)0.000s (-10.0% 🟢)2.022s (~)0.785s301.32x
💻 LocalNext.js (Turbopack)1.296s2.019s0.000s2.023s0.727s301.38x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro6.050s (+98.3% 🔺)7.665s (+74.5% 🔺)0.000s (-100.0% 🟢)8.112s (+68.7% 🔺)2.062s81.00x
▲ VercelNext.js (Turbopack)7.695s (-24.4% 🟢)7.641s (-33.7% 🟢)0.000s (NaN%)9.028s (-25.1% 🟢)1.333s71.27x
▲ VercelExpress⚠️missing-----

🔍 Observability: Nitro | Next.js (Turbopack)

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

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.720s (-4.0%)2.104s (-1.7%)0.000s (+93.1% 🔺)2.112s (-2.9%)0.392s291.00x
🐘 PostgresExpress1.727s (-2.5%)2.104s (-3.4%)0.000s (NaN%)2.113s (-3.9%)0.386s291.00x
🐘 PostgresNext.js (Turbopack)1.888s2.182s0.000s2.189s0.301s281.10x
💻 LocalNitro3.502s (+3.4%)4.035s (~)0.001s (+50.0% 🔺)4.038s (~)0.536s152.04x
💻 LocalExpress3.589s (+3.5%)4.030s (~)0.000s (-58.3% 🟢)4.033s (~)0.444s152.09x
💻 LocalNext.js (Turbopack)3.746s4.166s0.000s4.170s0.424s152.18x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)5.451s (-3.0%)6.756s (-3.2%)0.000s (-100.0% 🟢)7.096s (-5.9% 🟢)1.645s91.00x
▲ VercelNitro8.938s (+118.3% 🔺)10.290s (+91.5% 🔺)0.000s (-100.0% 🟢)10.758s (+85.7% 🔺)1.819s61.64x
▲ VercelExpress⚠️missing-----

🔍 Observability: Next.js (Turbopack) | Nitro

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalNext.js (Turbopack)15/21
🐘 PostgresNitro20/21
▲ VercelNitro18/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres18/21
Next.js (Turbopack)🐘 Postgres17/21
Nitro🐘 Postgres19/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

@changeset-bot

changeset-botBot commented Apr 10, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: dc6415b

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

This PR includes changesets to release 18 packages
NameType
@workflow/swc-pluginMajor
@workflow/buildersPatch
@workflow/cliPatch
@workflow/nextPatch
@workflow/rollupPatch
@workflow/nestPatch
@workflow/astroPatch
@workflow/nitroPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/vitestPatch
workflowPatch
@workflow/world-testingPatch
@workflow/nuxtPatch
@workflow/aiPatch
@workflow/corePatch
@workflow/web-sharedPatch
@workflow/webPatch

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

vercelBot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

@TooTallNate
TooTallNateforce-pushed the nr/remove-client-mode branch from aac9033 to cf9fe73CompareApril 10, 2026 17:20
Remove the `client` transform mode from the SWC compiler plugin. The
`client` and `step` modes were nearly identical — both preserved step
function bodies, replaced workflow bodies with throw stubs, and emitted
the same JSON manifest. Step mode now absorbs all client-mode behaviors:
- Dead code elimination (previously only workflow + client)
- Hoisted variable references for object property steps
- All integrations use mode: 'step' instead of 'client'
BREAKING CHANGE: The `client` value for the SWC plugin `mode` option is
no longer accepted. Use `step` instead.
…sId registration
In dev mode, Nitro's Rollup externalizes npm packages like @workflow/core,
so the SWC transform plugin never processes files like run.js. This means
serde classes (e.g. Run) never get the classId registration IIFE, causing
serialization failures when step functions return Run instances.
Uses a Rollup resolveId hook to force workflow SDK packages to be bundled
(non-external) while leaving all other dependencies external. This is more
targeted than noExternals=true which bundles everything and causes TDZ
errors from circular imports in packages like vue-bundle-renderer/h3.
The Nitro module now also ignores .nitro/workflow/** in watchOptions so
writing generated workflow bundles does not retrigger Nitro's own dev
bundle rebuild loop.
Also wraps dev:reload workflow rebuilds and makes LocalBuilder.build()
atomic (writes to temp files, renames on success) to avoid partial output
state during HMR.
For Nuxt, also configures Vite's ssr.noExternal to bundle workflow
packages in the SSR context.

CopilotAI left a comment

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.

Pull request overview

Removes the SWC plugin’s client transform mode by merging its behavior into step mode, and updates all repository integrations, docs, and fixtures to use the new 3-mode model (Step/Workflow/Detect).

Changes:

  • Dropped Client from TransformMode, updated step mode to include client-mode behaviors (notably DCE + object-property hoisting semantics), and removed client-mode fixture runners/outputs.
  • Updated framework/tooling integrations (Next loader, Rollup, Nest CLI, Builders, CLI) to use mode: 'step' everywhere client was previously used.
  • Updated docs/spec and the SWC playground (WASM + UI/types) to remove the client output/view.

Reviewed changes

Copilot reviewed 103 out of 103 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
workbench/swc-playground/wasm/src/lib.rsRemoves client from batch transform output and runs only workflow+step.
workbench/swc-playground/lib/transform.tsUpdates TS types to drop client transform result.
workbench/swc-playground/components/swc-playground.tsxRemoves client view/panel/state in the playground UI.
packages/swc-plugin-workflow/transform/src/lib.rsRemoves Client mode and folds client behaviors into Step (DCE, hoisting/registration paths, etc.).
packages/swc-plugin-workflow/spec.mdUpdates specification to reflect 3 modes and step-mode DCE/hoisting behavior.
packages/swc-plugin-workflow/transform/tests/fixture.rsRemoves the client-mode fixture test harness.
packages/swc-plugin-workflow/transform/tests/errors.rsRemoves the client-mode errors fixture harness and updates imports.
packages/swc-plugin-workflow/transform/tests/fixture/workflow-client-property/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/workflow-arrow-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/var-named-step-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/using-declaration-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/using-declaration-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/user-named-dunder-default/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/unused-variables-and-types/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/unused-variables-and-types/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/unused-exports/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/unused-exports/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step/output-step.jsUpdates step-mode fixture to reflect new object-property hoisting behavior.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step-default-export/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/sync-step-class/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/step-with-this-arguments-super/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/step-with-imports/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/step-with-imports/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/step-arrow-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/static-method-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/static-method-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/static-getter-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/single-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/single-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/separate-export-statement/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/private-member-dce/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/private-member-dce-native/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/object-property-step/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/object-property-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/object-getter-step/output-step.jsUpdates step-mode fixture to reflect object getter/property behavior.
packages/swc-plugin-workflow/transform/tests/fixture/object-getter-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/nested-steps-in-object-constructor/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/nested-steps-in-object-constructor/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/nested-step-with-closure/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/nested-step-with-closure/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/nested-step-in-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/multiple-const-step-functions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-workflow/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-step/output-step.jsUpdates step-mode fixture to reflect new DCE behavior.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/mixed-functions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/let-arrow-step-function/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/instance-method-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/instance-method-nested-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/instance-getter-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/expr-fn-default-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-named/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-anonymous/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-anonymous-step-only/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/destructuring/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/default-workflow-collision/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/output-workflow.jsUpdates fixture to reflect export changes under new behavior.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/output-step.jsUpdates fixture to reflect export changes under new behavior.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/default-parameter-usage/input.jsUpdates input fixture to be exported (aligning outputs).
packages/swc-plugin-workflow/transform/tests/fixture/default-arrow-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/deeply-nested-step/output-step.jsUpdates step-mode fixture to reflect hoisted reference usage.
packages/swc-plugin-workflow/transform/tests/fixture/deeply-nested-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-require-namespace/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-require-destructured/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-local-const/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/custom-serialization-imported/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/closure-typescript-expressions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/closure-new-expr-and-module-declarations/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/class-expression-binding-name/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/class-expression-binding-name-step-methods/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/anonymous-default-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step-shorthand-method/output-step.jsUpdates step-mode fixture to reflect object-property hoist references.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step-shorthand-method/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/sync-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/non-async-functions/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misspelled-workflow-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misspelled-step-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misplaced-module-directive/output-step.jsUpdates step-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misplaced-module-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/misplaced-function-directive/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/invalid-exports/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/invalid-default-exports-step/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/instance-methods/output-client.jsDeletes client-mode expected output fixture.
packages/swc-plugin-workflow/transform/tests/errors/getter-workflow/output-client.jsDeletes client-mode expected output fixture.
packages/next/src/loader.tsSwitches all transforms to mode: 'step'.
packages/rollup/src/index.tsSwitches Rollup integration transform mode to step.
packages/nest/src/cli.tsUpdates generated .swcrc to use mode: 'step' and help text accordingly.
packages/cli/src/commands/transform.tsRemoves client from CLI transform modes/options.
packages/builders/src/apply-swc-transform.tsUpdates API type to drop client mode.
packages/builders/src/swc-esbuild-plugin.tsUpdates SwcPluginOptions.mode type to drop client.
packages/builders/src/base-builder.tsUpdates builder SWC plugin usage from client to step.
packages/nuxt/src/module.tsForces Vite SSR bundling behavior for workflow packages and marks _vite for Nitro.
packages/nitro/src/index.tsAdds dev-only rollup force-inline plugin and dev-time dynamic loading of generated workflow bundles.
packages/nitro/src/builders.tsWrites workflow bundles to temp files first and renames into place.
.changeset/remove-client-mode.mdAdds changeset documenting the breaking removal of client mode and migration guidance.

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

Comment threadpackages/nitro/src/builders.ts Outdated
Comment threadpackages/nuxt/src/module.ts Outdated
Comment threadpackages/nitro/src/index.ts Outdated
- nitro builders: use crypto.randomUUID() for temp file suffix instead of
Date.now() to avoid collisions under rapid/concurrent build() calls,
and serialize concurrent build() calls through an internal queue so
two overlapping dev rebuilds cannot clobber each other's temp outputs.
- nitro index: use fileURLToPath() to convert file:// URLs to filesystem
paths, which correctly handles Windows paths (file:///C:/... -> C:\...)
and percent-decoding, instead of relying on new URL(...).pathname.
- nuxt module: normalize vite.ssr.noExternal to an array (preserving any
existing string/RegExp/array entry) before appending workflow package
matchers, so the force-bundle behavior is not a no-op when noExternal
is already set to a non-array value.

@VaguelySeriousVaguelySerious left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM assuming tests pass, we're only landing this on v5 right?

@TooTallNate

Copy link
Copy Markdown
MemberAuthor

@VaguelySerious correct

Sign up for freeto 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

@TooTallNate@ijjk@VaguelySerious