Skip to content

[world-vercel] Switch event endpoints to v4 wire format#2055

Draft
VaguelySerious wants to merge 11 commits into
mainfrom
peter/v4
Draft

[world-vercel] Switch event endpoints to v4 wire format#2055
VaguelySerious wants to merge 11 commits into
mainfrom
peter/v4

Conversation

@VaguelySerious
Copy link
Copy Markdown
Member

@VaguelySerious VaguelySerious commented May 21, 2026

Draft. Switches the world-vercel adapter's event endpoints from v2/v3 to v4. Companion to workflow-server PR #439; both land together.

What changes

The adapter's createWorkflowRunEvent / getEvent / getWorkflowRunEvents keep their public signatures and the EventResult / Event / PaginatedResponse<Event> shapes the workflow runtime consumes. What changes is what's on the wire under those calls:

  • Event metadata rides in x-wf-* HTTP request/response headers instead of inside the body.
  • User payloads stream end-to-end as opaque bytes. The SDK CBOR-encodes at the eventData[field] boundary on write and CBOR-decodes on read; the server treats the bytes as opaque and streams them straight to S3.
  • POST event response carries the materialized EventResult as a CBOR body. The runtime reads e.g. result.run.startedAt immediately after POST without a second round-trip.
  • LIST events response is now the v4 binary-frame stream (application/vnd.workflow.v4-frames). One frame per event with CBOR metadata + raw payload bytes inline. The per-event /refs round-trip used by the v3 client is gone.

What goes away

  • packages/world-vercel/src/refs.ts — deleted. The /refs hydration path is no longer used.
  • hydrateEventRefs / collectPendingRefs / eventDataRefFieldMap and the wire schemas (EventResultResolveWireSchema, EventResultLazyWireSchema, EventWithRefsSchema) — deleted from events.ts.
  • The lazy-refs branching in createWorkflowRunEvent — the server still respects remoteRefBehavior (passed via header for eventsNeedingResolve types) and bakes the resolution decision into its CBOR response, so the SDK has nothing to do.

Net diff: +297 / -601 lines on this PR.

What stays

  • v1Compat path in createWorkflowRunEvent — still uses /v1 endpoints for legacy SDK migrations that haven't moved to event sourcing. v4 doesn't cover these.
  • validateUlidTimestamp on run_created, the HookNotFoundError translation on hook 404s, and the stripEventDataRefs path for resolveData='none'.
  • events-v4.ts is now an internal helper module — not re-exported from the package's public API.

Not yet covered (by design)

  • storage.events.listByCorrelationId throws a clear error explaining the v4 server has no by-correlation-id list endpoint. The runtime mostly used this for hook lookups, which can use storage.hooks.getByToken instead. If real callers need it, a follow-up server PR can add /api/v4/events?correlationId=.

Test plan

  • pnpm --filter @workflow/world-vercel build clean
  • pnpm --filter @workflow/world-vercel test — 79/79 pass
  • pnpm build (full workspace) — 27/27 packages build
  • WORKFLOW_SERVER_URL_OVERRIDE on this branch points at the workflow-server PR Fix command injection vulnerability in CI workflow via untrusted fork PR #439 preview deployment for e2e tests.
  • E2E green against the v4-enabled workflow-server preview.

🤖 Generated with Claude Code

Mirrors the v4 server-side handlers landing in workflow-server. The
v4 wire format moves event metadata into x-wf-* request/response
headers and treats payloads as opaque user-data bytes (streamed
end-to-end). The SDK passes Uint8Array bytes through unchanged at
this layer; higher-level world-vercel adapter glue handles CBOR.

Adds:
  - packages/world-vercel/src/frames.ts: encoder + async-iterable
    decoder for the length-prefixed binary frame format used by the
    v4 list-events response.
  - packages/world-vercel/src/events-v4.ts: three new functions:
    * createWorkflowRunEventV4 — POST with x-wf-* headers + payload
      bytes, returns event/run ids and timestamp from response
      headers.
    * getEventV4 — GET single event, returns metadata + body bytes.
    * getWorkflowRunEventsV4 — GET list, parses frame stream, returns
      events + pagination cursor.
  - V4_HEADERS exported as the canonical name map; mirrors the
    server-side constant.

V4 client characteristics:
  - Required runId in URL for run_created too (no /runs/null/events
    shortcut; the runId is part of the S3 key the server allocates).
    Higher-level callers generate the ULID client-side.
  - Payload bytes flow through without CBOR encode/decode on this
    layer. Callers CBOR-encode for parity with v3 if they want.
  - Pagination cursor surfaces in the LIST response — eliminates the
    per-large-payload /refs round-trip used by v2/v3.

Tests (10 new in src/frames.test.ts, no new e2e):
  - Canonical wire layout round-trip.
  - Multi-frame round-trip with pagination cursor.
  - Decoder survives 1-byte chunk delivery (matching spike B's chunk-
    boundary robustness requirement).
  - 64 KB body split across many small chunks.
  - Bodies containing 0xff padding don't mis-frame.
  - Back-to-back frames in a single chunk.
  - Truncated stream raises.
  - Meta CBOR types (numbers, booleans, arrays) preserved.

The world-vercel adapter still defaults to the v3 path; v4 is exposed
for direct callers and a follow-up PR will switch the adapter over
once the matching server-side PR is on staging.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 21, 2026

🦋 Changeset detected

Latest commit: a2dac63

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

This PR includes changesets to release 17 packages
Name Type
@workflow/world-vercel Major
@workflow/cli Patch
@workflow/core Patch
@workflow/web Patch
workflow Patch
@workflow/world-testing Patch
@workflow/builders Patch
@workflow/next Patch
@workflow/nitro Patch
@workflow/vitest Patch
@workflow/web-shared 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

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 21, 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 May 25, 2026 11:24am
example-nextjs-workflow-webpack Ready Ready Preview, Comment May 25, 2026 11:24am
example-workflow Ready Ready Preview, Comment May 25, 2026 11:24am
workbench-astro-workflow Ready Ready Preview, Comment May 25, 2026 11:24am
workbench-express-workflow Ready Ready Preview, Comment May 25, 2026 11:24am
workbench-fastify-workflow Ready Ready Preview, Comment May 25, 2026 11:24am
workbench-hono-workflow Ready Ready Preview, Comment May 25, 2026 11:24am
workbench-nitro-workflow Ready Ready Preview, Comment May 25, 2026 11:24am
workbench-nuxt-workflow Ready Ready Preview, Comment May 25, 2026 11:24am
workbench-sveltekit-workflow Ready Ready Preview, Comment May 25, 2026 11:24am
workbench-tanstack-start-workflow Ready Ready Preview, Comment May 25, 2026 11:24am
workbench-vite-workflow Ready Ready Preview, Comment May 25, 2026 11:24am
workflow-docs Ready Ready Preview, Comment, Open in v0 May 25, 2026 11:24am
workflow-swc-playground Ready Ready Preview, Comment May 25, 2026 11:24am
workflow-tarballs Ready Ready Preview, Comment May 25, 2026 11:24am
workflow-web Ready Ready Preview, Comment May 25, 2026 11:24am

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 21, 2026

🧪 E2E Test Results

Some tests failed

Summary

Passed Failed Skipped Total
❌ ▲ Vercel Production 707 515 219 1441
✅ 💻 Local Development 1615 0 219 1834
✅ 📦 Local Production 1615 0 219 1834
✅ 🐘 Local Postgres 1615 0 219 1834
✅ 🪟 Windows 131 0 0 131
❌ 📋 Other 701 40 176 917
Total 6384 555 1052 7991

❌ Failed Tests

▲ Vercel Production (515 failed)

astro (40 failed):

  • readableStreamWorkflow | wrun_01KSFDYJFXKP83SFPBK3JSWR8Q | 🔍 observability
  • sleepingWorkflow | wrun_01KSFDZEV911J8N1F7FEHRKQ6H | 🔍 observability
  • parallelSleepWorkflow | wrun_01KSFDZVJD93SD2NY1D4K5DG1J | 🔍 observability
  • sleepWinsRaceWorkflow | wrun_01KSFDZZ0TNA38TQEZFF9H9JBE | 🔍 observability
  • stepWinsRaceWorkflow | wrun_01KSFE03PWZ0QV17TNSPRNJ1R6 | 🔍 observability
  • 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 getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KSFE2MBPJYYB45E4QP8REHK8 | 🔍 observability
  • utf8StreamWorkflow | wrun_01KSFE4FCNATPSA27Z0CRS48E6 | 🔍 observability
  • 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 maxRetries=0 disables retries
  • error handling catchability step throw round-trips FatalError with cause chain to workflow catch
  • error handling catchability step throw of a non-Error value preserves it as cause on the wrapping FatalError
  • 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
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KSFECB9DD6AY6THG75R9AJKP | 🔍 observability
  • hookWithSleepWorkflow - hook payloads delivered correctly with concurrent sleep | wrun_01KSFEM0CAWQ6PT3WTQ0DBXC87 | 🔍 observability
  • hookWithSleepFinalStepWorkflow - step only on final payload | wrun_01KSFEM63ZS74X0XQZQFQZRJ8J | 🔍 observability
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KSFEMGS77B4KNQCAJ2DZNHQY | 🔍 observability
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KSFEPBSRTBBCQ40QPRNG5CXH | 🔍 observability
  • AbortController abortTimeoutWorkflow: timeout cancels long-running step
  • AbortController abortParallelWorkflow: abort cancels all parallel steps
  • AbortController abortReasonWorkflow: abort reason preserved across boundaries
  • AbortController abortSurvivesReplayWorkflow: controller state consistent across replay
  • AbortController abortFetchInFlightWorkflow: aborting cancels an in-flight fetch
  • AbortController abortVoidSleepTimeoutWorkflow: documented void sleep().then(abort) pattern works
  • AbortController abortDeterministicBranchWorkflow: if-check takes same path on first-run and replay
  • AbortController abortDeterministicBranchFromStepWorkflow: branches stay consistent when abort comes from a step
  • AbortController abortHookOrderingWorkflow [listener-first-abort-first]: addEventListener → hook.then → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [listener-first-hook-first]: addEventListener → hook.then → resumeHook → abort()
  • AbortController abortHookOrderingWorkflow [hook-first-abort-first]: hook.then → addEventListener → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [hook-first-hook-first]: hook.then → addEventListener → resumeHook → abort()
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KSFEWRKNFV18RP86W9QGFN5J | 🔍 observability
  • distributedAbortController - manual abort triggers signal | wrun_01KSFEXA755PBRHSNMJPAYD569 | 🔍 observability
  • distributedAbortController - TTL expiration triggers signal | wrun_01KSFEZ553M5PKK0C2HS7QHM8B | 🔍 observability
  • distributedAbortController - reconnect to existing controller | wrun_01KSFF02SATTJ0EPM1WQFYHRMW | 🔍 observability

example (38 failed):

  • sleepingWorkflow | wrun_01KSFDZEV911J8N1F7FEHRKQ6H | 🔍 observability
  • parallelSleepWorkflow | wrun_01KSFDZVJD93SD2NY1D4K5DG1J | 🔍 observability
  • sleepWinsRaceWorkflow | wrun_01KSFDZZ0TNA38TQEZFF9H9JBE | 🔍 observability
  • stepWinsRaceWorkflow | wrun_01KSFE03PWZ0QV17TNSPRNJ1R6 | 🔍 observability
  • 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 getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KSFE2MBPJYYB45E4QP8REHK8 | 🔍 observability
  • utf8StreamWorkflow | wrun_01KSFE4FCNATPSA27Z0CRS48E6 | 🔍 observability
  • 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 maxRetries=0 disables retries
  • error handling catchability step throw round-trips FatalError with cause chain to workflow catch
  • error handling catchability step throw of a non-Error value preserves it as cause on the wrapping FatalError
  • 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
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KSFECB9DD6AY6THG75R9AJKP | 🔍 observability
  • hookWithSleepWorkflow - hook payloads delivered correctly with concurrent sleep | wrun_01KSFEM0CAWQ6PT3WTQ0DBXC87 | 🔍 observability
  • hookWithSleepFinalStepWorkflow - step only on final payload | wrun_01KSFEM63ZS74X0XQZQFQZRJ8J | 🔍 observability
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KSFEMGS77B4KNQCAJ2DZNHQY | 🔍 observability
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KSFEPBSRTBBCQ40QPRNG5CXH | 🔍 observability
  • AbortController abortTimeoutWorkflow: timeout cancels long-running step
  • AbortController abortParallelWorkflow: abort cancels all parallel steps
  • AbortController abortReasonWorkflow: abort reason preserved across boundaries
  • AbortController abortSurvivesReplayWorkflow: controller state consistent across replay
  • AbortController abortFetchInFlightWorkflow: aborting cancels an in-flight fetch
  • AbortController abortVoidSleepTimeoutWorkflow: documented void sleep().then(abort) pattern works
  • AbortController abortDeterministicBranchFromStepWorkflow: branches stay consistent when abort comes from a step
  • AbortController abortHookOrderingWorkflow [listener-first-abort-first]: addEventListener → hook.then → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [listener-first-hook-first]: addEventListener → hook.then → resumeHook → abort()
  • AbortController abortHookOrderingWorkflow [hook-first-abort-first]: hook.then → addEventListener → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [hook-first-hook-first]: hook.then → addEventListener → resumeHook → abort()
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KSFEWRKNFV18RP86W9QGFN5J | 🔍 observability
  • distributedAbortController - manual abort triggers signal | wrun_01KSFEXA755PBRHSNMJPAYD569 | 🔍 observability
  • distributedAbortController - TTL expiration triggers signal | wrun_01KSFEZ553M5PKK0C2HS7QHM8B | 🔍 observability
  • distributedAbortController - reconnect to existing controller | wrun_01KSFF02SATTJ0EPM1WQFYHRMW | 🔍 observability

express (40 failed):

  • sleepingWorkflow | wrun_01KSFDZEV911J8N1F7FEHRKQ6H | 🔍 observability
  • parallelSleepWorkflow | wrun_01KSFDZVJD93SD2NY1D4K5DG1J | 🔍 observability
  • sleepWinsRaceWorkflow | wrun_01KSFDZZ0TNA38TQEZFF9H9JBE | 🔍 observability
  • stepWinsRaceWorkflow | wrun_01KSFE03PWZ0QV17TNSPRNJ1R6 | 🔍 observability
  • 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 getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KSFE2MBPJYYB45E4QP8REHK8 | 🔍 observability
  • utf8StreamWorkflow | wrun_01KSFE4FCNATPSA27Z0CRS48E6 | 🔍 observability
  • 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 RetryableError respects custom retryAfter delay
  • error handling retry behavior maxRetries=0 disables retries
  • error handling catchability step throw round-trips FatalError with cause chain to workflow catch
  • error handling catchability step throw of a non-Error value preserves it as cause on the wrapping FatalError
  • 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
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KSFECB9DD6AY6THG75R9AJKP | 🔍 observability
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_01KSFEJ9G1KB6YE6984RZ12CDX | 🔍 observability
  • hookWithSleepWorkflow - hook payloads delivered correctly with concurrent sleep | wrun_01KSFEM0CAWQ6PT3WTQ0DBXC87 | 🔍 observability
  • hookWithSleepFinalStepWorkflow - step only on final payload | wrun_01KSFEM63ZS74X0XQZQFQZRJ8J | 🔍 observability
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KSFEMGS77B4KNQCAJ2DZNHQY | 🔍 observability
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KSFEPBSRTBBCQ40QPRNG5CXH | 🔍 observability
  • AbortController abortTimeoutWorkflow: timeout cancels long-running step
  • AbortController abortParallelWorkflow: abort cancels all parallel steps
  • AbortController abortReasonWorkflow: abort reason preserved across boundaries
  • AbortController abortSurvivesReplayWorkflow: controller state consistent across replay
  • AbortController abortFetchInFlightWorkflow: aborting cancels an in-flight fetch
  • AbortController abortVoidSleepTimeoutWorkflow: documented void sleep().then(abort) pattern works
  • AbortController abortDeterministicBranchFromStepWorkflow: branches stay consistent when abort comes from a step
  • AbortController abortHookOrderingWorkflow [listener-first-abort-first]: addEventListener → hook.then → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [listener-first-hook-first]: addEventListener → hook.then → resumeHook → abort()
  • AbortController abortHookOrderingWorkflow [hook-first-abort-first]: hook.then → addEventListener → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [hook-first-hook-first]: hook.then → addEventListener → resumeHook → abort()
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KSFEWRKNFV18RP86W9QGFN5J | 🔍 observability
  • distributedAbortController - manual abort triggers signal | wrun_01KSFEXA755PBRHSNMJPAYD569 | 🔍 observability
  • distributedAbortController - TTL expiration triggers signal | wrun_01KSFEZ553M5PKK0C2HS7QHM8B | 🔍 observability
  • distributedAbortController - reconnect to existing controller | wrun_01KSFF02SATTJ0EPM1WQFYHRMW | 🔍 observability

fastify (39 failed):

  • sleepingWorkflow | wrun_01KSFDZEV911J8N1F7FEHRKQ6H | 🔍 observability
  • parallelSleepWorkflow | wrun_01KSFDZVJD93SD2NY1D4K5DG1J | 🔍 observability
  • sleepWinsRaceWorkflow | wrun_01KSFDZZ0TNA38TQEZFF9H9JBE | 🔍 observability
  • stepWinsRaceWorkflow | wrun_01KSFE03PWZ0QV17TNSPRNJ1R6 | 🔍 observability
  • 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 getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KSFE2MBPJYYB45E4QP8REHK8 | 🔍 observability
  • utf8StreamWorkflow | wrun_01KSFE4FCNATPSA27Z0CRS48E6 | 🔍 observability
  • 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 maxRetries=0 disables retries
  • error handling catchability step throw round-trips FatalError with cause chain to workflow catch
  • error handling catchability step throw of a non-Error value preserves it as cause on the wrapping FatalError
  • 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
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KSFECB9DD6AY6THG75R9AJKP | 🔍 observability
  • errorSubclassRoundTripWorkflow - first-class Error subclasses survive every serialization boundary | wrun_01KSFEK5GK4KW81WTWVFJ3P86G | 🔍 observability
  • hookWithSleepWorkflow - hook payloads delivered correctly with concurrent sleep | wrun_01KSFEM0CAWQ6PT3WTQ0DBXC87 | 🔍 observability
  • hookWithSleepFinalStepWorkflow - step only on final payload | wrun_01KSFEM63ZS74X0XQZQFQZRJ8J | 🔍 observability
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KSFEMGS77B4KNQCAJ2DZNHQY | 🔍 observability
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KSFEPBSRTBBCQ40QPRNG5CXH | 🔍 observability
  • AbortController abortTimeoutWorkflow: timeout cancels long-running step
  • AbortController abortParallelWorkflow: abort cancels all parallel steps
  • AbortController abortReasonWorkflow: abort reason preserved across boundaries
  • AbortController abortSurvivesReplayWorkflow: controller state consistent across replay
  • AbortController abortFetchInFlightWorkflow: aborting cancels an in-flight fetch
  • AbortController abortVoidSleepTimeoutWorkflow: documented void sleep().then(abort) pattern works
  • AbortController abortDeterministicBranchFromStepWorkflow: branches stay consistent when abort comes from a step
  • AbortController abortHookOrderingWorkflow [listener-first-abort-first]: addEventListener → hook.then → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [listener-first-hook-first]: addEventListener → hook.then → resumeHook → abort()
  • AbortController abortHookOrderingWorkflow [hook-first-abort-first]: hook.then → addEventListener → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [hook-first-hook-first]: hook.then → addEventListener → resumeHook → abort()
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KSFEWRKNFV18RP86W9QGFN5J | 🔍 observability
  • distributedAbortController - manual abort triggers signal | wrun_01KSFEXA755PBRHSNMJPAYD569 | 🔍 observability
  • distributedAbortController - TTL expiration triggers signal | wrun_01KSFEZ553M5PKK0C2HS7QHM8B | 🔍 observability
  • distributedAbortController - reconnect to existing controller | wrun_01KSFF02SATTJ0EPM1WQFYHRMW | 🔍 observability

hono (41 failed):

  • sleepingWorkflow | wrun_01KSFDZEV911J8N1F7FEHRKQ6H | 🔍 observability
  • parallelSleepWorkflow | wrun_01KSFDZVJD93SD2NY1D4K5DG1J | 🔍 observability
  • sleepWinsRaceWorkflow | wrun_01KSFDZZ0TNA38TQEZFF9H9JBE | 🔍 observability
  • stepWinsRaceWorkflow | wrun_01KSFE03PWZ0QV17TNSPRNJ1R6 | 🔍 observability
  • workflowAndStepMetadataWorkflow | wrun_01KSFE092CVGYV32MNEQEXKVM9 | 🔍 observability
  • 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 getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KSFE2MBPJYYB45E4QP8REHK8 | 🔍 observability
  • utf8StreamWorkflow | wrun_01KSFE4FCNATPSA27Z0CRS48E6 | 🔍 observability
  • 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 maxRetries=0 disables retries
  • error handling catchability step throw round-trips FatalError with cause chain to workflow catch
  • error handling catchability step throw of a non-Error value preserves it as cause on the wrapping FatalError
  • 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
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KSFECB9DD6AY6THG75R9AJKP | 🔍 observability
  • startFromWorkflow - calling start() directly inside a workflow function with hook communication | wrun_01KSFEH3S9JCC5CA5QZN0B1G9Y | 🔍 observability
  • hookWithSleepWorkflow - hook payloads delivered correctly with concurrent sleep | wrun_01KSFEM0CAWQ6PT3WTQ0DBXC87 | 🔍 observability
  • hookWithSleepFinalStepWorkflow - step only on final payload | wrun_01KSFEM63ZS74X0XQZQFQZRJ8J | 🔍 observability
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KSFEMGS77B4KNQCAJ2DZNHQY | 🔍 observability
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KSFEPBSRTBBCQ40QPRNG5CXH | 🔍 observability
  • AbortController abortTimeoutWorkflow: timeout cancels long-running step
  • AbortController abortParallelWorkflow: abort cancels all parallel steps
  • AbortController abortReasonWorkflow: abort reason preserved across boundaries
  • AbortController abortSurvivesReplayWorkflow: controller state consistent across replay
  • AbortController abortFetchInFlightWorkflow: aborting cancels an in-flight fetch
  • AbortController abortVoidSleepTimeoutWorkflow: documented void sleep().then(abort) pattern works
  • AbortController abortDeterministicBranchWorkflow: if-check takes same path on first-run and replay
  • AbortController abortDeterministicBranchFromStepWorkflow: branches stay consistent when abort comes from a step
  • AbortController abortHookOrderingWorkflow [listener-first-abort-first]: addEventListener → hook.then → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [listener-first-hook-first]: addEventListener → hook.then → resumeHook → abort()
  • AbortController abortHookOrderingWorkflow [hook-first-abort-first]: hook.then → addEventListener → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [hook-first-hook-first]: hook.then → addEventListener → resumeHook → abort()
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KSFEWRKNFV18RP86W9QGFN5J | 🔍 observability
  • distributedAbortController - manual abort triggers signal | wrun_01KSFEXA755PBRHSNMJPAYD569 | 🔍 observability
  • distributedAbortController - TTL expiration triggers signal | wrun_01KSFEZ553M5PKK0C2HS7QHM8B | 🔍 observability
  • distributedAbortController - reconnect to existing controller | wrun_01KSFF02SATTJ0EPM1WQFYHRMW | 🔍 observability

nextjs-turbopack (44 failed):

  • promiseAllWorkflow | wrun_01KSFDXS3QPMH2SZ23ZTCYKKJP | 🔍 observability
  • sleepingWorkflow | wrun_01KSFDZEV911J8N1F7FEHRKQ6H | 🔍 observability
  • parallelSleepWorkflow | wrun_01KSFDZVJD93SD2NY1D4K5DG1J | 🔍 observability
  • sleepWinsRaceWorkflow | wrun_01KSFDZZ0TNA38TQEZFF9H9JBE | 🔍 observability
  • stepWinsRaceWorkflow | wrun_01KSFE03PWZ0QV17TNSPRNJ1R6 | 🔍 observability
  • 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 getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KSFE2MBPJYYB45E4QP8REHK8 | 🔍 observability
  • utf8StreamWorkflow | wrun_01KSFE4FCNATPSA27Z0CRS48E6 | 🔍 observability
  • promiseRaceStressTestWorkflow | wrun_01KSFE8CJ6VYTP73TXT92DH7BC | 🔍 observability
  • 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 maxRetries=0 disables retries
  • error handling catchability step throw round-trips FatalError with cause chain to workflow catch
  • error handling catchability step throw of a non-Error value preserves it as cause on the wrapping FatalError
  • 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
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KSFECB9DD6AY6THG75R9AJKP | 🔍 observability
  • fibonacciWorkflow - recursive workflow composition via start() | wrun_01KSFEH6JJMVF81JT0DA56Q3JC | 🔍 observability
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_01KSFEHMD5F13712919SY6DEZA | 🔍 observability
  • errorSubclassRoundTripWorkflow - first-class Error subclasses survive every serialization boundary | wrun_01KSFEK5GK4KW81WTWVFJ3P86G | 🔍 observability
  • pages router sleepingWorkflow via pages router
  • hookWithSleepWorkflow - hook payloads delivered correctly with concurrent sleep | wrun_01KSFEM0CAWQ6PT3WTQ0DBXC87 | 🔍 observability
  • hookWithSleepFinalStepWorkflow - step only on final payload | wrun_01KSFEM63ZS74X0XQZQFQZRJ8J | 🔍 observability
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KSFEMGS77B4KNQCAJ2DZNHQY | 🔍 observability
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KSFEPBSRTBBCQ40QPRNG5CXH | 🔍 observability
  • AbortController abortTimeoutWorkflow: timeout cancels long-running step
  • AbortController abortParallelWorkflow: abort cancels all parallel steps
  • AbortController abortReasonWorkflow: abort reason preserved across boundaries
  • AbortController abortSurvivesReplayWorkflow: controller state consistent across replay
  • AbortController abortFetchInFlightWorkflow: aborting cancels an in-flight fetch
  • AbortController abortVoidSleepTimeoutWorkflow: documented void sleep().then(abort) pattern works
  • AbortController abortDeterministicBranchFromStepWorkflow: branches stay consistent when abort comes from a step
  • AbortController abortHookOrderingWorkflow [listener-first-abort-first]: addEventListener → hook.then → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [listener-first-hook-first]: addEventListener → hook.then → resumeHook → abort()
  • AbortController abortHookOrderingWorkflow [hook-first-abort-first]: hook.then → addEventListener → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [hook-first-hook-first]: hook.then → addEventListener → resumeHook → abort()
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KSFEWRKNFV18RP86W9QGFN5J | 🔍 observability
  • distributedAbortController - manual abort triggers signal | wrun_01KSFEXA755PBRHSNMJPAYD569 | 🔍 observability
  • distributedAbortController - TTL expiration triggers signal | wrun_01KSFEZ553M5PKK0C2HS7QHM8B | 🔍 observability
  • distributedAbortController - reconnect to existing controller | wrun_01KSFF02SATTJ0EPM1WQFYHRMW | 🔍 observability

nextjs-webpack (115 failed):

  • DurableAgent e2e core basic text response
  • DurableAgent e2e core single tool call
  • DurableAgent e2e core multiple sequential tool calls
  • DurableAgent e2e core tool error recovery
  • DurableAgent e2e onStepFinish fires constructor + stream callbacks in order with step data
  • DurableAgent e2e onFinish fires constructor + stream callbacks in order with event data
  • DurableAgent e2e provider tools provider tool identity preserved across step boundaries
  • DurableAgent e2e provider tools mixed provider and function tools
  • DurableAgent e2e instructions string instructions are passed to the model
  • DurableAgent e2e timeout completes within timeout
  • DurableAgent e2e experimental_onStart (GAP) completes but callbacks are not called (GAP)
  • DurableAgent e2e experimental_onStepStart (GAP) completes but callbacks are not called (GAP)
  • DurableAgent e2e experimental_onToolCallStart (GAP) completes but callbacks are not called (GAP)
  • DurableAgent e2e experimental_onToolCallFinish (GAP) completes but callbacks are not called (GAP)
  • DurableAgent e2e prepareCall (GAP) completes but prepareCall is not applied (GAP)
  • DurableAgent e2e prepareStep on constructor agent-level prepareStep is called for each LLM step
  • DurableAgent e2e prepareStep on constructor stream-level prepareStep overrides constructor-level
  • DurableAgent e2e multimodal tool results passes through LanguageModelV3ToolResultOutput from tools
  • DurableAgent e2e tool approval (GAP) completes but needsApproval is not checked (GAP)
  • addTenWorkflow | wrun_01KSFDXK25T6XPDBV09E2V7D9X | 🔍 observability
  • addTenWorkflow | wrun_01KSFDXK25T6XPDBV09E2V7D9X | 🔍 observability
  • wellKnownAgentWorkflow (.well-known/agent) | wrun_01KSFDYFQGJJ5HSHD93Y8TRNC0 | 🔍 observability
  • promiseAllWorkflow | wrun_01KSFDXS3QPMH2SZ23ZTCYKKJP | 🔍 observability
  • promiseRaceWorkflow | wrun_01KSFDXYGY9YBY151FCM9FYSKP | 🔍 observability
  • promiseAnyWorkflow | wrun_01KSFDYASDH564591MPGHS3T15 | 🔍 observability
  • importedStepOnlyWorkflow | wrun_01KSFDZ3HN9ZMQ0V1R1REFVH50 | 🔍 observability
  • readableStreamWorkflow | wrun_01KSFDYJFXKP83SFPBK3JSWR8Q | 🔍 observability
  • hookWorkflow | wrun_01KSFDYX4BNB108F9MQG2PGMSA | 🔍 observability
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KSFDZ4MP2Y30J25AJQ098FJ3 | 🔍 observability
  • webhookWorkflow | wrun_01KSFDZ994BZ1TVEC11SWBVAYN | 🔍 observability
  • sleepingWorkflow | wrun_01KSFDZEV911J8N1F7FEHRKQ6H | 🔍 observability
  • parallelSleepWorkflow | wrun_01KSFDZVJD93SD2NY1D4K5DG1J | 🔍 observability
  • sleepWinsRaceWorkflow | wrun_01KSFDZZ0TNA38TQEZFF9H9JBE | 🔍 observability
  • stepWinsRaceWorkflow | wrun_01KSFE03PWZ0QV17TNSPRNJ1R6 | 🔍 observability
  • nullByteWorkflow | wrun_01KSFE075J80SSJ0DEDHQGQ3MR | 🔍 observability
  • workflowAndStepMetadataWorkflow | wrun_01KSFE092CVGYV32MNEQEXKVM9 | 🔍 observability
  • 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 getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KSFE2MBPJYYB45E4QP8REHK8 | 🔍 observability
  • utf8StreamWorkflow | wrun_01KSFE4FCNATPSA27Z0CRS48E6 | 🔍 observability
  • writableForwardedFromWorkflowWorkflow | wrun_01KSFE84ZWCDCAY6NT7ARHAXGA | 🔍 observability
  • writableForwardedFromStepWorkflow | wrun_01KSFE88KMTVCFVP520CD1G3VE | 🔍 observability
  • fetchWorkflow | wrun_01KSFE8AMDF3BSPTVDPQ8PMWRW | 🔍 observability
  • promiseRaceStressTestWorkflow | wrun_01KSFE8CJ6VYTP73TXT92DH7BC | 🔍 observability
  • 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 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 catchability step throw round-trips FatalError with cause chain to workflow catch
  • error handling catchability step throw of a non-Error value preserves it as cause on the wrapping FatalError
  • 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_01KSFEBJCEG13P7V7K657C0S8W | 🔍 observability
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KSFEBXC0MRBNB255R8N4C0ZS | 🔍 observability
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KSFECB9DD6AY6THG75R9AJKP | 🔍 observability
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KSFECHT35NQYXK9SW17PSJ16 | 🔍 observability
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_01KSFECWMQS89SKFK4DMFW9C3M | 🔍 observability
  • closureVariableWorkflow - nested step functions with closure variables | wrun_01KSFED1FTF11ZVK31P4G0DW9F | 🔍 observability
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_01KSFED3E9SBJXCZGJ0YXAYKNS | 🔍 observability
  • runClassSerializationWorkflow - Run instances serialize across workflow/step boundaries | wrun_01KSFEDDC9H71FH4S1HM3YMME7 | 🔍 observability
  • startFromWorkflow - calling start() directly inside a workflow function with hook communication | wrun_01KSFEH3S9JCC5CA5QZN0B1G9Y | 🔍 observability
  • fibonacciWorkflow - recursive workflow composition via start() | wrun_01KSFEH6JJMVF81JT0DA56Q3JC | 🔍 observability
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_01KSFEHMD5F13712919SY6DEZA | 🔍 observability
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_01KSFEHTMJDFAJT3TFV1RKW0ZM | 🔍 observability
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_01KSFEHZED7DGM4DYF6DD47068 | 🔍 observability
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_01KSFEJ4FJYPENRNKBHGA5CXSE | 🔍 observability
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_01KSFEJ9G1KB6YE6984RZ12CDX | 🔍 observability
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_01KSFEJEM0CPA33T2CYRCWZW2M | 🔍 observability
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_01KSFEJMGPRZ0WQ5Q32F6H7KEE | 🔍 observability
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_01KSFEJZG769TTAW3JHJZM4J6F | 🔍 observability
  • errorSubclassRoundTripWorkflow - first-class Error subclasses survive every serialization boundary | wrun_01KSFEK5GK4KW81WTWVFJ3P86G | 🔍 observability
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_01KSFEK7QMFYWQEF32GY82MMB9 | 🔍 observability
  • 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_01KSFEM0CAWQ6PT3WTQ0DBXC87 | 🔍 observability
  • hookWithSleepFinalStepWorkflow - step only on final payload | wrun_01KSFEM63ZS74X0XQZQFQZRJ8J | 🔍 observability
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KSFEMGS77B4KNQCAJ2DZNHQY | 🔍 observability
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KSFEPBSRTBBCQ40QPRNG5CXH | 🔍 observability
  • AbortController abortTimeoutWorkflow: timeout cancels long-running step
  • AbortController abortParallelWorkflow: abort cancels all parallel steps
  • AbortController abortFromStepWorkflow: step abort cancels an in-flight sibling step
  • AbortController abortAlreadyAbortedWorkflow: pre-aborted signal seen by step
  • AbortController abortReasonWorkflow: abort reason preserved across boundaries
  • AbortController abortAfterCompletionWorkflow: abort after step completes is a no-op
  • AbortController abortViaHookWorkflow: external hook triggers abort on in-flight step
  • AbortController abortExternalSignalWorkflow: signal passed as workflow input
  • AbortController abortExternalSignalInFlightWorkflow: external abort fires mid-flight, propagates to nested steps
  • AbortController abortAnyInStepWorkflow: AbortSignal.any inside a step composes deserialized signals
  • AbortController abortSurvivesReplayWorkflow: controller state consistent across replay
  • AbortController abortThrowIfAbortedWorkflow: throwIfAborted causes FatalError, no retries
  • AbortController abortReasonTypesWorkflow: various abort reason types propagate correctly
  • AbortController abortFetchUncaughtWorkflow: uncaught fetch AbortError is FatalError, no retries
  • AbortController abortFetchInFlightWorkflow: aborting cancels an in-flight fetch
  • AbortController abortVoidSleepTimeoutWorkflow: documented void sleep().then(abort) pattern works
  • AbortController abortDeterministicBranchWorkflow: if-check takes same path on first-run and replay
  • AbortController abortListenerWorkflow: signal.addEventListener fires on the deserialized step signal
  • AbortController abortThrowIfAbortedMidFlightWorkflow: throwIfAborted in a polling loop bails when abort fires
  • AbortController abortDeterministicBranchFromStepWorkflow: branches stay consistent when abort comes from a step
  • AbortController abortHookOrderingWorkflow [listener-first-abort-first]: addEventListener → hook.then → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [listener-first-hook-first]: addEventListener → hook.then → resumeHook → abort()
  • AbortController abortHookOrderingWorkflow [hook-first-abort-first]: hook.then → addEventListener → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [hook-first-hook-first]: hook.then → addEventListener → resumeHook → abort()
  • importMetaUrlWorkflow - import.meta.url is available in step bundles | wrun_01KSFEWMTT9SCVFBEQGDG0VDY5 | 🔍 observability
  • metadataFromHelperWorkflow - getWorkflowMetadata/getStepMetadata work from module-level helper (#1577) | wrun_01KSFEWPQT6V79499C66V64ND8 | 🔍 observability
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KSFEWRKNFV18RP86W9QGFN5J | 🔍 observability
  • getterStepWorkflow - getter functions with "use step" directive | wrun_01KSFEX4AN5T7KGEWVWS5QYF1F | 🔍 observability
  • distributedAbortController - manual abort triggers signal | wrun_01KSFEXA755PBRHSNMJPAYD569 | 🔍 observability
  • distributedAbortController - TTL expiration triggers signal | wrun_01KSFEZ553M5PKK0C2HS7QHM8B | 🔍 observability
  • distributedAbortController - reconnect to existing controller | wrun_01KSFF02SATTJ0EPM1WQFYHRMW | 🔍 observability

nitro (41 failed):

  • sleepingWorkflow | wrun_01KSFDZEV911J8N1F7FEHRKQ6H | 🔍 observability
  • parallelSleepWorkflow | wrun_01KSFDZVJD93SD2NY1D4K5DG1J | 🔍 observability
  • sleepWinsRaceWorkflow | wrun_01KSFDZZ0TNA38TQEZFF9H9JBE | 🔍 observability
  • stepWinsRaceWorkflow | wrun_01KSFE03PWZ0QV17TNSPRNJ1R6 | 🔍 observability
  • 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 getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KSFE2MBPJYYB45E4QP8REHK8 | 🔍 observability
  • utf8StreamWorkflow | wrun_01KSFE4FCNATPSA27Z0CRS48E6 | 🔍 observability
  • 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 maxRetries=0 disables retries
  • error handling catchability step throw round-trips FatalError with cause chain to workflow catch
  • error handling catchability step throw of a non-Error value preserves it as cause on the wrapping FatalError
  • 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
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KSFECB9DD6AY6THG75R9AJKP | 🔍 observability
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_01KSFED3E9SBJXCZGJ0YXAYKNS | 🔍 observability
  • hookWithSleepWorkflow - hook payloads delivered correctly with concurrent sleep | wrun_01KSFEM0CAWQ6PT3WTQ0DBXC87 | 🔍 observability
  • hookWithSleepFinalStepWorkflow - step only on final payload | wrun_01KSFEM63ZS74X0XQZQFQZRJ8J | 🔍 observability
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KSFEMGS77B4KNQCAJ2DZNHQY | 🔍 observability
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KSFEPBSRTBBCQ40QPRNG5CXH | 🔍 observability
  • AbortController abortTimeoutWorkflow: timeout cancels long-running step
  • AbortController abortParallelWorkflow: abort cancels all parallel steps
  • AbortController abortReasonWorkflow: abort reason preserved across boundaries
  • AbortController abortViaHookWorkflow: external hook triggers abort on in-flight step
  • AbortController abortSurvivesReplayWorkflow: controller state consistent across replay
  • AbortController abortFetchInFlightWorkflow: aborting cancels an in-flight fetch
  • AbortController abortVoidSleepTimeoutWorkflow: documented void sleep().then(abort) pattern works
  • AbortController abortDeterministicBranchFromStepWorkflow: branches stay consistent when abort comes from a step
  • AbortController abortHookOrderingWorkflow [listener-first-abort-first]: addEventListener → hook.then → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [listener-first-hook-first]: addEventListener → hook.then → resumeHook → abort()
  • AbortController abortHookOrderingWorkflow [hook-first-abort-first]: hook.then → addEventListener → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [hook-first-hook-first]: hook.then → addEventListener → resumeHook → abort()
  • metadataFromHelperWorkflow - getWorkflowMetadata/getStepMetadata work from module-level helper (#1577) | wrun_01KSFEWPQT6V79499C66V64ND8 | 🔍 observability
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KSFEWRKNFV18RP86W9QGFN5J | 🔍 observability
  • distributedAbortController - manual abort triggers signal | wrun_01KSFEXA755PBRHSNMJPAYD569 | 🔍 observability
  • distributedAbortController - TTL expiration triggers signal | wrun_01KSFEZ553M5PKK0C2HS7QHM8B | 🔍 observability
  • distributedAbortController - reconnect to existing controller | wrun_01KSFF02SATTJ0EPM1WQFYHRMW | 🔍 observability

nuxt (39 failed):

  • sleepingWorkflow | wrun_01KSFDZEV911J8N1F7FEHRKQ6H | 🔍 observability
  • parallelSleepWorkflow | wrun_01KSFDZVJD93SD2NY1D4K5DG1J | 🔍 observability
  • sleepWinsRaceWorkflow | wrun_01KSFDZZ0TNA38TQEZFF9H9JBE | 🔍 observability
  • stepWinsRaceWorkflow | wrun_01KSFE03PWZ0QV17TNSPRNJ1R6 | 🔍 observability
  • 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 getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KSFE2MBPJYYB45E4QP8REHK8 | 🔍 observability
  • utf8StreamWorkflow | wrun_01KSFE4FCNATPSA27Z0CRS48E6 | 🔍 observability
  • 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 maxRetries=0 disables retries
  • error handling catchability step throw round-trips FatalError with cause chain to workflow catch
  • error handling catchability step throw of a non-Error value preserves it as cause on the wrapping FatalError
  • 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
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KSFECB9DD6AY6THG75R9AJKP | 🔍 observability
  • fibonacciWorkflow - recursive workflow composition via start() | wrun_01KSFEH6JJMVF81JT0DA56Q3JC | 🔍 observability
  • hookWithSleepWorkflow - hook payloads delivered correctly with concurrent sleep | wrun_01KSFEM0CAWQ6PT3WTQ0DBXC87 | 🔍 observability
  • hookWithSleepFinalStepWorkflow - step only on final payload | wrun_01KSFEM63ZS74X0XQZQFQZRJ8J | 🔍 observability
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KSFEMGS77B4KNQCAJ2DZNHQY | 🔍 observability
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KSFEPBSRTBBCQ40QPRNG5CXH | 🔍 observability
  • AbortController abortTimeoutWorkflow: timeout cancels long-running step
  • AbortController abortParallelWorkflow: abort cancels all parallel steps
  • AbortController abortReasonWorkflow: abort reason preserved across boundaries
  • AbortController abortSurvivesReplayWorkflow: controller state consistent across replay
  • AbortController abortFetchInFlightWorkflow: aborting cancels an in-flight fetch
  • AbortController abortVoidSleepTimeoutWorkflow: documented void sleep().then(abort) pattern works
  • AbortController abortDeterministicBranchFromStepWorkflow: branches stay consistent when abort comes from a step
  • AbortController abortHookOrderingWorkflow [listener-first-abort-first]: addEventListener → hook.then → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [listener-first-hook-first]: addEventListener → hook.then → resumeHook → abort()
  • AbortController abortHookOrderingWorkflow [hook-first-abort-first]: hook.then → addEventListener → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [hook-first-hook-first]: hook.then → addEventListener → resumeHook → abort()
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KSFEWRKNFV18RP86W9QGFN5J | 🔍 observability
  • distributedAbortController - manual abort triggers signal | wrun_01KSFEXA755PBRHSNMJPAYD569 | 🔍 observability
  • distributedAbortController - TTL expiration triggers signal | wrun_01KSFEZ553M5PKK0C2HS7QHM8B | 🔍 observability
  • distributedAbortController - reconnect to existing controller | wrun_01KSFF02SATTJ0EPM1WQFYHRMW | 🔍 observability

sveltekit (39 failed):

  • sleepingWorkflow | wrun_01KSFDZEV911J8N1F7FEHRKQ6H | 🔍 observability
  • parallelSleepWorkflow | wrun_01KSFDZVJD93SD2NY1D4K5DG1J | 🔍 observability
  • sleepWinsRaceWorkflow | wrun_01KSFDZZ0TNA38TQEZFF9H9JBE | 🔍 observability
  • stepWinsRaceWorkflow | wrun_01KSFE03PWZ0QV17TNSPRNJ1R6 | 🔍 observability
  • 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 getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KSFE2MBPJYYB45E4QP8REHK8 | 🔍 observability
  • utf8StreamWorkflow | wrun_01KSFE4FCNATPSA27Z0CRS48E6 | 🔍 observability
  • 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 maxRetries=0 disables retries
  • error handling catchability step throw round-trips FatalError with cause chain to workflow catch
  • error handling catchability step throw of a non-Error value preserves it as cause on the wrapping FatalError
  • 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
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KSFECB9DD6AY6THG75R9AJKP | 🔍 observability
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_01KSFEJ9G1KB6YE6984RZ12CDX | 🔍 observability
  • hookWithSleepWorkflow - hook payloads delivered correctly with concurrent sleep | wrun_01KSFEM0CAWQ6PT3WTQ0DBXC87 | 🔍 observability
  • hookWithSleepFinalStepWorkflow - step only on final payload | wrun_01KSFEM63ZS74X0XQZQFQZRJ8J | 🔍 observability
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KSFEMGS77B4KNQCAJ2DZNHQY | 🔍 observability
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KSFEPBSRTBBCQ40QPRNG5CXH | 🔍 observability
  • AbortController abortTimeoutWorkflow: timeout cancels long-running step
  • AbortController abortParallelWorkflow: abort cancels all parallel steps
  • AbortController abortReasonWorkflow: abort reason preserved across boundaries
  • AbortController abortSurvivesReplayWorkflow: controller state consistent across replay
  • AbortController abortFetchInFlightWorkflow: aborting cancels an in-flight fetch
  • AbortController abortVoidSleepTimeoutWorkflow: documented void sleep().then(abort) pattern works
  • AbortController abortDeterministicBranchFromStepWorkflow: branches stay consistent when abort comes from a step
  • AbortController abortHookOrderingWorkflow [listener-first-abort-first]: addEventListener → hook.then → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [listener-first-hook-first]: addEventListener → hook.then → resumeHook → abort()
  • AbortController abortHookOrderingWorkflow [hook-first-abort-first]: hook.then → addEventListener → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [hook-first-hook-first]: hook.then → addEventListener → resumeHook → abort()
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KSFEWRKNFV18RP86W9QGFN5J | 🔍 observability
  • distributedAbortController - manual abort triggers signal | wrun_01KSFEXA755PBRHSNMJPAYD569 | 🔍 observability
  • distributedAbortController - TTL expiration triggers signal | wrun_01KSFEZ553M5PKK0C2HS7QHM8B | 🔍 observability
  • distributedAbortController - reconnect to existing controller | wrun_01KSFF02SATTJ0EPM1WQFYHRMW | 🔍 observability

vite (39 failed):

  • sleepingWorkflow | wrun_01KSFDZEV911J8N1F7FEHRKQ6H | 🔍 observability
  • parallelSleepWorkflow | wrun_01KSFDZVJD93SD2NY1D4K5DG1J | 🔍 observability
  • sleepWinsRaceWorkflow | wrun_01KSFDZZ0TNA38TQEZFF9H9JBE | 🔍 observability
  • stepWinsRaceWorkflow | wrun_01KSFE03PWZ0QV17TNSPRNJ1R6 | 🔍 observability
  • 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 getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KSFE2MBPJYYB45E4QP8REHK8 | 🔍 observability
  • utf8StreamWorkflow | wrun_01KSFE4FCNATPSA27Z0CRS48E6 | 🔍 observability
  • 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 maxRetries=0 disables retries
  • error handling catchability step throw round-trips FatalError with cause chain to workflow catch
  • error handling catchability step throw of a non-Error value preserves it as cause on the wrapping FatalError
  • 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
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KSFECB9DD6AY6THG75R9AJKP | 🔍 observability
  • runClassSerializationWorkflow - Run instances serialize across workflow/step boundaries | wrun_01KSFEDDC9H71FH4S1HM3YMME7 | 🔍 observability
  • hookWithSleepWorkflow - hook payloads delivered correctly with concurrent sleep | wrun_01KSFEM0CAWQ6PT3WTQ0DBXC87 | 🔍 observability
  • hookWithSleepFinalStepWorkflow - step only on final payload | wrun_01KSFEM63ZS74X0XQZQFQZRJ8J | 🔍 observability
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KSFEMGS77B4KNQCAJ2DZNHQY | 🔍 observability
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KSFEPBSRTBBCQ40QPRNG5CXH | 🔍 observability
  • AbortController abortTimeoutWorkflow: timeout cancels long-running step
  • AbortController abortParallelWorkflow: abort cancels all parallel steps
  • AbortController abortReasonWorkflow: abort reason preserved across boundaries
  • AbortController abortSurvivesReplayWorkflow: controller state consistent across replay
  • AbortController abortFetchInFlightWorkflow: aborting cancels an in-flight fetch
  • AbortController abortVoidSleepTimeoutWorkflow: documented void sleep().then(abort) pattern works
  • AbortController abortDeterministicBranchFromStepWorkflow: branches stay consistent when abort comes from a step
  • AbortController abortHookOrderingWorkflow [listener-first-abort-first]: addEventListener → hook.then → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [listener-first-hook-first]: addEventListener → hook.then → resumeHook → abort()
  • AbortController abortHookOrderingWorkflow [hook-first-abort-first]: hook.then → addEventListener → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [hook-first-hook-first]: hook.then → addEventListener → resumeHook → abort()
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KSFEWRKNFV18RP86W9QGFN5J | 🔍 observability
  • distributedAbortController - manual abort triggers signal | wrun_01KSFEXA755PBRHSNMJPAYD569 | 🔍 observability
  • distributedAbortController - TTL expiration triggers signal | wrun_01KSFEZ553M5PKK0C2HS7QHM8B | 🔍 observability
  • distributedAbortController - reconnect to existing controller | wrun_01KSFF02SATTJ0EPM1WQFYHRMW | 🔍 observability
📋 Other (40 failed)

e2e-vercel-prod-tanstack-start (40 failed):

  • webhookWorkflow | wrun_01KSFDZ994BZ1TVEC11SWBVAYN
  • sleepingWorkflow | wrun_01KSFDZEV911J8N1F7FEHRKQ6H
  • parallelSleepWorkflow | wrun_01KSFDZVJD93SD2NY1D4K5DG1J
  • sleepWinsRaceWorkflow | wrun_01KSFDZZ0TNA38TQEZFF9H9JBE
  • stepWinsRaceWorkflow | wrun_01KSFE03PWZ0QV17TNSPRNJ1R6
  • 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 getChunks returns same content as reading the stream
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions | wrun_01KSFE2MBPJYYB45E4QP8REHK8
  • utf8StreamWorkflow | wrun_01KSFE4FCNATPSA27Z0CRS48E6
  • 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 maxRetries=0 disables retries
  • error handling catchability step throw round-trips FatalError with cause chain to workflow catch
  • error handling catchability step throw of a non-Error value preserves it as cause on the wrapping FatalError
  • 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
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KSFECB9DD6AY6THG75R9AJKP
  • fibonacciWorkflow - recursive workflow composition via start() | wrun_01KSFEH6JJMVF81JT0DA56Q3JC
  • hookWithSleepWorkflow - hook payloads delivered correctly with concurrent sleep | wrun_01KSFEM0CAWQ6PT3WTQ0DBXC87
  • hookWithSleepFinalStepWorkflow - step only on final payload | wrun_01KSFEM63ZS74X0XQZQFQZRJ8J
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KSFEMGS77B4KNQCAJ2DZNHQY
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KSFEPBSRTBBCQ40QPRNG5CXH
  • AbortController abortTimeoutWorkflow: timeout cancels long-running step
  • AbortController abortParallelWorkflow: abort cancels all parallel steps
  • AbortController abortReasonWorkflow: abort reason preserved across boundaries
  • AbortController abortSurvivesReplayWorkflow: controller state consistent across replay
  • AbortController abortFetchInFlightWorkflow: aborting cancels an in-flight fetch
  • AbortController abortVoidSleepTimeoutWorkflow: documented void sleep().then(abort) pattern works
  • AbortController abortDeterministicBranchFromStepWorkflow: branches stay consistent when abort comes from a step
  • AbortController abortHookOrderingWorkflow [listener-first-abort-first]: addEventListener → hook.then → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [listener-first-hook-first]: addEventListener → hook.then → resumeHook → abort()
  • AbortController abortHookOrderingWorkflow [hook-first-abort-first]: hook.then → addEventListener → abort() → resumeHook
  • AbortController abortHookOrderingWorkflow [hook-first-hook-first]: hook.then → addEventListener → resumeHook → abort()
  • resilient start: addTenWorkflow completes when run_created returns 500 | wrun_01KSFEWRKNFV18RP86W9QGFN5J
  • distributedAbortController - manual abort triggers signal | wrun_01KSFEXA755PBRHSNMJPAYD569
  • distributedAbortController - TTL expiration triggers signal | wrun_01KSFEZ553M5PKK0C2HS7QHM8B
  • distributedAbortController - reconnect to existing controller | wrun_01KSFF02SATTJ0EPM1WQFYHRMW

Details by Category

❌ ▲ Vercel Production
App Passed Failed Skipped
❌ astro 65 40 26
❌ example 67 38 26
❌ express 65 40 26
❌ fastify 66 39 26
❌ hono 64 41 26
❌ nextjs-turbopack 85 44 2
❌ nextjs-webpack 14 115 2
❌ nitro 64 41 26
❌ nuxt 66 39 26
❌ sveltekit 85 39 7
❌ vite 66 39 26
✅ 💻 Local Development
App Passed Failed Skipped
✅ astro-stable 106 0 25
✅ express-stable 106 0 25
✅ fastify-stable 106 0 25
✅ hono-stable 106 0 25
✅ nextjs-turbopack-canary 112 0 19
✅ nextjs-turbopack-stable-lazy-discovery-disabled 131 0 0
✅ nextjs-turbopack-stable-lazy-discovery-enabled 131 0 0
✅ nextjs-webpack-canary 112 0 19
✅ nextjs-webpack-stable-lazy-discovery-disabled 131 0 0
✅ nextjs-webpack-stable-lazy-discovery-enabled 131 0 0
✅ nitro-stable 106 0 25
✅ nuxt-stable 106 0 25
✅ sveltekit-stable 125 0 6
✅ vite-stable 106 0 25
✅ 📦 Local Production
App Passed Failed Skipped
✅ astro-stable 106 0 25
✅ express-stable 106 0 25
✅ fastify-stable 106 0 25
✅ hono-stable 106 0 25
✅ nextjs-turbopack-canary 112 0 19
✅ nextjs-turbopack-stable-lazy-discovery-disabled 131 0 0
✅ nextjs-turbopack-stable-lazy-discovery-enabled 131 0 0
✅ nextjs-webpack-canary 112 0 19
✅ nextjs-webpack-stable-lazy-discovery-disabled 131 0 0
✅ nextjs-webpack-stable-lazy-discovery-enabled 131 0 0
✅ nitro-stable 106 0 25
✅ nuxt-stable 106 0 25
✅ sveltekit-stable 125 0 6
✅ vite-stable 106 0 25
✅ 🐘 Local Postgres
App Passed Failed Skipped
✅ astro-stable 106 0 25
✅ express-stable 106 0 25
✅ fastify-stable 106 0 25
✅ hono-stable 106 0 25
✅ nextjs-turbopack-canary 112 0 19
✅ nextjs-turbopack-stable-lazy-discovery-disabled 131 0 0
✅ nextjs-turbopack-stable-lazy-discovery-enabled 131 0 0
✅ nextjs-webpack-canary 112 0 19
✅ nextjs-webpack-stable-lazy-discovery-disabled 131 0 0
✅ nextjs-webpack-stable-lazy-discovery-enabled 131 0 0
✅ nitro-stable 106 0 25
✅ nuxt-stable 106 0 25
✅ sveltekit-stable 125 0 6
✅ vite-stable 106 0 25
✅ 🪟 Windows
App Passed Failed Skipped
✅ nextjs-turbopack 131 0 0
❌ 📋 Other
App Passed Failed Skipped
✅ e2e-local-dev-nest-stable 106 0 25
✅ e2e-local-dev-tanstack-start- 106 0 25
✅ e2e-local-postgres-nest-stable 106 0 25
✅ e2e-local-postgres-tanstack-start- 106 0 25
✅ e2e-local-prod-nest-stable 106 0 25
✅ e2e-local-prod-tanstack-start- 106 0 25
❌ e2e-vercel-prod-tanstack-start 65 40 26

📋 View full workflow run


Some E2E test jobs failed:

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

Check the workflow run for details.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 21, 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 (-30.9% 🟢) 1.006s (~) 0.975s 10 1.00x
💻 Local Nitro 0.031s (-28.8% 🟢) 1.006s (~) 0.975s 10 1.00x
🐘 Postgres Nitro 0.049s (-48.2% 🟢) 1.011s (-3.1%) 0.962s 10 1.61x
💻 Local Next.js (Turbopack) 0.049s 1.004s 0.955s 10 1.61x
🐘 Postgres Express 0.053s (-8.8% 🟢) 1.011s (~) 0.958s 10 1.73x
🐘 Postgres Next.js (Turbopack) 0.055s 1.011s 0.957s 10 1.79x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 0.227s (-9.9% 🟢) 2.334s (~) 2.108s 10 1.00x
▲ Vercel Express ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Next.js (Turbopack)

workflow with 1 step

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 1.069s (-5.5% 🟢) 2.006s (~) 0.937s 10 1.00x
💻 Local Express 1.075s (-4.4%) 2.006s (~) 0.930s 10 1.01x
🐘 Postgres Express 1.085s (-5.4% 🟢) 2.008s (~) 0.924s 10 1.01x
💻 Local Next.js (Turbopack) 1.087s 2.005s 0.918s 10 1.02x
🐘 Postgres Nitro 1.091s (-4.3%) 2.009s (~) 0.919s 10 1.02x
🐘 Postgres Next.js (Turbopack) 1.128s 2.011s 0.883s 10 1.06x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 1.665s (-18.2% 🟢) 3.399s (-11.3% 🟢) 1.734s 10 1.00x
▲ Vercel Express ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Next.js (Turbopack)

workflow with 10 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 10.406s (-4.9%) 11.022s (~) 0.616s 3 1.00x
💻 Local Express 10.409s (-4.7%) 11.022s (~) 0.613s 3 1.00x
🐘 Postgres Express 10.417s (-5.0%) 11.015s (~) 0.598s 3 1.00x
🐘 Postgres Nitro 10.419s (-4.2%) 11.018s (~) 0.599s 3 1.00x
💻 Local Next.js (Turbopack) 10.552s 11.020s 0.468s 3 1.01x
🐘 Postgres Next.js (Turbopack) 10.706s 11.019s 0.313s 3 1.03x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 14.432s (-16.7% 🟢) 15.882s (-18.1% 🟢) 1.450s 2 1.00x
▲ Vercel Express ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Next.js (Turbopack)

workflow with 25 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 13.421s (-8.0% 🟢) 14.017s (-6.7% 🟢) 0.596s 5 1.00x
💻 Local Nitro 13.466s (-10.6% 🟢) 14.027s (-12.5% 🟢) 0.561s 5 1.00x
💻 Local Express 13.507s (-9.8% 🟢) 14.027s (-6.7% 🟢) 0.519s 5 1.01x
🐘 Postgres Express 13.541s (-7.1% 🟢) 14.020s (-6.7% 🟢) 0.479s 5 1.01x
💻 Local Next.js (Turbopack) 13.751s 14.026s 0.275s 5 1.02x
🐘 Postgres Next.js (Turbopack) 14.120s 15.020s 0.900s 4 1.05x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 21.152s (-59.8% 🟢) 22.786s (-58.3% 🟢) 1.635s 3 1.00x
▲ Vercel Express ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Next.js (Turbopack)

workflow with 50 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 11.874s (-15.0% 🟢) 12.141s (-15.1% 🟢) 0.267s 8 1.00x
💻 Local Nitro 11.924s (-29.0% 🟢) 12.272s (-27.9% 🟢) 0.349s 8 1.00x
💻 Local Express 11.949s (-28.0% 🟢) 12.272s (-27.9% 🟢) 0.323s 8 1.01x
🐘 Postgres Express 11.961s (-14.6% 🟢) 12.144s (-16.8% 🟢) 0.183s 8 1.01x
💻 Local Next.js (Turbopack) 12.443s 13.022s 0.578s 7 1.05x
🐘 Postgres Next.js (Turbopack) 13.306s 14.017s 0.711s 7 1.12x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 28.553s (-92.7% 🟢) 30.257s (-92.3% 🟢) 1.704s 4 1.00x
▲ Vercel Express ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Next.js (Turbopack)

Promise.all with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.135s (-11.0% 🟢) 2.008s (~) 0.873s 15 1.00x
🐘 Postgres Express 1.145s (-9.1% 🟢) 2.008s (~) 0.863s 15 1.01x
💻 Local Nitro 1.168s (-28.4% 🟢) 2.006s (-3.3%) 0.838s 15 1.03x
💻 Local Express 1.184s (-20.5% 🟢) 2.005s (~) 0.821s 15 1.04x
💻 Local Next.js (Turbopack) 1.227s 2.005s 0.778s 15 1.08x
🐘 Postgres Next.js (Turbopack) 1.228s 2.007s 0.779s 15 1.08x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 3.852s (+13.4% 🔺) 5.353s (+8.5% 🔺) 1.500s 7 1.00x
▲ Vercel Express ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Next.js (Turbopack)

Promise.all with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 1.201s (-49.1% 🟢) 2.007s (-33.3% 🟢) 0.806s 15 1.00x
🐘 Postgres Nitro 1.202s (-48.9% 🟢) 2.007s (-33.3% 🟢) 0.805s 15 1.00x
🐘 Postgres Next.js (Turbopack) 1.348s 2.007s 0.659s 15 1.12x
💻 Local Next.js (Turbopack) 1.571s 2.005s 0.434s 15 1.31x
💻 Local Nitro 1.721s (-45.3% 🟢) 2.005s (-48.4% 🟢) 0.284s 15 1.43x
💻 Local Express 1.788s (-39.4% 🟢) 2.006s (-41.9% 🟢) 0.218s 15 1.49x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 3.696s (-47.9% 🟢) 5.238s (-41.2% 🟢) 1.542s 6 1.00x
▲ Vercel Express ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Next.js (Turbopack)

Promise.all with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.299s (-62.7% 🟢) 2.007s (-49.9% 🟢) 0.708s 15 1.00x
🐘 Postgres Express 1.307s (-62.5% 🟢) 2.007s (-49.9% 🟢) 0.700s 15 1.01x
🐘 Postgres Next.js (Turbopack) 1.576s 2.006s 0.430s 15 1.21x
💻 Local Next.js (Turbopack) 3.713s 4.258s 0.545s 8 2.86x
💻 Local Nitro 4.276s (-48.8% 🟢) 5.011s (-44.5% 🟢) 0.735s 6 3.29x
💻 Local Express 5.743s (-31.1% 🟢) 6.015s (-33.4% 🟢) 0.272s 5 4.42x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 106.976s (+1099.9% 🔺) 108.853s (+893.2% 🔺) 1.877s 3 1.00x
▲ Vercel Express ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Next.js (Turbopack)

Promise.race with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 1.148s (-8.6% 🟢) 2.007s (~) 0.859s 15 1.00x
🐘 Postgres Nitro 1.156s (-8.0% 🟢) 2.007s (~) 0.851s 15 1.01x
🐘 Postgres Next.js (Turbopack) 1.197s 2.008s 0.811s 15 1.04x
💻 Local Next.js (Turbopack) 1.263s 2.005s 0.742s 15 1.10x
💻 Local Nitro 1.399s (-25.0% 🟢) 2.005s (-14.3% 🟢) 0.607s 15 1.22x
💻 Local Express 1.415s (-25.3% 🟢) 2.006s (-15.1% 🟢) 0.591s 15 1.23x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 2.496s (-14.9% 🟢) 4.136s (-10.9% 🟢) 1.640s 8 1.00x
▲ Vercel Express ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Next.js (Turbopack)

Promise.race with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 1.194s (-49.0% 🟢) 2.009s (-33.3% 🟢) 0.815s 15 1.00x
🐘 Postgres Nitro 1.216s (-48.0% 🟢) 2.009s (-33.3% 🟢) 0.793s 15 1.02x
🐘 Postgres Next.js (Turbopack) 1.332s 2.008s 0.675s 15 1.12x
💻 Local Next.js (Turbopack) 1.905s 2.149s 0.244s 14 1.60x
💻 Local Nitro 2.006s (-34.6% 🟢) 2.470s (-36.5% 🟢) 0.464s 13 1.68x
💻 Local Express 2.118s (-32.4% 🟢) 2.509s (-33.3% 🟢) 0.391s 12 1.77x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 3.704s (+17.9% 🔺) 5.764s (+27.5% 🔺) 2.060s 6 1.00x
▲ Vercel Express ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Next.js (Turbopack)

Promise.race with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.308s (-62.4% 🟢) 2.006s (-50.0% 🟢) 0.699s 15 1.00x
🐘 Postgres Express 1.315s (-62.4% 🟢) 2.007s (-50.0% 🟢) 0.693s 15 1.01x
🐘 Postgres Next.js (Turbopack) 1.583s 2.007s 0.425s 15 1.21x
💻 Local Next.js (Turbopack) 4.218s 4.582s 0.363s 7 3.23x
💻 Local Nitro 5.457s (-40.3% 🟢) 6.012s (-40.0% 🟢) 0.556s 5 4.17x
💻 Local Express 5.929s (-32.6% 🟢) 6.416s (-30.8% 🟢) 0.487s 5 4.53x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 5.050s (-25.3% 🟢) 6.698s (-21.6% 🟢) 1.648s 5 1.00x
▲ Vercel Express ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Next.js (Turbopack)

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Express 0.445s (-47.0% 🟢) 1.006s (-1.7%) 0.562s 60 1.00x
🐘 Postgres Nitro 0.445s (-45.7% 🟢) 1.023s (+1.6%) 0.578s 59 1.00x
💻 Local Nitro 0.473s (-51.7% 🟢) 1.004s (-8.2% 🟢) 0.531s 60 1.06x
💻 Local Express 0.477s (-51.5% 🟢) 1.004s (-6.7% 🟢) 0.527s 60 1.07x
💻 Local Next.js (Turbopack) 0.603s 1.004s 0.400s 60 1.36x
🐘 Postgres Next.js (Turbopack) 0.670s 1.006s 0.336s 60 1.51x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 5.745s (-60.4% 🟢) 8.051s (-49.9% 🟢) 2.307s 8 1.00x
▲ Vercel Express ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Next.js (Turbopack)

workflow with 25 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 0.983s (-49.0% 🟢) 1.222s (-41.8% 🟢) 0.240s 74 1.00x
🐘 Postgres Express 1.061s (-46.3% 🟢) 1.757s (-22.2% 🟢) 0.696s 52 1.08x
💻 Local Nitro 1.170s (-61.5% 🟢) 2.006s (-46.6% 🟢) 0.836s 45 1.19x
💻 Local Express 1.197s (-60.3% 🟢) 2.006s (-44.1% 🟢) 0.809s 45 1.22x
💻 Local Next.js (Turbopack) 1.586s 2.030s 0.443s 45 1.61x
🐘 Postgres Next.js (Turbopack) 1.605s 2.007s 0.401s 45 1.63x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 15.134s (-69.6% 🟢) 17.084s (-67.0% 🟢) 1.950s 6 1.00x
▲ Vercel Express ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Next.js (Turbopack)

workflow with 50 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.988s (-51.6% 🟢) 2.291s (-50.2% 🟢) 0.303s 53 1.00x
🐘 Postgres Express 2.107s (-47.2% 🟢) 2.913s (-33.3% 🟢) 0.806s 42 1.06x
💻 Local Nitro 2.661s (-71.4% 🟢) 3.007s (-70.0% 🟢) 0.346s 40 1.34x
💻 Local Express 2.754s (-70.1% 🟢) 3.057s (-69.5% 🟢) 0.303s 40 1.39x
🐘 Postgres Next.js (Turbopack) 3.121s 4.009s 0.888s 30 1.57x
💻 Local Next.js (Turbopack) 3.266s 3.944s 0.678s 31 1.64x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 31.711s (-70.4% 🟢) 33.927s (-68.9% 🟢) 2.216s 4 1.00x
▲ Vercel Express ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Next.js (Turbopack)

workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 0.165s (-41.6% 🟢) 1.006s (~) 0.840s 60 1.00x
🐘 Postgres Express 0.173s (-38.8% 🟢) 1.006s (~) 0.833s 60 1.05x
🐘 Postgres Next.js (Turbopack) 0.218s 1.006s 0.788s 60 1.32x
💻 Local Nitro 0.386s (-36.1% 🟢) 1.004s (-1.7%) 0.618s 60 2.34x
💻 Local Express 0.404s (-28.0% 🟢) 1.004s (~) 0.601s 60 2.44x
💻 Local Next.js (Turbopack) 0.476s 1.004s 0.527s 60 2.88x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 2.156s (+6.6% 🔺) 3.951s (+4.1%) 1.795s 16 1.00x
▲ Vercel Express ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: 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.285s (-42.6% 🟢) 1.006s (~) 0.721s 90 1.00x
🐘 Postgres Express 0.300s (-41.1% 🟢) 1.006s (~) 0.706s 90 1.05x
🐘 Postgres Next.js (Turbopack) 0.426s 1.006s 0.579s 90 1.50x
💻 Local Next.js (Turbopack) 2.005s 2.607s 0.603s 35 7.03x
💻 Local Nitro 2.135s (-15.9% 🟢) 2.656s (-11.7% 🟢) 0.521s 34 7.49x
💻 Local Express 2.141s (-14.8% 🟢) 2.820s (-6.3% 🟢) 0.680s 32 7.51x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 4.230s (+19.6% 🔺) 6.099s (+17.4% 🔺) 1.869s 15 1.00x
▲ Vercel Express ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: Next.js (Turbopack)

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 0.587s (-25.7% 🟢) 1.005s (~) 0.418s 120 1.00x
🐘 Postgres Express 0.636s (-22.3% 🟢) 1.006s (-1.2%) 0.369s 120 1.08x
🐘 Postgres Next.js (Turbopack) 0.863s 1.015s 0.151s 119 1.47x
💻 Local Next.js (Turbopack) 8.930s 9.638s 0.708s 13 15.20x
💻 Local Nitro 10.114s (-9.6% 🟢) 10.693s (-8.3% 🟢) 0.579s 12 17.22x
💻 Local Express 10.268s (-8.2% 🟢) 10.698s (-10.4% 🟢) 0.430s 12 17.48x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 13.273s (+28.5% 🔺) 15.581s (+26.8% 🔺) 2.308s 8 1.00x
▲ Vercel Express ⚠️ missing - - - -
▲ Vercel Nitro ⚠️ missing - - - -

🔍 Observability: 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 🥇 Nitro 1.132s (+429.7% 🔺) 2.005s (+99.6% 🔺) 0.012s (-7.2% 🟢) 2.019s (+98.2% 🔺) 0.887s 10 1.00x
🐘 Postgres Nitro 1.133s (+452.5% 🔺) 1.994s (+99.5% 🔺) 0.001s (-20.0% 🟢) 2.011s (+98.8% 🔺) 0.878s 10 1.00x
💻 Local Express 1.136s (+470.7% 🔺) 2.005s (+99.6% 🔺) 0.013s (+3.3%) 2.020s (+98.4% 🔺) 0.884s 10 1.00x
💻 Local Next.js (Turbopack) 1.144s 2.003s 0.008s 2.014s 0.870s 10 1.01x
🐘 Postgres Express 1.145s (+458.4% 🔺) 1.994s (+99.7% 🔺) 0.001s (-18.8% 🟢) 2.010s (+98.7% 🔺) 0.865s 10 1.01x
🐘 Postgres Next.js (Turbopack) 1.201s 2.001s 0.001s 2.010s 0.808s 10 1.06x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 2.496s (-63.6% 🟢) 3.570s (-58.7% 🟢) 2.002s (+216.9% 🔺) 6.046s (-38.2% 🟢) 3.550s 10 1.00x
▲ Vercel Express ⚠️ missing - - - - -
▲ Vercel Nitro ⚠️ missing - - - - -

🔍 Observability: Next.js (Turbopack)

stream pipeline with 5 transform steps (1MB)

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.478s (+136.8% 🔺) 2.000s (+98.6% 🔺) 0.004s (-12.1% 🟢) 2.023s (+97.9% 🔺) 0.545s 30 1.00x
🐘 Postgres Express 1.517s (+140.9% 🔺) 2.004s (+99.1% 🔺) 0.004s (+1.8%) 2.027s (+98.1% 🔺) 0.509s 30 1.03x
💻 Local Nitro 1.527s (+82.1% 🔺) 2.010s (+98.6% 🔺) 0.010s (+3.5%) 2.021s (+81.1% 🔺) 0.494s 30 1.03x
💻 Local Next.js (Turbopack) 1.551s 2.008s 0.008s 2.019s 0.467s 30 1.05x
🐘 Postgres Next.js (Turbopack) 1.660s 2.010s 0.004s 2.024s 0.364s 30 1.12x
💻 Local Express 1.703s (+125.0% 🔺) 2.011s (+95.5% 🔺) 0.010s (+10.3% 🔺) 2.196s (+111.2% 🔺) 0.493s 29 1.15x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 6.287s (-62.8% 🟢) 7.654s (-58.0% 🟢) 0.226s (+6.7% 🔺) 8.299s (-56.2% 🟢) 2.012s 8 1.00x
▲ Vercel Express ⚠️ missing - - - - -
▲ Vercel Nitro ⚠️ missing - - - - -

🔍 Observability: Next.js (Turbopack)

10 parallel streams (1MB each)

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 0.649s (-33.0% 🟢) 1.010s (-19.0% 🟢) 0.000s (-18.6% 🟢) 1.028s (-18.2% 🟢) 0.379s 59 1.00x
🐘 Postgres Express 0.673s (-29.9% 🟢) 1.066s (-16.6% 🟢) 0.000s (-58.9% 🟢) 1.079s (-17.4% 🟢) 0.405s 56 1.04x
🐘 Postgres Next.js (Turbopack) 0.773s 1.054s 0.000s 1.075s 0.302s 57 1.19x
💻 Local Next.js (Turbopack) 1.241s 1.947s 0.000s 1.950s 0.709s 31 1.91x
💻 Local Express 1.344s (+9.8% 🔺) 2.016s (~) 0.000s (+40.0% 🔺) 2.018s (~) 0.674s 30 2.07x
💻 Local Nitro 1.364s (+11.6% 🔺) 2.015s (~) 0.000s (+233.3% 🔺) 2.017s (~) 0.653s 30 2.10x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 4.490s (-55.9% 🟢) 5.872s (-49.0% 🟢) 0.000s (NaN%) 6.356s (-47.3% 🟢) 1.866s 10 1.00x
▲ Vercel Express ⚠️ missing - - - - -
▲ Vercel Nitro ⚠️ missing - - - - -

🔍 Observability: 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
🐘 Postgres 🥇 Nitro 1.190s (-33.6% 🟢) 1.899s (-11.3% 🟢) 0.000s (+75.0% 🔺) 1.919s (-11.8% 🟢) 0.729s 32 1.00x
🐘 Postgres Express 1.242s (-29.9% 🟢) 2.025s (-7.0% 🟢) 0.000s (NaN%) 2.054s (-6.6% 🟢) 0.813s 30 1.04x
🐘 Postgres Next.js (Turbopack) 1.565s 2.225s 0.000s 2.234s 0.669s 27 1.32x
💻 Local Next.js (Turbopack) 2.402s 3.073s 0.000s 3.076s 0.674s 20 2.02x
💻 Local Express 3.110s (-10.3% 🟢) 3.966s (-1.7%) 0.001s (-37.5% 🟢) 3.968s (-1.7%) 0.858s 16 2.61x
💻 Local Nitro 3.177s (-6.2% 🟢) 3.839s (-4.8%) 0.001s (+17.2% 🔺) 3.847s (-4.7%) 0.670s 16 2.67x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 83.481s (+1386.3% 🔺) 85.202s (+1120.3% 🔺) 0.000s (-100.0% 🟢) 85.736s (+1037.1% 🔺) 2.256s 4 1.00x
▲ Vercel Express ⚠️ missing - - - - -
▲ Vercel Nitro ⚠️ missing - - - - -

🔍 Observability: Next.js (Turbopack)

Summary

Fastest Framework by World

Winner determined by most benchmark wins

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

Winner determined by most benchmark wins

Framework 🥇 Fastest World Wins
Express 🐘 Postgres 15/21
Next.js (Turbopack) 🐘 Postgres 11/21
Nitro 🐘 Postgres 17/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)
  • 🌐 Redis: Community world (local development)
  • 🌐 Redis + BullMQ: Community world (local development)
  • 🌐 Cloudflare: Community world (local development)
  • 🌐 MySQL: Community world (local development)
  • 🌐 Azure: Community world (local development)
  • 🌐 NATS JetStream: Community world (local development)
  • 🌐 Upstash: Community world (local development)

📋 View full workflow run


Some benchmark jobs failed:

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

Check the workflow run for details.

Sets WORKFLOW_SERVER_URL_OVERRIDE in
packages/world-vercel/src/utils.ts to
https://workflow-server-git-peter-v4.vercel.sh so that e2e tests
running off this SDK branch exercise the v4-enabled workflow-server
preview instead of production.

The override is the inline mechanism documented at the constant —
when set, it wins over both the default
(https://vercel-workflow.com) and the VERCEL_WORKFLOW_SERVER_URL
env var. The same pattern is used in v4 testing on the workflow-
server side: CI rewrites this string on PR branches. Reset to ''
before merging to main.

Companion to vercel/workflow-server#439.

Updates four tests in utils.test.ts that previously assumed the
override is empty. Each affected assertion gets a comment noting
what the expectation looks like on main; flipping back to the main
behavior is a one-line edit per test when the override is reset.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…CBOR

The matching server-side change
(workflow-server PR #439, commit 5d79cf1) now returns:

  - GET single event: full event entity CBOR-encoded in the body
    (resolves refs server-side and bakes payload into eventData).
  - LIST events: each frame's meta is the full event entity (CBOR),
    payload stays as a RefDescriptor in eventData[field], resolved
    bytes ride in the frame body.

This commit threads that through the world-vercel adapter:

  - events-v4.ts:
    * getEventV4 returns DecodedV4Event (CBOR-decode of response
      body). Drop the parseEventMetaFromHeaders / readHeader-driven
      reconstruction.
    * ListedEventV4 carries `{ event: DecodedV4Event, body:
      Uint8Array }` — the full entity plus the resolved payload bytes
      to splice in.

  - events.ts:
    * buildEventFromV4 takes (decoded entity, payload bytes) and
      splices the bytes into eventData[payloadField] for the LIST
      path. For the GET path the server already baked the bytes in,
      so buildEventFromV4 is called with an empty body.
    * CBOR-decode the payload bytes back into the original JS value
      on read. Matches the unconditional CBOR-encode on write
      (Uint8Array round-trips via cbor-x's binary type).

Why this matters: the workflow runtime's replay path reads arbitrary
fields off eventData (executionContext, hookToken, isWebhook,
resumeAt, error shape, …). The previous cherry-picked-metadata shape
dropped those fields, which is why every E2E Vercel Prod test on
this branch was getting stuck after run_started with no further
events — the runtime's invocation of the workflow function on the
workbench deployment couldn't reconstruct state correctly.

Companion to workflow-server PR #439 commit 5d79cf1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@@ -0,0 +1,5 @@
---
"@workflow/world-vercel": major
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Suggested change
"@workflow/world-vercel": major
"@workflow/world-vercel": minor

Comment thread .changeset/v4-events-client.md Outdated
"@workflow/world-vercel": major
---

Switch the world-vercel adapter's event endpoints from the v2/v3 wire format to v4. Event metadata now rides in `x-wf-*` HTTP headers and payloads stream end-to-end as opaque bytes — no server-side CBOR parse on writes, and no per-event `/refs` round-trip on list responses. POST event response carries the materialized EventResult as a CBOR body. Public `createWorkflowRunEvent` / `getEvent` / `getWorkflowRunEvents` signatures are unchanged; the underlying wire calls swap to v4. `listEventsByCorrelationId` is not yet implemented on v4 and now throws — callers should fetch hooks directly via `storage.hooks.getByToken`. Requires workflow-server with v4 routes mounted.
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Suggested change
Switch the world-vercel adapter's event endpoints from the v2/v3 wire format to v4. Event metadata now rides in `x-wf-*` HTTP headers and payloads stream end-to-end as opaque bytes — no server-side CBOR parse on writes, and no per-event `/refs` round-trip on list responses. POST event response carries the materialized EventResult as a CBOR body. Public `createWorkflowRunEvent` / `getEvent` / `getWorkflowRunEvents` signatures are unchanged; the underlying wire calls swap to v4. `listEventsByCorrelationId` is not yet implemented on v4 and now throws — callers should fetch hooks directly via `storage.hooks.getByToken`. Requires workflow-server with v4 routes mounted.
New internal API format: separately encode event metadata from user payloads. Eliminates the need for calling separate endpoints for ref resolution, which improves performance on longer runs.

VaguelySerious and others added 3 commits May 25, 2026 10:49
Companion to workflow-server PR #439 commit 2a55acd, which switched
GET /api/v4/runs/:runId/events/:eventId from a CBOR-entity body to a
single v4 frame (same wire shape as one LIST frame).

  - getEventV4 now returns `{ event: DecodedV4Event, body: Uint8Array }`
    by reading exactly one frame off the response body via
    `decodeFrames` — same reader the LIST path uses. No content-type
    branching, no separate CBOR decode path.

  - getEvent (the storage adapter wrapper) passes both pieces to
    `buildEventFromV4`, which splices the CBOR-decoded body into
    `eventData[payloadField]`. Same path LIST already uses, so no
    GET-specific shape exists anymore.

  - Drop the special-case fallback in `buildEventFromV4` that used to
    re-decode an in-eventData Uint8Array — only one input shape now.

Net effect: server-side memory for GET single-event is now bounded by
S3 chunk size (~64 KB) instead of full payload size.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Companion to workflow-server PR #439 commit 5036b56, which added
`GET /api/v4/events?correlationId=...`. The SDK adapter's
`storage.events.listByCorrelationId` no longer throws.

Implementation:

  - New `getEventsByCorrelationIdV4` wire helper alongside
    `getWorkflowRunEventsV4`. Both share a small
    `consumeListFrameStream(url, config, opName)` that drives the
    same frame-stream-to-page conversion — only the URL differs.

  - `events.ts`'s `getWorkflowRunEvents` dispatches between the two
    based on whether params carry `runId` or `correlationId`. Same
    return shape on either path.

Changeset updated to drop the "not yet implemented" caveat.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…st headers

Mirrors the server-side change in workflow-server: the POST request body
is now one length-prefixed frame containing CBOR-encoded metadata plus
the opaque payload. Eliminates the V4_HEADERS constant, the
percent-encoding for non-ASCII values, the base64-CBOR encoding for
executionContext, and the implicit 32 KB cap on Vercel header size.
The response side still uses x-wf-event-id/run-id/created-at headers
for callers that want eventId without decoding the CBOR body.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
"@workflow/world-vercel": major
---

Switch the world-vercel adapter's event endpoints from the v2/v3 wire format to v4. Event metadata now rides in `x-wf-*` HTTP headers and payloads stream end-to-end as opaque bytes — no server-side CBOR parse on writes, and no per-event `/refs` round-trip on list responses. POST event response carries the materialized EventResult as a CBOR body. GET single event and LIST events use the same `application/vnd.workflow.v4-frames` binary frame stream; `listEventsByCorrelationId` is wired through too. Public `createWorkflowRunEvent` / `getEvent` / `getWorkflowRunEvents` signatures are unchanged. Requires workflow-server with v4 routes mounted.
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Suggested change
Switch the world-vercel adapter's event endpoints from the v2/v3 wire format to v4. Event metadata now rides in `x-wf-*` HTTP headers and payloads stream end-to-end as opaque bytes — no server-side CBOR parse on writes, and no per-event `/refs` round-trip on list responses. POST event response carries the materialized EventResult as a CBOR body. GET single event and LIST events use the same `application/vnd.workflow.v4-frames` binary frame stream; `listEventsByCorrelationId` is wired through too. Public `createWorkflowRunEvent` / `getEvent` / `getWorkflowRunEvents` signatures are unchanged. Requires workflow-server with v4 routes mounted.
New internal API format: separately encode event metadata from user payloads. Eliminates the need for calling separate endpoints for ref resolution, which improves performance especially on longer runs.

VaguelySerious and others added 3 commits May 25, 2026 12:23
Payload fields (input / output / result / error / payload / metadata)
reach world-vercel after the runtime has already serialized them via
dehydrateRunError / dehydrateStepReturnValue / dehydrateStepArguments —
they're Uint8Arrays carrying a devalue blob with a format prefix.
splitEventDataForV4 was running them through cbor-x.encode again, so
the wire bytes ended up as cbor(Uint8Array). On reads through
runs.get (which goes through v2 and just returns the raw stored bytes),
the consumer saw the CBOR wrapping and hydrateRunError couldn't parse
the format prefix — every failed workflow run surfaced as
"Failed to hydrate workflow run error".

Pass the bytes through unchanged on write and read; symmetric with
world-local and the v2/v3 wire format. Throw on non-Uint8Array to flag
non-runtime callers loudly instead of silently double-wrapping.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…emitter)

Hook-emitting runtimes set eventData.token (matches the world contract
in packages/world/src/events.ts). splitEventDataForV4 was looking for
eventData.hookToken instead, so the frame meta arrived without a token
and the server's hook materialization failed validation. The v4 wire
name (meta.hookToken) is unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
cbor-x encodes Date natively (CBOR tag 1) and the server (post-23c79b9)
decodes it back to a Date for the materialization service. Stop
pre-flattening to an ISO string — that was a workaround for the original
header-based v4 contract and now leaves the runtime with a string in
eventData.resumeAt after replay, blowing up on .getTime().

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant