Skip to content

Make serialization functions async with Encryptor interface#955

Closed
TooTallNate wants to merge 1 commit intomainfrom
nate/async-serialization
Closed

Make serialization functions async with Encryptor interface#955
TooTallNate wants to merge 1 commit intomainfrom
nate/async-serialization

Conversation

@TooTallNate
Copy link
Copy Markdown
Member

Summary

  • Adds Encryptor, EncryptionContext, and KeyMaterial interfaces to @workflow/world
  • Makes World extend Encryptor (all methods are optional, so existing implementations are unaffected)
  • Converts all 8 dehydrate/hydrate functions in serialization.ts to async with new runId and encryptor parameters
  • Adds runId and world to WorkflowOrchestratorContext for threading encryption context through the workflow lifecycle
  • Updates all callers throughout: runtime, step handler, suspension handler, resume-hook, observability, CLI, web-shared, workbenches, world-testing, and tests

This is a no-op refactor — the encryptor parameter is unused (prefixed with _) in this PR. All callers pass {} as the encryptor. The actual encryption logic will be wired in a subsequent PR.

Stack

Test plan

All 303 core tests pass. Build succeeds.

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Feb 6, 2026

Copilot AI review requested due to automatic review settings February 6, 2026 02:29
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Feb 6, 2026

🦋 Changeset detected

Latest commit: 7b2edf6

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

This PR includes changesets to release 19 packages
Name Type
@workflow/core Patch
@workflow/world Patch
@workflow/cli Patch
@workflow/web Patch
@workflow/world-testing Patch
@workflow/builders Patch
@workflow/next Patch
@workflow/nitro Patch
@workflow/web-shared Patch
workflow Patch
@workflow/world-local Patch
@workflow/world-postgres Patch
@workflow/world-vercel Patch
@workflow/astro Patch
@workflow/nest Patch
@workflow/rollup Patch
@workflow/sveltekit Patch
@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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 6, 2026

🧪 E2E Test Results

Some tests failed

Summary

Passed Failed Skipped Total
✅ ▲ Vercel Production 490 0 38 528
✅ 💻 Local Development 418 0 62 480
✅ 📦 Local Production 418 0 62 480
✅ 🐘 Local Postgres 418 0 62 480
✅ 🪟 Windows 45 0 3 48
❌ 🌍 Community Worlds 29 163 12 204
✅ 📋 Other 123 0 21 144
Total 1941 163 260 2364

❌ Failed Tests

🌍 Community Worlds (163 failed)

mongodb (40 failed):

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

redis (40 failed):

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

starter (42 failed):

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

turso (41 failed):

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

Details by Category

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

📋 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 adds encryption support infrastructure to the Workflow SDK as a no-op refactor, preparing for future E2E encryption implementation. It introduces Encryptor, EncryptionContext, and KeyMaterial interfaces to @workflow/world, extends the World interface to include optional encryption methods, and converts all 8 serialization functions (dehydrate/hydrate) to async with new runId and encryptor parameters.

Changes:

  • Added encryption interfaces (Encryptor, EncryptionContext, KeyMaterial) to @workflow/world package
  • Made all 8 serialization functions async and added runId and encryptor parameters (unused in this PR, prefixed with _)
  • Updated WorkflowOrchestratorContext to include runId and world for threading encryption context through workflow lifecycle
  • Updated all 200+ call sites across runtime, step handlers, hook handlers, CLI, web-shared, workbenches, and tests to await async hydration and pass new parameters

Reviewed changes

Copilot reviewed 42 out of 42 changed files in this pull request and generated no comments.

Show a summary per file
File Description
packages/world/src/interfaces.ts Added Encryptor, EncryptionContext, KeyMaterial interfaces; extended World to include Encryptor
packages/core/src/serialization.ts Converted all 8 dehydrate/hydrate functions to async with new runId and encryptor parameters
packages/core/src/serialization.test.ts Added test wrapper functions to maintain backward-compatible signatures for existing tests
packages/core/src/workflow.ts Updated runWorkflow to accept world parameter and pass it through orchestrator context
packages/core/src/private.ts Added runId and world to WorkflowOrchestratorContext interface
packages/core/src/workflow/hook.ts Updated to use async hydration with .then()/.catch() pattern in event consumer
packages/core/src/step.ts Updated to use async hydration with .then()/.catch() pattern in event consumer
packages/core/src/runtime/*.ts Updated start, run, step-handler, suspension-handler, resume-hook to await async serialization
packages/core/src/observability.ts Converted all hydration helper functions to async and properly await them
packages/cli/src/lib/inspect/output.ts Updated all hydration calls to properly await and pass world
packages/web-shared/src/api/workflow-server-actions.ts Converted hydrate helper to async and updated all callers to await
workbench//api/trigger All 15 workbench trigger endpoints updated to await hydration and pass empty runId/encryptor
packages/core/e2e/e2e.test.ts Removed withResolvers import and updated dehydrateWorkflowArguments call (missing cleanup on lines 96-97)
packages/core/e2e/bench.bench.ts Properly removed all references to ops variable

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

Copy link
Copy Markdown
Member Author

TooTallNate commented Feb 6, 2026

@TooTallNate TooTallNate force-pushed the nate/async-serialization branch from 8a2fcdc to 07fb637 Compare February 8, 2026 07:42
@TooTallNate TooTallNate force-pushed the nate/async-serialization branch from 07fb637 to f32020d Compare February 8, 2026 07:46
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 8, 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.031s (-10.7% 🟢) 1.005s (~) 0.974s 10 1.00x
💻 Local Nitro 0.032s (-1.9%) 1.005s (~) 0.973s 10 1.02x
💻 Local Next.js (Turbopack) 0.041s 1.005s 0.964s 10 1.31x
🐘 Postgres Nitro 0.301s (+36.2% 🔺) 1.009s (~) 0.708s 10 9.72x
🐘 Postgres Express 0.434s (+7.0% 🔺) 1.010s (-1.1%) 0.576s 10 13.99x
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 0.857s (-5.2% 🟢) 2.877s (+19.1% 🔺) 2.020s 10 1.00x
▲ Vercel Express 0.859s (-6.0% 🟢) 2.727s (+14.9% 🔺) 1.868s 10 1.00x
▲ Vercel Next.js (Turbopack) 0.894s (-8.5% 🟢) 2.804s (+0.9%) 1.911s 10 1.04x

🔍 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.101s 2.006s 0.904s 10 1.00x
💻 Local Express 1.102s (~) 2.005s (~) 0.903s 10 1.00x
💻 Local Nitro 1.105s (~) 2.005s (~) 0.901s 10 1.00x
🐘 Postgres Nitro 2.171s (-11.7% 🟢) 3.014s (~) 0.843s 10 1.97x
🐘 Postgres Express 2.307s (+2.2%) 3.015s (~) 0.708s 10 2.09x
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 2.627s (-3.8%) 3.579s (-12.3% 🟢) 0.952s 10 1.00x
▲ Vercel Express 2.635s (-1.1%) 3.874s (+8.4% 🔺) 1.240s 10 1.00x
▲ Vercel Nitro 2.681s (+2.9%) 3.942s (+3.4%) 1.261s 10 1.02x

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

workflow with 10 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Next.js (Turbopack) 10.709s 11.021s 0.312s 3 1.00x
💻 Local Nitro 10.822s (~) 11.021s (~) 0.199s 3 1.01x
💻 Local Express 10.827s (~) 11.021s (~) 0.194s 3 1.01x
🐘 Postgres Express 20.171s (~) 21.059s (~) 0.888s 2 1.88x
🐘 Postgres Nitro 20.299s (~) 21.054s (~) 0.754s 2 1.90x
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 19.098s (-2.1%) 20.649s (+1.0%) 1.551s 2 1.00x
▲ Vercel Nitro 19.099s (-2.4%) 20.123s (-5.1% 🟢) 1.024s 2 1.00x
▲ Vercel Express 19.745s (-0.7%) 22.467s (+5.6% 🔺) 2.721s 2 1.03x

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

workflow with 25 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Next.js (Turbopack) 27.151s 28.049s 0.898s 3 1.00x
💻 Local Express 27.472s (~) 28.051s (~) 0.579s 3 1.01x
💻 Local Nitro 27.487s (~) 28.051s (~) 0.564s 3 1.01x
🐘 Postgres Nitro 50.352s (~) 51.139s (~) 0.787s 2 1.85x
🐘 Postgres Express 50.478s (~) 51.127s (~) 0.649s 2 1.86x
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 48.630s (~) 50.145s (~) 1.515s 2 1.00x
▲ Vercel Nitro 48.834s (~) 50.305s (-0.6%) 1.471s 2 1.00x
▲ Vercel Next.js (Turbopack) 51.682s (+2.0%) 53.957s (+3.0%) 2.275s 2 1.06x

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

workflow with 50 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Next.js (Turbopack) 56.509s 57.104s 0.595s 2 1.00x
💻 Local Express 57.075s (~) 57.601s (~) 0.526s 2 1.01x
💻 Local Nitro 57.236s (~) 58.101s (~) 0.864s 2 1.01x
🐘 Postgres Express 100.196s (~) 100.213s (-1.0%) 0.017s 1 1.77x
🐘 Postgres Nitro 100.531s (~) 101.243s (~) 0.712s 1 1.78x
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 99.867s (-5.3% 🟢) 101.818s (-4.7%) 1.951s 1 1.00x
▲ Vercel Nitro 102.638s (-2.1%) 104.169s (-2.4%) 1.531s 1 1.03x
▲ Vercel Next.js (Turbopack) 102.723s (+1.5%) 103.516s (+0.7%) 0.793s 1 1.03x

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

Promise.all with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Express 1.403s (-0.8%) 2.005s (~) 0.602s 15 1.00x
💻 Local Next.js (Turbopack) 1.405s 2.004s 0.599s 15 1.00x
💻 Local Nitro 1.424s (+2.2%) 2.006s (~) 0.582s 15 1.02x
🐘 Postgres Express 2.274s (-2.6%) 3.014s (~) 0.740s 10 1.62x
🐘 Postgres Nitro 2.554s (+10.9% 🔺) 3.013s (~) 0.459s 10 1.82x
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 2.790s (-27.0% 🟢) 4.445s (-23.0% 🟢) 1.655s 7 1.00x
▲ Vercel Next.js (Turbopack) 2.812s (-5.9% 🟢) 4.062s (-3.9%) 1.251s 8 1.01x
▲ Vercel Express 3.164s (-3.1%) 4.638s (+2.8%) 1.474s 7 1.13x

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

Promise.all with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Next.js (Turbopack) 2.517s 3.006s 0.490s 10 1.00x
💻 Local Express 2.557s (+0.9%) 3.007s (~) 0.450s 10 1.02x
💻 Local Nitro 2.636s (+0.8%) 3.007s (~) 0.371s 10 1.05x
🐘 Postgres Express 8.667s (-2.8%) 9.035s (-2.7%) 0.368s 4 3.44x
🐘 Postgres Nitro 10.017s (+17.6% 🔺) 10.700s (+21.9% 🔺) 0.683s 3 3.98x
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 3.112s (-8.2% 🟢) 4.493s (+0.7%) 1.380s 7 1.00x
▲ Vercel Express 3.394s (+7.3% 🔺) 4.695s (+7.6% 🔺) 1.301s 7 1.09x
▲ Vercel Next.js (Turbopack) 4.336s (+36.5% 🔺) 5.606s (+25.8% 🔺) 1.270s 6 1.39x

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

Promise.all with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Next.js (Turbopack) 6.896s 7.415s 0.518s 5 1.00x
💻 Local Express 7.137s (+1.4%) 7.767s (~) 0.630s 4 1.03x
💻 Local Nitro 7.609s (+2.3%) 8.017s (~) 0.408s 4 1.10x
🐘 Postgres Nitro 47.120s (-6.9% 🟢) 48.118s (-5.9% 🟢) 0.998s 1 6.83x
🐘 Postgres Express 49.586s (+1.5%) 50.148s (+2.1%) 0.562s 1 7.19x
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 3.651s (-5.9% 🟢) 5.254s (-2.1%) 1.604s 6 1.00x
▲ Vercel Nitro 3.737s (-0.6%) 5.738s (-1.8%) 2.000s 6 1.02x
▲ Vercel Express 4.076s (+16.5% 🔺) 5.627s (+7.1% 🔺) 1.552s 6 1.12x

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

Promise.race with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Express 1.418s (~) 2.005s (~) 0.586s 15 1.00x
💻 Local Next.js (Turbopack) 1.420s 2.005s 0.585s 15 1.00x
💻 Local Nitro 1.432s (~) 2.005s (~) 0.574s 15 1.01x
🐘 Postgres Nitro 2.023s (~) 2.474s (+6.7% 🔺) 0.451s 13 1.43x
🐘 Postgres Express 2.087s (-4.9%) 2.319s (-13.4% 🟢) 0.233s 13 1.47x
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.664s (-8.3% 🟢) 3.870s (-2.5%) 1.206s 8 1.00x
▲ Vercel Nitro 2.671s (-5.1% 🟢) 3.914s (-2.6%) 1.242s 8 1.00x
▲ Vercel Next.js (Turbopack) 2.680s (-10.7% 🟢) 3.755s (-18.0% 🟢) 1.075s 8 1.01x

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

Promise.race with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Express 2.637s (-1.2%) 3.007s (~) 0.370s 10 1.00x
💻 Local Next.js (Turbopack) 2.657s 3.011s 0.353s 10 1.01x
💻 Local Nitro 2.707s (-0.6%) 3.008s (~) 0.301s 10 1.03x
🐘 Postgres Express 10.315s (-19.0% 🟢) 10.697s (-20.0% 🟢) 0.382s 3 3.91x
🐘 Postgres Nitro 12.648s (+11.0% 🔺) 13.042s (+11.5% 🔺) 0.394s 3 4.80x
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.839s (~) 3.922s (-2.9%) 1.083s 8 1.00x
▲ Vercel Nitro 2.907s (-0.7%) 4.240s (-7.4% 🟢) 1.334s 8 1.02x
▲ Vercel Next.js (Turbopack) 3.357s (+12.7% 🔺) 4.602s (+10.7% 🔺) 1.245s 7 1.18x

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

Promise.race with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Next.js (Turbopack) 7.718s 8.015s 0.297s 4 1.00x
💻 Local Express 7.779s (+2.1%) 8.019s (~) 0.240s 4 1.01x
💻 Local Nitro 7.881s (-1.5%) 8.271s (-5.7% 🟢) 0.390s 4 1.02x
🐘 Postgres Nitro 51.476s (+1.2%) 52.118s (+2.0%) 0.642s 1 6.67x
🐘 Postgres Express 51.743s (-1.3%) 52.122s (-1.9%) 0.379s 1 6.70x
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 3.562s (-2.6%) 5.559s (+13.3% 🔺) 1.997s 6 1.00x
▲ Vercel Express 3.801s (-0.9%) 5.080s (-0.7%) 1.279s 6 1.07x
▲ Vercel Next.js (Turbopack) 3.936s (+14.5% 🔺) 5.236s (+1.2%) 1.300s 6 1.10x

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

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.145s 1.001s 0.010s 1.015s 0.870s 10 1.00x
💻 Local Express 0.170s (-3.8%) 1.002s (~) 0.010s (+5.3% 🔺) 1.015s (~) 0.845s 10 1.17x
💻 Local Nitro 0.175s (~) 1.002s (~) 0.010s (-10.7% 🟢) 1.015s (~) 0.840s 10 1.20x
🐘 Postgres Nitro 2.130s (-11.3% 🟢) 2.913s (+10.4% 🔺) 0.001s (+8.3% 🔺) 3.015s (~) 0.885s 10 14.67x
🐘 Postgres Express 2.328s (+7.5% 🔺) 2.715s (-5.6% 🟢) 0.001s (~) 3.014s (~) 0.686s 10 16.04x
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - - -

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 2.416s (-9.1% 🟢) 3.098s (+0.6%) 0.172s (+29.0% 🔺) 4.047s (+0.8%) 1.631s 10 1.00x
▲ Vercel Express 2.466s (-1.9%) 3.140s (+5.3% 🔺) 0.145s (-46.6% 🟢) 4.104s (+2.5%) 1.638s 10 1.02x
▲ Vercel Next.js (Turbopack) 2.545s (-13.4% 🟢) 3.078s (-17.0% 🟢) 0.149s (-10.2% 🟢) 3.913s (-18.0% 🟢) 1.368s 10 1.05x

🔍 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) 8/12
🐘 Postgres Nitro 7/12
▲ Vercel Nitro 5/12
Fastest World by Framework

Winner determined by most benchmark wins

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

Worlds:

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

📋 View full workflow run

Copy link
Copy Markdown
Contributor

@pranaygp pranaygp left a comment

Choose a reason for hiding this comment

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

Review: PR #955 - Make serialization functions async with Encryptor interface

This PR appears to combine what has been split into #978 and #979 in the newer stack. Since the split versions are cleaner (separating the async refactor from the Encryptor interface threading), I'd recommend closing this in favor of the split stack: #978 -> #979 -> #956 -> #957.

Detailed reviews are on the individual PRs in the split stack.

@TooTallNate
Copy link
Copy Markdown
Member Author

Good bot

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