Skip to content

Inline all SWC plugin step registrations, remove workflow/internal/private#1632

Merged
TooTallNate merged 5 commits intomainfrom
inline-step-registration
Apr 8, 2026
Merged

Inline all SWC plugin step registrations, remove workflow/internal/private#1632
TooTallNate merged 5 commits intomainfrom
inline-step-registration

Conversation

@TooTallNate
Copy link
Copy Markdown
Member

Summary

  • SWC plugin no longer generates import statements. All step function registrations and closure variable access are now self-contained inline IIFEs with zero module dependencies.
  • Step registration uses an IIFE writing to globalThis[Symbol.for("@workflow/core//registeredSteps")], matching the pattern already used for class serialization registration.
  • Closure variable access uses an IIFE reading from globalThis[Symbol.for("WORKFLOW_STEP_CONTEXT_STORAGE")], eliminating the __private_getClosureVars import.
  • Registrations are placed immediately after each function definition instead of being batched at the bottom of the file.
  • Removes @workflow/core/private and workflow/internal/private public subpath exports since they are no longer referenced by generated code.

Motivation

The previous import { registerStepFunction } from "workflow/internal/private" pattern was problematic for 3rd-party node_modules packages that define step functions but don't have the workflow package available at runtime. By inlining all registrations as self-contained IIFEs (the same pattern already used for class serialization), the transformed code has zero module dependencies.

Changed packages

  • @workflow/swc-plugin — Rust transform: replaced create_private_imports() with create_inline_step_registration() and create_inline_get_closure_vars() IIFEs; moved registration placement from end-of-file to immediately after each function definition; removed registration_calls field
  • @workflow/core — Removed ./private from package.json exports; updated serialization test to import __private_getClosureVars directly
  • workflow — Removed ./internal/private from package.json exports; deleted src/internal/private.ts re-export file
  • Docs — Updated code-transform.mdx with new inline IIFE example
  • Updated spec.md with all new code patterns
  • Updated e2e test stack trace assertions (no longer reference registerStepFunction)

Test plan

  • All 193 Rust SWC plugin tests pass (22 unit + 24 error + 147 fixture)
  • All 580 @workflow/core unit tests pass
  • All 252 @workflow/builders tests pass
  • Fixture test outputs auto-updated via UPDATE=1 cargo test

…/private

The SWC compiler plugin no longer generates import statements. All step
function registrations and closure variable access are now self-contained
inline IIFEs with zero module dependencies:

- Step registration uses an IIFE that writes to
  globalThis[Symbol.for('@workflow/core//registeredSteps')]
- Closure variable access uses an IIFE that reads from
  globalThis[Symbol.for('WORKFLOW_STEP_CONTEXT_STORAGE')]
- Registrations are placed immediately after each function definition
  instead of being batched at the bottom of the file

This enables 3rd-party node_modules packages to define step functions
without needing the 'workflow' package available at runtime.

Also removes the @workflow/core/private and workflow/internal/private
public subpath exports since they are no longer referenced by generated
code.
@TooTallNate TooTallNate requested a review from a team as a code owner April 7, 2026 07:03
Copilot AI review requested due to automatic review settings April 7, 2026 07:03
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 7, 2026

🦋 Changeset detected

Latest commit: 0fb7721

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

This PR includes changesets to release 17 packages
Name Type
@workflow/swc-plugin Major
@workflow/core Major
workflow Major
@workflow/astro Patch
@workflow/builders Patch
@workflow/cli Patch
@workflow/nest Patch
@workflow/next Patch
@workflow/nitro Patch
@workflow/rollup Patch
@workflow/sveltekit Patch
@workflow/vitest Patch
@workflow/web-shared Patch
@workflow/world-testing Patch
@workflow/ai Major
@workflow/vite Patch
@workflow/nuxt Patch

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

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

@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Apr 7, 2026

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

Project Deployment Actions Updated (UTC)
example-nextjs-workflow-turbopack Ready Ready Preview, Comment Apr 8, 2026 11:28pm
example-nextjs-workflow-webpack Ready Ready Preview, Comment Apr 8, 2026 11:28pm
example-workflow Ready Ready Preview, Comment Apr 8, 2026 11:28pm
workbench-astro-workflow Ready Ready Preview, Comment Apr 8, 2026 11:28pm
workbench-express-workflow Ready Ready Preview, Comment Apr 8, 2026 11:28pm
workbench-fastify-workflow Ready Ready Preview, Comment Apr 8, 2026 11:28pm
workbench-hono-workflow Ready Ready Preview, Comment Apr 8, 2026 11:28pm
workbench-nitro-workflow Ready Ready Preview, Comment Apr 8, 2026 11:28pm
workbench-nuxt-workflow Ready Ready Preview, Comment Apr 8, 2026 11:28pm
workbench-sveltekit-workflow Ready Ready Preview, Comment Apr 8, 2026 11:28pm
workbench-vite-workflow Ready Ready Preview, Comment Apr 8, 2026 11:28pm
workflow-docs Ready Ready Preview, Comment, Open in v0 Apr 8, 2026 11:28pm
workflow-swc-playground Ready Ready Preview, Comment Apr 8, 2026 11:28pm

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 7, 2026

📊 Benchmark Results

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

workflow with no steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Express 0.041s (-6.7% 🟢) 1.006s (~) 0.965s 10 1.00x
💻 Local Nitro 0.041s (-5.8% 🟢) 1.005s (~) 0.965s 10 1.01x
💻 Local Next.js (Turbopack) 0.048s 1.005s 0.957s 10 1.18x
🌐 Redis Next.js (Turbopack) 0.052s 1.005s 0.952s 10 1.28x
🐘 Postgres Next.js (Turbopack) 0.056s 1.010s 0.954s 10 1.38x
🐘 Postgres Nitro 0.059s (-7.0% 🟢) 1.010s (~) 0.952s 10 1.44x
🐘 Postgres Express 0.059s (+1.2%) 1.010s (~) 0.951s 10 1.46x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 0.208s (-10.9% 🟢) 1.986s (-5.0% 🟢) 1.779s 10 1.00x
▲ Vercel Express 0.219s (+4.6%) 2.004s (-7.8% 🟢) 1.786s 10 1.05x
▲ Vercel Next.js (Turbopack) 0.258s (+12.4% 🔺) 1.949s (-14.0% 🟢) 1.691s 10 1.24x

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

workflow with 1 step

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Next.js (Turbopack) 1.121s 2.005s 0.885s 10 1.00x
💻 Local Express 1.127s (~) 2.006s (~) 0.879s 10 1.01x
🌐 Redis Next.js (Turbopack) 1.128s 2.006s 0.878s 10 1.01x
💻 Local Nitro 1.130s (~) 2.006s (~) 0.877s 10 1.01x
🐘 Postgres Next.js (Turbopack) 1.134s 2.010s 0.876s 10 1.01x
🐘 Postgres Express 1.140s (~) 2.010s (~) 0.870s 10 1.02x
🐘 Postgres Nitro 1.149s (~) 2.010s (~) 0.861s 10 1.03x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 1.782s (-6.5% 🟢) 3.767s (~) 1.986s 10 1.00x
▲ Vercel Next.js (Turbopack) 1.812s (-12.1% 🟢) 3.510s (-8.1% 🟢) 1.699s 10 1.02x
▲ Vercel Express 2.051s (+11.0% 🔺) 3.739s (+2.2%) 1.688s 10 1.15x

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

workflow with 10 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 10.731s 11.022s 0.291s 3 1.00x
💻 Local Next.js (Turbopack) 10.833s 11.024s 0.190s 3 1.01x
🐘 Postgres Next.js (Turbopack) 10.896s 11.019s 0.123s 3 1.02x
🐘 Postgres Express 10.910s (~) 11.020s (~) 0.110s 3 1.02x
💻 Local Express 10.919s (~) 11.022s (~) 0.103s 3 1.02x
💻 Local Nitro 10.943s (~) 11.023s (~) 0.081s 3 1.02x
🐘 Postgres Nitro 10.981s (+0.6%) 11.022s (~) 0.041s 3 1.02x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 16.674s (-2.6%) 18.834s (-4.6%) 2.161s 2 1.00x
▲ Vercel Express 16.829s (-11.5% 🟢) 18.471s (-11.9% 🟢) 1.642s 2 1.01x
▲ Vercel Next.js (Turbopack) 16.875s (-2.0%) 18.628s (-4.1%) 1.753s 2 1.01x

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

workflow with 25 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 14.177s 15.028s 0.852s 4 1.00x
🐘 Postgres Next.js (Turbopack) 14.435s 15.026s 0.591s 4 1.02x
🐘 Postgres Express 14.528s (~) 15.024s (~) 0.496s 4 1.02x
💻 Local Next.js (Turbopack) 14.582s 15.030s 0.447s 4 1.03x
🐘 Postgres Nitro 14.665s (~) 15.025s (~) 0.359s 4 1.03x
💻 Local Express 14.979s (~) 15.029s (~) 0.051s 4 1.06x
💻 Local Nitro 14.985s (~) 15.029s (~) 0.043s 4 1.06x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 30.500s (-7.5% 🟢) 33.735s (-3.4%) 3.235s 2 1.00x
▲ Vercel Express 31.866s (-0.6%) 34.467s (+3.3%) 2.601s 2 1.04x
▲ Vercel Next.js (Turbopack) 33.843s (~) 35.580s (-0.8%) 1.738s 2 1.11x

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

workflow with 50 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 13.370s 14.024s 0.654s 7 1.00x
🐘 Postgres Next.js (Turbopack) 13.844s 14.024s 0.179s 7 1.04x
🐘 Postgres Express 13.999s (-1.2%) 14.590s (-2.9%) 0.591s 7 1.05x
🐘 Postgres Nitro 14.272s (+1.0%) 15.022s (+1.9%) 0.750s 6 1.07x
💻 Local Next.js (Turbopack) 15.776s 16.031s 0.255s 6 1.18x
💻 Local Nitro 16.658s (+0.6%) 17.030s (~) 0.372s 6 1.25x
💻 Local Express 16.930s (+3.4%) 17.365s (+2.0%) 0.434s 6 1.27x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 48.017s (-76.8% 🟢) 50.259s (-76.0% 🟢) 2.242s 2 1.00x
▲ Vercel Express 50.003s (-75.8% 🟢) 51.616s (-75.2% 🟢) 1.613s 2 1.04x
▲ Vercel Next.js (Turbopack) 51.422s (-15.2% 🟢) 52.966s (-15.3% 🟢) 1.544s 2 1.07x

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

Promise.all with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Next.js (Turbopack) 1.243s 2.009s 0.767s 15 1.00x
🌐 Redis Next.js (Turbopack) 1.260s 2.006s 0.746s 15 1.01x
🐘 Postgres Nitro 1.277s (-1.0%) 2.009s (~) 0.732s 15 1.03x
🐘 Postgres Express 1.279s (+1.5%) 2.011s (~) 0.732s 15 1.03x
💻 Local Next.js (Turbopack) 1.516s 2.006s 0.489s 15 1.22x
💻 Local Express 1.529s (+2.0%) 2.006s (~) 0.477s 15 1.23x
💻 Local Nitro 1.595s (+3.7%) 2.006s (~) 0.411s 15 1.28x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 2.113s (-19.0% 🟢) 3.784s (-12.5% 🟢) 1.671s 8 1.00x
▲ Vercel Express 2.482s (-9.6% 🟢) 4.041s (-9.4% 🟢) 1.559s 8 1.17x
▲ Vercel Next.js (Turbopack) 2.498s (+1.6%) 4.126s (-8.9% 🟢) 1.628s 8 1.18x

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

Promise.all with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 2.331s (-2.0%) 3.008s (~) 0.677s 10 1.00x
🐘 Postgres Nitro 2.356s (~) 3.011s (~) 0.655s 10 1.01x
🐘 Postgres Next.js (Turbopack) 2.426s 3.010s 0.584s 10 1.04x
🌐 Redis Next.js (Turbopack) 2.555s 3.007s 0.452s 10 1.10x
💻 Local Next.js (Turbopack) 2.563s 3.008s 0.445s 10 1.10x
💻 Local Nitro 3.063s (+4.6%) 3.565s (+14.7% 🔺) 0.502s 9 1.31x
💻 Local Express 3.143s (+11.2% 🔺) 4.010s (+29.0% 🔺) 0.868s 8 1.35x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 2.303s (-32.9% 🟢) 3.695s (-26.6% 🟢) 1.393s 9 1.00x
▲ Vercel Express 2.379s (-22.1% 🟢) 3.906s (-16.5% 🟢) 1.527s 8 1.03x
▲ Vercel Next.js (Turbopack) 2.745s (-3.4%) 4.445s (-7.1% 🟢) 1.700s 7 1.19x

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

Promise.all with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 3.474s (~) 4.011s (~) 0.536s 8 1.00x
🐘 Postgres Express 3.508s (+0.9%) 4.012s (~) 0.504s 8 1.01x
🐘 Postgres Next.js (Turbopack) 3.664s 4.010s 0.346s 8 1.05x
🌐 Redis Next.js (Turbopack) 4.078s 4.582s 0.504s 7 1.17x
💻 Local Next.js (Turbopack) 7.256s 8.016s 0.760s 4 2.09x
💻 Local Nitro 8.582s (+4.9%) 9.024s (~) 0.442s 4 2.47x
💻 Local Express 8.626s (+13.3% 🔺) 9.276s (+12.1% 🔺) 0.650s 4 2.48x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.623s (-14.4% 🟢) 4.043s (-15.8% 🟢) 1.420s 8 1.00x
▲ Vercel Next.js (Turbopack) 2.992s (-26.4% 🟢) 5.006s (-20.3% 🟢) 2.014s 7 1.14x
▲ Vercel Nitro 3.075s (-6.2% 🟢) 4.672s (-5.0%) 1.597s 7 1.17x

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

Promise.race with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Next.js (Turbopack) 1.224s 2.009s 0.785s 15 1.00x
🐘 Postgres Nitro 1.264s (~) 2.009s (~) 0.745s 15 1.03x
🐘 Postgres Express 1.266s (~) 2.008s (~) 0.742s 15 1.03x
🌐 Redis Next.js (Turbopack) 1.307s 2.006s 0.699s 15 1.07x
💻 Local Next.js (Turbopack) 1.489s 2.006s 0.518s 15 1.22x
💻 Local Express 1.544s (+2.5%) 2.005s (~) 0.461s 15 1.26x
💻 Local Nitro 1.565s (+2.2%) 2.005s (~) 0.441s 15 1.28x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 2.006s (-12.6% 🟢) 3.836s (-3.0%) 1.830s 8 1.00x
▲ Vercel Express 2.077s (-8.9% 🟢) 3.755s (-5.2% 🟢) 1.679s 8 1.04x
▲ Vercel Next.js (Turbopack) 2.095s (-10.5% 🟢) 3.780s (-9.4% 🟢) 1.685s 9 1.04x

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

Promise.race with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 2.342s (~) 3.009s (~) 0.668s 10 1.00x
🐘 Postgres Nitro 2.354s (-0.8%) 3.010s (~) 0.655s 10 1.01x
🐘 Postgres Next.js (Turbopack) 2.395s 3.008s 0.613s 10 1.02x
🌐 Redis Next.js (Turbopack) 2.555s 3.007s 0.452s 10 1.09x
💻 Local Next.js (Turbopack) 2.919s 3.453s 0.533s 9 1.25x
💻 Local Nitro 3.008s (-3.0%) 3.759s (-3.2%) 0.751s 8 1.28x
💻 Local Express 3.171s (+10.9% 🔺) 4.010s (+33.3% 🔺) 0.839s 8 1.35x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 2.430s (-99.2% 🟢) 4.126s (-98.7% 🟢) 1.696s 8 1.00x
▲ Vercel Express 2.558s (-96.8% 🟢) 4.425s (-94.5% 🟢) 1.867s 7 1.05x
▲ Vercel Next.js (Turbopack) 2.674s (-5.5% 🟢) 4.144s (-12.7% 🟢) 1.470s 8 1.10x

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

Promise.race with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 3.486s (~) 4.010s (~) 0.524s 8 1.00x
🐘 Postgres Nitro 3.522s (+1.9%) 4.012s (~) 0.490s 8 1.01x
🐘 Postgres Next.js (Turbopack) 3.658s 4.012s 0.355s 8 1.05x
🌐 Redis Next.js (Turbopack) 4.124s 4.725s 0.601s 7 1.18x
💻 Local Next.js (Turbopack) 8.178s 8.770s 0.592s 4 2.35x
💻 Local Nitro 8.826s (-1.6%) 9.278s (~) 0.452s 4 2.53x
💻 Local Express 9.371s (+16.8% 🔺) 10.023s (+14.2% 🔺) 0.653s 3 2.69x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 2.492s (-17.0% 🟢) 3.886s (-17.1% 🟢) 1.394s 8 1.00x
▲ Vercel Express 2.639s (-40.8% 🟢) 3.960s (-34.1% 🟢) 1.321s 8 1.06x
▲ Vercel Next.js (Turbopack) 3.168s (-11.8% 🟢) 4.749s (-11.0% 🟢) 1.581s 7 1.27x

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

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 0.683s 1.004s 0.321s 60 1.00x
🐘 Postgres Next.js (Turbopack) 0.789s 1.023s 0.234s 59 1.15x
🐘 Postgres Express 0.814s (-4.5%) 1.006s (~) 0.191s 60 1.19x
🐘 Postgres Nitro 0.877s (+6.5% 🔺) 1.023s (+1.7%) 0.146s 59 1.28x
💻 Local Next.js (Turbopack) 0.878s 1.021s 0.143s 59 1.28x
💻 Local Express 0.986s (-3.5%) 1.181s (-23.5% 🟢) 0.195s 51 1.44x
💻 Local Nitro 0.993s (+0.8%) 1.229s (+4.1%) 0.237s 49 1.45x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 9.076s (-12.2% 🟢) 11.177s (-10.3% 🟢) 2.101s 6 1.00x
▲ Vercel Nitro 10.169s (+11.7% 🔺) 11.826s (+5.8% 🔺) 1.657s 6 1.12x
▲ Vercel Express 10.253s (~) 12.359s (+2.8%) 2.106s 5 1.13x

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

workflow with 25 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 1.631s 2.006s 0.374s 45 1.00x
🐘 Postgres Next.js (Turbopack) 1.909s 2.076s 0.167s 44 1.17x
🐘 Postgres Express 1.969s (-4.3%) 2.283s (-20.8% 🟢) 0.314s 40 1.21x
🐘 Postgres Nitro 2.082s (+5.6% 🔺) 2.884s (+29.5% 🔺) 0.802s 32 1.28x
💻 Local Next.js (Turbopack) 2.715s 3.008s 0.293s 30 1.66x
💻 Local Express 3.058s (~) 3.843s (+5.3% 🔺) 0.786s 24 1.87x
💻 Local Nitro 3.212s (+7.0% 🔺) 3.729s (+5.1% 🔺) 0.517s 25 1.97x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 26.552s (-8.3% 🟢) 28.504s (-7.1% 🟢) 1.952s 4 1.00x
▲ Vercel Next.js (Turbopack) 27.186s (-11.7% 🟢) 28.728s (-12.7% 🟢) 1.542s 4 1.02x
▲ Vercel Express 27.343s (-2.7%) 29.493s (-2.0%) 2.151s 4 1.03x

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

workflow with 50 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 3.272s 4.008s 0.736s 30 1.00x
🐘 Postgres Next.js (Turbopack) 3.856s 4.043s 0.186s 30 1.18x
🐘 Postgres Nitro 4.038s (-2.4%) 4.664s (-4.6%) 0.626s 26 1.23x
🐘 Postgres Express 4.110s (+0.9%) 4.742s (-1.4%) 0.632s 26 1.26x
💻 Local Next.js (Turbopack) 8.341s 9.017s 0.675s 14 2.55x
💻 Local Nitro 9.172s (~) 9.864s (-0.8%) 0.693s 13 2.80x
💻 Local Express 9.446s (+5.6% 🔺) 10.019s (+6.6% 🔺) 0.574s 12 2.89x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 71.540s (-5.7% 🟢) 73.269s (-5.6% 🟢) 1.729s 2 1.00x
▲ Vercel Nitro 74.939s (+2.5%) 77.097s (+3.0%) 2.158s 2 1.05x
▲ Vercel Next.js (Turbopack) 75.960s (-8.9% 🟢) 78.327s (-8.4% 🟢) 2.367s 2 1.06x

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

workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Next.js (Turbopack) 0.254s 1.007s 0.753s 60 1.00x
🌐 Redis Next.js (Turbopack) 0.266s 1.004s 0.739s 60 1.04x
🐘 Postgres Nitro 0.288s (+0.6%) 1.007s (~) 0.719s 60 1.13x
🐘 Postgres Express 0.294s (+5.3% 🔺) 1.007s (~) 0.713s 60 1.16x
💻 Local Nitro 0.581s (-2.2%) 1.004s (~) 0.423s 60 2.29x
💻 Local Next.js (Turbopack) 0.581s 1.022s 0.440s 59 2.29x
💻 Local Express 0.604s (+2.3%) 1.005s (~) 0.401s 60 2.38x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 1.351s (-24.8% 🟢) 2.751s (-22.8% 🟢) 1.400s 22 1.00x
▲ Vercel Express 1.398s (-26.7% 🟢) 2.922s (-17.9% 🟢) 1.523s 21 1.03x
▲ Vercel Next.js (Turbopack) 1.707s (+2.8%) 3.323s (+2.7%) 1.615s 19 1.26x

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

workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 0.488s (-2.9%) 1.006s (~) 0.518s 90 1.00x
🐘 Postgres Express 0.498s (+0.8%) 1.006s (~) 0.508s 90 1.02x
🐘 Postgres Next.js (Turbopack) 0.501s 1.006s 0.505s 90 1.03x
🌐 Redis Next.js (Turbopack) 1.137s 2.005s 0.869s 45 2.33x
💻 Local Express 2.527s (+3.4%) 3.008s (~) 0.481s 30 5.18x
💻 Local Next.js (Turbopack) 2.536s 3.009s 0.472s 30 5.20x
💻 Local Nitro 2.584s (+0.9%) 3.009s (~) 0.425s 30 5.29x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 19.418s (+643.4% 🔺) 21.124s (+385.7% 🔺) 1.707s 18 1.00x
▲ Vercel Nitro 20.373s (+721.8% 🔺) 21.893s (+424.7% 🔺) 1.520s 17 1.05x
▲ Vercel Next.js (Turbopack) 46.519s (+1211.0% 🔺) 48.120s (+834.9% 🔺) 1.600s 7 2.40x

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

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Next.js (Turbopack) 0.770s 1.007s 0.237s 120 1.00x
🐘 Postgres Express 0.794s (+0.5%) 1.008s (~) 0.214s 120 1.03x
🐘 Postgres Nitro 0.801s (-7.2% 🟢) 1.008s (-5.2% 🟢) 0.208s 119 1.04x
🌐 Redis Next.js (Turbopack) 2.577s 3.007s 0.430s 40 3.35x
💻 Local Next.js (Turbopack) 10.617s 11.205s 0.588s 11 13.79x
💻 Local Express 11.249s (+6.7% 🔺) 11.938s (+8.2% 🔺) 0.689s 11 14.61x
💻 Local Nitro 11.346s (+2.6%) 12.030s (+3.1%) 0.684s 10 14.74x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 5.932s (-13.9% 🟢) 7.702s (-10.3% 🟢) 1.770s 16 1.00x
▲ Vercel Next.js (Turbopack) 6.443s (+3.0%) 8.124s (+2.9%) 1.681s 15 1.09x
▲ Vercel Express 8.384s (+18.1% 🔺) 10.256s (+16.1% 🔺) 1.871s 13 1.41x

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

Stream Benchmarks (includes TTFB metrics)
workflow with stream

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Next.js (Turbopack) 0.174s 1.002s 0.010s 1.016s 0.842s 10 1.00x
🌐 Redis Next.js (Turbopack) 0.179s 1.000s 0.002s 1.007s 0.828s 10 1.03x
🐘 Postgres Next.js (Turbopack) 0.198s 1.001s 0.002s 1.011s 0.813s 10 1.14x
💻 Local Nitro 0.204s (~) 1.004s (~) 0.012s (+1.6%) 1.019s (~) 0.814s 10 1.17x
🐘 Postgres Express 0.206s (~) 0.996s (~) 0.002s (+23.1% 🔺) 1.010s (~) 0.804s 10 1.18x
💻 Local Express 0.208s (+2.6%) 1.005s (~) 0.013s (+26.0% 🔺) 1.019s (~) 0.811s 10 1.19x
🐘 Postgres Nitro 0.219s (+8.3% 🔺) 0.997s (~) 0.001s (-15.4% 🟢) 1.011s (~) 0.791s 10 1.26x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 1.355s (-21.9% 🟢) 2.365s (-27.2% 🟢) 0.793s (+129.2% 🔺) 3.642s (-9.5% 🟢) 2.287s 10 1.00x
▲ Vercel Nitro 1.480s (-37.8% 🟢) 2.630s (-30.8% 🟢) 0.601s (+62.5% 🔺) 3.637s (-21.7% 🟢) 2.157s 10 1.09x
▲ Vercel Next.js (Turbopack) 1.602s (~) 3.095s (-1.8%) 0.317s (+1.2%) 3.826s (-3.3%) 2.224s 10 1.18x

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

stream pipeline with 5 transform steps (1MB)

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 0.463s 1.002s 0.003s 1.010s 0.547s 60 1.00x
🐘 Postgres Next.js (Turbopack) 0.604s 1.009s 0.004s 1.021s 0.417s 59 1.30x
🐘 Postgres Express 0.608s (-2.7%) 1.003s (~) 0.004s (-9.7% 🟢) 1.021s (~) 0.414s 59 1.31x
🐘 Postgres Nitro 0.664s (+6.7% 🔺) 1.021s (+1.6%) 0.004s (+3.8%) 1.039s (+1.7%) 0.375s 58 1.43x
💻 Local Nitro 0.735s (+0.7%) 1.012s (~) 0.010s (+2.3%) 1.023s (~) 0.288s 59 1.59x
💻 Local Next.js (Turbopack) 0.759s 1.010s 0.008s 1.114s 0.355s 54 1.64x
💻 Local Express 0.816s (+5.9% 🔺) 1.012s (~) 0.009s (-0.5%) 1.116s (+8.9% 🔺) 0.300s 54 1.76x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 4.125s (-2.8%) 5.610s (-3.0%) 0.197s (-49.0% 🟢) 6.319s (-4.7%) 2.195s 10 1.00x
▲ Vercel Nitro 4.146s (+9.5% 🔺) 5.683s (+7.6% 🔺) 0.539s (+40.4% 🔺) 6.705s (+10.4% 🔺) 2.558s 9 1.01x
▲ Vercel Express 4.190s 5.547s 0.223s 6.209s 2.019s 10 1.02x

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

10 parallel streams (1MB each)

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 0.875s 1.000s 0.000s 1.004s 0.129s 60 1.00x
🐘 Postgres Express 0.948s (-2.3%) 1.172s (~) 0.000s (-50.0% 🟢) 1.184s (-1.0%) 0.237s 51 1.08x
🐘 Postgres Next.js (Turbopack) 0.952s 1.112s 0.000s 1.119s 0.168s 54 1.09x
🐘 Postgres Nitro 0.966s (+0.9%) 1.270s (+10.6% 🔺) 0.000s (-26.2% 🟢) 1.285s (+10.6% 🔺) 0.320s 47 1.10x
💻 Local Express 1.227s (~) 2.021s (~) 0.000s (-42.9% 🟢) 2.023s (~) 0.796s 30 1.40x
💻 Local Nitro 1.246s (~) 2.023s (~) 0.000s (+100.0% 🔺) 2.024s (~) 0.778s 30 1.42x
💻 Local Next.js (Turbopack) 1.250s 2.020s 0.000s 2.023s 0.772s 30 1.43x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.454s (-5.8% 🟢) 3.540s (-4.2%) 0.000s (-88.3% 🟢) 3.957s (-4.0%) 1.503s 16 1.00x
▲ Vercel Nitro 2.573s (-91.7% 🟢) 3.611s (-88.8% 🟢) 0.000s (NaN%) 4.051s (-87.6% 🟢) 1.478s 15 1.05x
▲ Vercel Next.js (Turbopack) 3.060s (-8.2% 🟢) 4.456s (-4.2%) 0.000s (-53.8% 🟢) 4.954s (-2.8%) 1.894s 13 1.25x

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

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

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 1.559s 2.036s 0.000s 2.039s 0.480s 30 1.00x
🐘 Postgres Nitro 1.759s (-1.5%) 2.142s (~) 0.000s (-100.0% 🟢) 2.153s (~) 0.394s 28 1.13x
🐘 Postgres Express 1.763s (-6.1% 🟢) 2.176s (-5.1% 🟢) 0.000s (+Infinity% 🔺) 2.189s (-5.1% 🟢) 0.425s 28 1.13x
🐘 Postgres Next.js (Turbopack) 1.823s 2.110s 0.000s 2.152s 0.329s 28 1.17x
💻 Local Express 3.461s (+1.4%) 4.101s (+1.7%) 0.000s (-12.5% 🟢) 4.103s (+1.7%) 0.643s 15 2.22x
💻 Local Nitro 3.492s (-1.5%) 4.034s (~) 0.001s (+33.3% 🔺) 4.037s (~) 0.544s 15 2.24x
💻 Local Next.js (Turbopack) 3.660s 4.030s 0.000s 4.033s 0.373s 15 2.35x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 3.452s (-16.3% 🟢) 4.790s (-10.3% 🟢) 0.000s (-8.3% 🟢) 5.247s (-9.5% 🟢) 1.795s 12 1.00x
▲ Vercel Express 3.600s (-4.5%) 4.955s (+1.6%) 0.000s (+400.0% 🔺) 5.369s (+0.7%) 1.769s 12 1.04x
▲ Vercel Next.js (Turbopack) 4.145s (+3.2%) 5.394s (+1.2%) 0.000s (+Infinity% 🔺) 5.815s (~) 1.670s 11 1.20x

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

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World 🥇 Fastest Framework Wins
💻 Local Next.js (Turbopack) 15/21
🐘 Postgres Next.js (Turbopack) 14/21
▲ Vercel Nitro 14/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework 🥇 Fastest World Wins
Express 🐘 Postgres 17/21
Next.js (Turbopack) 🌐 Redis 9/21
Nitro 🐘 Postgres 14/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


⚠️ Community world benchmarks failed (non-blocking):

  • Community Worlds: failure

Check the workflow run for details.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 7, 2026

🧪 E2E Test Results

Some tests failed

Summary

Passed Failed Skipped Total
✅ ▲ Vercel Production 890 0 67 957
✅ 💻 Local Development 866 0 178 1044
✅ 📦 Local Production 866 0 178 1044
✅ 🐘 Local Postgres 866 0 178 1044
✅ 🪟 Windows 79 0 8 87
❌ 🌍 Community Worlds 136 65 24 225
✅ 📋 Other 219 0 42 261
Total 3922 65 675 4662

❌ Failed Tests

🌍 Community Worlds (65 failed)

mongodb (4 failed):

  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KNQPT2YKVJ8DGQD3JB7A8FK5
  • webhookWorkflow | wrun_01KNQPTAZ2YFZ46D06DF6DWR0S
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KNQQ1YG6XCXRV769KFXF3A25
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KNQQ8DEFKDQ6SAQNV6YY1KBY

redis (3 failed):

  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KNQPT2YKVJ8DGQD3JB7A8FK5
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KNQQ1YG6XCXRV769KFXF3A25
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KNQQ8DEFKDQ6SAQNV6YY1KBY

turso (58 failed):

  • addTenWorkflow | wrun_01KNQPRXJX0RSJ2XBN1WBG7V65
  • addTenWorkflow | wrun_01KNQPRXJX0RSJ2XBN1WBG7V65
  • wellKnownAgentWorkflow (.well-known/agent) | wrun_01KNQPV3F6NWZBB59YPMM5MKWS
  • should work with react rendering in step
  • promiseAllWorkflow | wrun_01KNQPS4831GTWA4XYH6VYJCPG
  • promiseRaceWorkflow | wrun_01KNQPS8VWK9QKGTMNTSXE19TK
  • promiseAnyWorkflow | wrun_01KNQPSBDWRXD6PBAKWR9B8ZRY
  • importedStepOnlyWorkflow | wrun_01KNQPVEJ55NWKTYA3RM6RQMD9
  • hookWorkflow | wrun_01KNQPSQEH6937NVPY1FDPWSVP
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KNQPT2YKVJ8DGQD3JB7A8FK5
  • webhookWorkflow | wrun_01KNQPTAZ2YFZ46D06DF6DWR0S
  • sleepingWorkflow | wrun_01KNQPTHFK7VQ443TYBHXSP9R5
  • parallelSleepWorkflow | wrun_01KNQPTX5PP4Y0BK7HK42PJHNB
  • nullByteWorkflow | wrun_01KNQPV0C7BCBGWD4TKAMND3B8
  • workflowAndStepMetadataWorkflow | wrun_01KNQPV2GHYBV175EA9CC0H22Y
  • fetchWorkflow | wrun_01KNQPXRAX62YH1ZKP95YWZEF0
  • promiseRaceStressTestWorkflow | wrun_01KNQPXVPWS5DR1NCS1YRHWMPK
  • 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_01KNQQ19Y61J81F5BNJJJR05D7
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KNQQ1YG6XCXRV769KFXF3A25
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KNQQ2MHNMP86R0Q0QGZ441F0
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KNQQ38X1G07373GCME98W1YF
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_01KNQQ3J7S7YMGCV6WBJTA5FY0
  • closureVariableWorkflow - nested step functions with closure variables | wrun_01KNQQ3T0TCEXK6W59M876RQ2F
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_01KNQQ3WN6E9CD8HTCDCABK46F
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_01KNQQ4C2WXJ653H9CK417V5CV
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_01KNQQ4HPN6W5CY0TM59XEBVQN
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_01KNQQ4QSYRKGQJGEYF5X8TPM4
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_01KNQQ4YGAKG7QR7VT9NHVHZY6
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_01KNQQ54J0PWS33AJ9K1NMNPYE
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_01KNQQ5BDAH3FK0JT0RZ76FGSQ
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_01KNQQ5JGNJ376PCYVYFHTF3H6
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_01KNQQ5Y6PJ1RH9V11N5FKM9YC
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_01KNQQ667S2TB8Y3NAQF6CPSAX
  • cancelRun - cancelling a running workflow | wrun_01KNQQ6D8J00EZ6WX51YEG2CN0
  • cancelRun via CLI - cancelling a running workflow | wrun_01KNQQ6PG44AAD7W3MB54DY3KW
  • 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_01KNQQ72K670FRHYSVF372M36K
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KNQQ7QZD9TPC75AXWDJRMF4M
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KNQQ828Z5MVHD1ZX6V9NJKHA
  • importMetaUrlWorkflow - import.meta.url is available in step bundles | wrun_01KNQQ8911JNH51XAJ51FW5D1Y
  • metadataFromHelperWorkflow - getWorkflowMetadata/getStepMetadata work from module-level helper (#1577) | wrun_01KNQQ8B2Z49BKYHYVD8T7TT4T
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KNQQ8DEFKDQ6SAQNV6YY1KBY
  • getterStepWorkflow - getter functions with "use step" directive | wrun_01KNQQ8HAKTVXRN9PZWVHM0Z8D

Details by Category

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

📋 View full workflow run

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the SWC workflow transform to inline step registrations and closure-var access so transformed step bundles have zero runtime module imports, enabling 3rd-party packages to define step functions without requiring workflow to be installed at runtime. It also removes now-unneeded public subpath exports and updates docs/tests/fixtures accordingly.

Changes:

  • Inline step registrations as self-contained IIFEs writing to globalThis[Symbol.for("@workflow/core//registeredSteps")] (step mode) and inline closure-var access via Symbol.for("WORKFLOW_STEP_CONTEXT_STORAGE").
  • Remove @workflow/core/private and workflow/internal/private exports/re-exports; update internal tests/imports and docs/spec examples.
  • Refresh SWC fixture outputs and e2e stack-trace assertions to match new emitted code patterns.

Reviewed changes

Copilot reviewed 52 out of 52 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
packages/workflow/src/internal/private.ts Removes the workflow/internal/private re-export shim.
packages/workflow/package.json Drops the ./internal/private export entry.
packages/swc-plugin-workflow/transform/tests/fixture/var-named-step-function/output-step.js Updates expected output to inline registration IIFEs.
packages/swc-plugin-workflow/transform/tests/fixture/using-declaration-step/output-step.js Updates expected output to inline registration IIFEs.
packages/swc-plugin-workflow/transform/tests/fixture/unused-variables-and-types/output-step.js Updates expected output to inline registration IIFEs.
packages/swc-plugin-workflow/transform/tests/fixture/unused-exports/output-step.js Updates expected output to inline registration IIFEs.
packages/swc-plugin-workflow/transform/tests/fixture/step-with-this-arguments-super/output-step.js Updates expected output to inline registration IIFEs for functions/methods.
packages/swc-plugin-workflow/transform/tests/fixture/step-with-imports/output-step.js Updates expected output to inline registration IIFEs.
packages/swc-plugin-workflow/transform/tests/fixture/step-arrow-function/output-step.js Updates expected output to inline registration IIFEs.
packages/swc-plugin-workflow/transform/tests/fixture/static-method-step/output-step.js Updates expected output to inline registration IIFEs for static methods.
packages/swc-plugin-workflow/transform/tests/fixture/single-step/output-step.js Updates expected output to inline registration IIFEs.
packages/swc-plugin-workflow/transform/tests/fixture/separate-export-statement/output-step.js Updates expected output to inline registration IIFEs.
packages/swc-plugin-workflow/transform/tests/fixture/object-property-step/output-step.js Updates expected output to inline registration IIFEs for hoisted object-property steps.
packages/swc-plugin-workflow/transform/tests/fixture/object-property-step/output-client.js Moves stepId assignments to match new placement rules.
packages/swc-plugin-workflow/transform/tests/fixture/nested-steps-in-object-constructor/output-step.js Updates expected output to inline registration IIFEs for nested steps.
packages/swc-plugin-workflow/transform/tests/fixture/nested-step-with-closure/output-step.js Updates expected output to inline registration IIFEs + inlined closure-var access.
packages/swc-plugin-workflow/transform/tests/fixture/nested-step-in-workflow/output-step.js Updates expected output to inline registration IIFEs for workflow-nested steps.
packages/swc-plugin-workflow/transform/tests/fixture/multiple-const-step-functions/output-step.js Updates expected output to inline registration IIFEs for multi-declarator var statements.
packages/swc-plugin-workflow/transform/tests/fixture/module-level-step/output-step.js Updates expected output to inline registration IIFEs.
packages/swc-plugin-workflow/transform/tests/fixture/mixed-functions/output-step.js Updates expected output to inline registration IIFEs.
packages/swc-plugin-workflow/transform/tests/fixture/let-arrow-step-function/output-step.js Updates expected output to inline registration IIFEs.
packages/swc-plugin-workflow/transform/tests/fixture/instance-method-step/output-step.js Updates expected output to inline registration IIFEs for instance methods.
packages/swc-plugin-workflow/transform/tests/fixture/instance-method-nested-step/output-step.js Updates expected output to inline registration IIFEs for helper + instance method.
packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/output-step.js Updates expected output to inline registration IIFEs for factory step method.
packages/swc-plugin-workflow/transform/tests/fixture/factory-with-step-method/output-client.js Moves stepId assignment to match new placement rules.
packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-named/output-step.js Updates expected output to inline registration IIFEs for default-export class method.
packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-anonymous/output-step.js Updates expected output to inline registration IIFEs for rewritten default class binding.
packages/swc-plugin-workflow/transform/tests/fixture/export-default-class-anonymous-step-only/output-step.js Updates expected output to inline registration IIFEs for rewritten default class binding.
packages/swc-plugin-workflow/transform/tests/fixture/destructuring/output-step.js Updates expected output to inline registration IIFEs.
packages/swc-plugin-workflow/transform/tests/fixture/deeply-nested-step/output-step.js Updates expected output to inline registration IIFEs.
packages/swc-plugin-workflow/transform/tests/fixture/deeply-nested-step/output-client.js Moves stepId assignment to match new placement rules.
packages/swc-plugin-workflow/transform/tests/fixture/closure-typescript-expressions/output-step.js Updates expected output to inline registration + inlined closure-var access.
packages/swc-plugin-workflow/transform/tests/fixture/closure-new-expr-and-module-declarations/output-step.js Updates expected output to inline registration + inlined closure-var access.
packages/swc-plugin-workflow/transform/tests/fixture/class-expression-binding-name-step-methods/output-step.js Updates expected output to inline registration IIFEs for binding-name class expr methods.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step/output-step.js Updates expected output to inline registration IIFEs for tool execute steps.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step/output-client.js Moves stepId assignment to match new placement rules.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step-shorthand-method/output-step.js Updates expected output to inline registration IIFEs for shorthand methods.
packages/swc-plugin-workflow/transform/tests/fixture/agent-with-tool-step-shorthand-method/output-client.js Moves stepId assignment to match new placement rules.
packages/swc-plugin-workflow/transform/tests/errors/non-async-functions/output-step.js Updates expected error fixture output to inline registration IIFEs.
packages/swc-plugin-workflow/transform/tests/errors/misplaced-function-directive/output-step.js Updates expected error fixture output to inline registration IIFEs.
packages/swc-plugin-workflow/transform/tests/errors/invalid-exports/output-step.js Updates expected error fixture output to inline registration IIFEs.
packages/swc-plugin-workflow/transform/tests/errors/instance-methods/output-step.js Updates expected error fixture output to inline registration IIFEs for methods.
packages/swc-plugin-workflow/transform/tests/errors/conflicting-directives/output-step.js Updates expected error fixture output to inline registration IIFEs.
packages/swc-plugin-workflow/transform/src/lib.rs Implements inline step registration + inline closure-var accessor; removes private imports/registration batching.
packages/swc-plugin-workflow/spec.md Updates spec examples and narrative to describe new inline IIFE patterns.
packages/core/src/serialization.test.ts Updates internal test to import closure-var helper from its direct module.
packages/core/src/private.ts Documents new inline registration approach; stops re-exporting __private_getClosureVars.
packages/core/package.json Removes ./private export.
packages/core/e2e/e2e.test.ts Updates stack-trace assertions to stop referencing registerStepFunction.
docs/content/docs/how-it-works/code-transform.mdx Updates docs example to show inline IIFE registration output.
.changeset/remove-private-subpath.md Adds changeset for removing private subpath exports.
.changeset/inline-step-registration.md Adds changeset for SWC plugin output change to inline IIFEs.

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

…row behavior

- Remove stale 'Collect registration calls' comment from StepTransform
- Fix 'everyhwere' typo in e2e test comments
- Closure vars IIFE now throws when called outside a step function
  context, matching the original __private_getClosureVars behavior
Copy link
Copy Markdown
Member

@VaguelySerious VaguelySerious left a comment

Choose a reason for hiding this comment

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

AI review: blocking issues found

Address review feedback:
- Replace registerStepFunction() calls in getter step registrations with
  self.create_inline_step_registration() to match the inline IIFE pattern
  used by all other step registrations (the import was removed by this PR)
- Update spec.md closure vars example to include throw guard
- Update spec.md getter sections to show inline IIFE pattern instead of
  registerStepFunction
@TooTallNate TooTallNate merged commit 0a86de3 into main Apr 8, 2026
101 of 102 checks passed
@TooTallNate TooTallNate deleted the inline-step-registration branch April 8, 2026 23:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants