Add workflow versioning docs - #2010

Merged
pranaygp merged 10 commits into
mainfrom
pranaygp/codex/docs-versioning-page
May 18, 2026
Merged

Add workflow versioning docs#2010
pranaygp merged 10 commits into
mainfrom
pranaygp/codex/docs-versioning-page

Conversation

@pranaygp

@pranaygppranaygp commented May 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a new Foundations page explaining Workflow SDK versioning semantics for both v5 and v4 docs.

The page covers:

  • default run pinning to the deployment that started the run
  • canceling and rerunning affected in-flight runs on the latest deployment
  • explicit self-upgrade patterns using deploymentId: "latest"
  • carrying serializable context such as streams and abort signals across child runs

This also links existing versioning and deploymentId: "latest" mentions back to the new Foundations page, and calls out that deploymentId is currently a Vercelism that may become a more generic version concept in the World spec later.

Follow-up cookbook pass added targeted callouts for long-lived or multi-turn patterns:

  • scheduled workflows
  • DurableAgent
  • AI SDK multi-turn sessions
  • Chat SDK sessions
  • Sandbox sessions

The docs now also distinguish v5 from v4 for child-run starts. Native start() from workflow context was added by e295bae41 / #1491, which is on main but not stable, so v5 examples encourage direct workflow-context start() and v4 keeps the step-wrapped pattern.

Validation

  • git diff --check
  • Parsed the updated v4/v5 Foundations meta.json files as JSON
  • Verified v4/v5 copies of the touched cookbook pages match before the v5-only native-start pass
  • Searched docs/content for stale v5 step-wrapped start() guidance and v4 direct-start guidance
  • Confirmed origin/stable lacks the 'use step' directive in packages/core/src/runtime/start.ts, while main has it via e295bae41 / feat: allow start() to be called directly inside workflow functions #1491

Full docs lint/typecheck were not run because this checkout does not have node_modules installed, so biome, vitest, and changeset are unavailable locally.

@vercel

vercelBot commented May 18, 2026

Copy link
Copy Markdown
Contributor

@changeset-bot

changeset-botBot commented May 18, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7eff96c

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

This PR includes changesets to release 0 packages

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

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

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

@github-actions

github-actionsBot commented May 18, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

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

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Nitro0.031s (-28.3% 🟢)1.005s (~)0.974s101.00x
💻 LocalExpress0.036s (-19.6% 🟢)1.005s (~)0.970s101.15x
🐘 PostgresExpress0.045s (-21.9% 🟢)1.011s (~)0.966s101.47x
🐘 PostgresNitro0.046s (-51.3% 🟢)1.013s (-2.9%)0.967s101.50x
workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.070s (-4.9%)2.006s (~)0.936s101.00x
💻 LocalNitro1.071s (-5.3% 🟢)2.006s (~)0.935s101.00x
🐘 PostgresExpress1.079s (-5.9% 🟢)2.009s (~)0.930s101.01x
🐘 PostgresNitro1.081s (-5.2% 🟢)2.010s (~)0.929s101.01x
workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro10.396s (-4.4%)11.018s (~)0.622s31.00x
🐘 PostgresExpress10.402s (-5.1% 🟢)11.016s (~)0.614s31.00x
💻 LocalExpress10.411s (-4.7%)11.023s (~)0.612s31.00x
💻 LocalNitro10.412s (-4.9%)11.022s (~)0.610s31.00x
workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express13.432s (-10.3% 🟢)14.027s (-6.7% 🟢)0.595s51.00x
🐘 PostgresExpress13.435s (-7.9% 🟢)14.017s (-6.7% 🟢)0.581s51.00x
🐘 PostgresNitro13.484s (-7.6% 🟢)14.017s (-6.7% 🟢)0.533s51.00x
💻 LocalNitro13.489s (-10.4% 🟢)14.027s (-12.5% 🟢)0.538s51.00x
workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Nitro11.875s (-29.2% 🟢)12.022s (-29.4% 🟢)0.147s81.00x
💻 LocalExpress11.890s (-28.4% 🟢)12.022s (-29.4% 🟢)0.132s81.00x
🐘 PostgresExpress11.941s (-14.7% 🟢)12.391s (-15.1% 🟢)0.450s81.01x
🐘 PostgresNitro11.944s (-14.5% 🟢)12.266s (-14.3% 🟢)0.321s81.01x
Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.136s (-9.8% 🟢)2.007s (~)0.870s151.00x
🐘 PostgresNitro1.137s (-10.8% 🟢)2.007s (~)0.870s151.00x
💻 LocalNitro1.172s (-28.2% 🟢)2.006s (-3.3%)0.834s151.03x
💻 LocalExpress1.183s (-20.6% 🟢)2.006s (~)0.823s151.04x
Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.192s (-49.3% 🟢)2.007s (-33.3% 🟢)0.815s151.00x
🐘 PostgresExpress1.224s (-48.2% 🟢)2.007s (-33.3% 🟢)0.783s151.03x
💻 LocalExpress1.703s (-42.3% 🟢)2.005s (-41.9% 🟢)0.303s151.43x
💻 LocalNitro1.704s (-45.8% 🟢)2.005s (-48.4% 🟢)0.302s151.43x
Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.305s (-62.5% 🟢)2.008s (-49.9% 🟢)0.702s151.00x
🐘 PostgresExpress1.324s (-62.0% 🟢)2.008s (-49.9% 🟢)0.684s151.01x
💻 LocalExpress4.638s (-44.4% 🟢)5.179s (-42.6% 🟢)0.541s63.55x
💻 LocalNitro4.910s (-41.2% 🟢)5.511s (-38.9% 🟢)0.601s63.76x
Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.155s (-8.1% 🟢)2.009s (~)0.854s151.00x
🐘 PostgresNitro1.163s (-7.5% 🟢)2.010s (~)0.847s151.01x
💻 LocalExpress1.386s (-26.8% 🟢)2.006s (-15.2% 🟢)0.620s151.20x
💻 LocalNitro1.388s (-25.6% 🟢)2.006s (-14.3% 🟢)0.618s151.20x
Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.199s (-48.8% 🟢)2.008s (-33.3% 🟢)0.810s151.00x
🐘 PostgresNitro1.199s (-48.7% 🟢)2.007s (-33.3% 🟢)0.808s151.00x
💻 LocalExpress1.828s (-41.6% 🟢)2.222s (-40.9% 🟢)0.394s141.53x
💻 LocalNitro1.935s (-36.9% 🟢)2.316s (-40.4% 🟢)0.381s131.61x
Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.305s (-62.7% 🟢)2.008s (-49.9% 🟢)0.702s151.00x
🐘 PostgresNitro1.309s (-62.4% 🟢)2.009s (-49.9% 🟢)0.700s151.00x
💻 LocalExpress5.446s (-38.1% 🟢)5.849s (-36.9% 🟢)0.403s64.17x
💻 LocalNitro5.557s (-39.2% 🟢)6.179s (-38.4% 🟢)0.622s64.26x
workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.418s (-50.1% 🟢)1.006s (-1.6%)0.588s601.00x
🐘 PostgresNitro0.459s (-44.0% 🟢)1.006s (~)0.547s601.10x
💻 LocalNitro0.468s (-52.2% 🟢)1.004s (-8.2% 🟢)0.535s601.12x
💻 LocalExpress0.469s (-52.4% 🟢)1.004s (-6.7% 🟢)0.535s601.12x
workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.047s (-47.0% 🟢)1.705s (-24.5% 🟢)0.659s531.00x
🐘 PostgresNitro1.066s (-44.7% 🟢)1.576s (-25.0% 🟢)0.510s581.02x
💻 LocalNitro1.185s (-61.0% 🟢)2.006s (-46.6% 🟢)0.821s451.13x
💻 LocalExpress1.191s (-60.5% 🟢)2.005s (-44.1% 🟢)0.815s451.14x
workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express2.030s (-49.1% 🟢)2.427s (-44.4% 🟢)0.397s501.00x
🐘 PostgresNitro2.128s (-48.2% 🟢)2.660s (-42.2% 🟢)0.532s461.05x
💻 LocalNitro2.704s (-70.9% 🟢)3.032s (-69.7% 🟢)0.328s401.33x
💻 LocalExpress2.719s (-70.5% 🟢)3.057s (-69.5% 🟢)0.338s401.34x
workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.163s (-42.4% 🟢)1.005s (~)0.843s601.00x
🐘 PostgresNitro0.178s (-37.0% 🟢)1.006s (~)0.827s601.10x
💻 LocalExpress0.455s (-18.8% 🟢)1.004s (~)0.550s602.80x
💻 LocalNitro0.469s (-22.4% 🟢)1.004s (-1.7%)0.535s602.89x
workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.286s (-43.9% 🟢)1.006s (~)0.720s901.00x
🐘 PostgresNitro0.295s (-40.5% 🟢)1.006s (~)0.711s901.03x
💻 LocalNitro2.205s (-13.1% 🟢)2.944s (-2.2%)0.738s317.71x
💻 LocalExpress2.226s (-11.4% 🟢)2.943s (-2.2%)0.717s317.78x
workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.582s (-28.9% 🟢)1.007s (-1.0%)0.425s1201.00x
🐘 PostgresNitro0.634s (-19.7% 🟢)1.006s (~)0.372s1201.09x
💻 LocalNitro10.021s (-10.5% 🟢)10.611s (-9.0% 🟢)0.590s1217.21x
💻 LocalExpress10.042s (-10.3% 🟢)10.694s (-10.4% 🟢)0.652s1217.25x
Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.132s (+468.5% 🔺)2.005s (+99.6% 🔺)0.011s (-13.2% 🟢)2.018s (+98.2% 🔺)0.886s101.00x
💻 LocalNitro1.133s (+430.4% 🔺)2.005s (+99.6% 🔺)0.011s (-15.2% 🟢)2.018s (+98.1% 🔺)0.885s101.00x
🐘 PostgresNitro1.135s (+453.6% 🔺)2.001s (+100.2% 🔺)0.001s (-20.0% 🟢)2.010s (+98.7% 🔺)0.875s101.00x
🐘 PostgresExpress1.135s (+453.5% 🔺)1.999s (+100.2% 🔺)0.001s (-25.0% 🟢)2.010s (+98.7% 🔺)0.875s101.00x
stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.492s (+136.8% 🔺)2.002s (+98.9% 🔺)0.003s (-30.4% 🟢)2.023s (+97.8% 🔺)0.531s301.00x
🐘 PostgresNitro1.519s (+143.4% 🔺)2.004s (+99.0% 🔺)0.004s (-2.5%)2.027s (+98.2% 🔺)0.507s301.02x
💻 LocalNitro1.707s (+103.5% 🔺)2.013s (+98.9% 🔺)0.009s (-4.3%)2.203s (+97.4% 🔺)0.496s281.14x
💻 LocalExpress1.923s (+154.0% 🔺)2.011s (+95.4% 🔺)0.009s (-8.2% 🟢)2.422s (+132.9% 🔺)0.499s251.29x
10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.627s (-34.7% 🟢)1.033s (-19.2% 🟢)0.000s (-20.7% 🟢)1.045s (-20.0% 🟢)0.418s581.00x
🐘 PostgresNitro0.662s (-31.7% 🟢)1.029s (-17.5% 🟢)0.000s (-17.2% 🟢)1.049s (-16.6% 🟢)0.387s581.05x
💻 LocalExpress1.365s (+11.5% 🔺)2.015s (~)0.000s (+40.0% 🔺)2.018s (~)0.652s302.18x
💻 LocalNitro1.561s (+27.6% 🔺)2.016s (~)0.000s (+364.3% 🔺)2.197s (+8.7% 🔺)0.636s282.49x
fan-out fan-in 10 streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.228s (-30.7% 🟢)1.869s (-14.2% 🟢)0.000s (NaN%)1.900s (-13.6% 🟢)0.673s321.00x
🐘 PostgresNitro1.325s (-26.1% 🟢)1.997s (-6.7% 🟢)0.000s (+86.7% 🔺)2.019s (-7.2% 🟢)0.694s301.08x
💻 LocalExpress3.158s (-8.9% 🟢)4.028s (~)0.001s (-33.3% 🟢)4.030s (~)0.873s152.57x
💻 LocalNitro3.187s (-5.9% 🟢)4.029s (~)0.000s (-75.0% 🟢)4.031s (~)0.844s152.60x

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalExpress12/21
🐘 PostgresExpress17/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres16/21
Nitro🐘 Postgres17/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.

@github-actions

github-actionsBot commented May 18, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
❌ ▲ Vercel Production119642191419
✅ 💻 Local Development158702191806
✅ 📦 Local Production145802191677
❌ 🐘 Local Postgres158522191806
✅ 🪟 Windows12900129
✅ 📋 Other7270176903
Total6682610527740

❌ Failed Tests

▲ Vercel Production (4 failed)

astro (1 failed):

  • AbortController abortFromStepWorkflow: step abort cancels an in-flight sibling step

hono (2 failed):

  • outputStreamWorkflow no startIndex (reads all chunks)
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KRYMPWTNKF0CE4BP27X7R946 | 🔍 observability

nextjs-webpack (1 failed):

🐘 Local Postgres (2 failed)

nextjs-webpack-stable-lazy-discovery-disabled (1 failed):

  • DurableAgent e2e core basic text response

nextjs-webpack-stable-lazy-discovery-enabled (1 failed):

  • addTenWorkflow | wrun_01KRYMBT8QHFK9EZ9FDY03D9G0

Details by Category

❌ ▲ Vercel Production
AppPassedFailedSkipped
❌ astro102126
✅ example103026
✅ express103026
✅ fastify103026
❌ hono101226
✅ nextjs-turbopack12702
❌ nextjs-webpack12612
✅ nitro103026
✅ nuxt103026
✅ sveltekit12207
✅ vite103026
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable104025
✅ express-stable104025
✅ fastify-stable104025
✅ hono-stable104025
✅ nextjs-turbopack-canary110019
✅ nextjs-turbopack-stable-lazy-discovery-disabled12900
✅ nextjs-turbopack-stable-lazy-discovery-enabled12900
✅ nextjs-webpack-canary110019
✅ nextjs-webpack-stable-lazy-discovery-disabled12900
✅ nextjs-webpack-stable-lazy-discovery-enabled12900
✅ nitro-stable104025
✅ nuxt-stable104025
✅ sveltekit-stable12306
✅ vite-stable104025
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable104025
✅ express-stable104025
✅ fastify-stable104025
✅ hono-stable104025
✅ nextjs-turbopack-canary110019
✅ nextjs-turbopack-stable-lazy-discovery-disabled12900
✅ nextjs-webpack-canary110019
✅ nextjs-webpack-stable-lazy-discovery-disabled12900
✅ nextjs-webpack-stable-lazy-discovery-enabled12900
✅ nitro-stable104025
✅ nuxt-stable104025
✅ sveltekit-stable12306
✅ vite-stable104025
❌ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable104025
✅ express-stable104025
✅ fastify-stable104025
✅ hono-stable104025
✅ nextjs-turbopack-canary110019
✅ nextjs-turbopack-stable-lazy-discovery-disabled12900
✅ nextjs-turbopack-stable-lazy-discovery-enabled12900
✅ nextjs-webpack-canary110019
❌ nextjs-webpack-stable-lazy-discovery-disabled12810
❌ nextjs-webpack-stable-lazy-discovery-enabled12810
✅ nitro-stable104025
✅ nuxt-stable104025
✅ sveltekit-stable12306
✅ vite-stable104025
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack12900
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable104025
✅ e2e-local-dev-tanstack-start-104025
✅ e2e-local-postgres-nest-stable104025
✅ e2e-local-postgres-tanstack-start-104025
✅ e2e-local-prod-nest-stable104025
✅ e2e-local-prod-tanstack-start-104025
✅ e2e-vercel-prod-tanstack-start103026

📋 View full workflow run


Some E2E test jobs failed:

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

Check the workflow run for details.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a new "Versioning" Foundations page (v4 and v5) explaining default run pinning to deployments, recovery via cancel + rerun, opting into newer code with deploymentId: "latest", and carrying serializable state/streams across child-run continuations. Existing references to deploymentId: "latest" and versioning behavior are linked back to the new page. Cookbook pages also pick up callouts about long-lived / multi-turn patterns and, on v5 only, are updated to reflect that start() can now be called directly inside "use workflow" functions (via #1491), while v4 retains the step-wrapped pattern.

Changes:

  • New foundations/versioning.mdx for both v4 and v5, plus meta.json + index.mdx + linkbacks from vercel-world, start.mdx, and code-transform.mdx.
  • v5 cookbook + migration guides updated to drop "use step" wrappers around start() in favor of calling start() directly from the workflow function; v4 keeps the step-wrapped pattern.
  • Added "Versioning" callouts to scheduling, durable-agent, ai-sdk, chat-sdk, and sandbox cookbooks; fixed a few small wording/grammar issues in code-transform.mdx.

Reviewed changes

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

Show a summary per file
FileDescription
docs/content/docs/v5/foundations/versioning.mdxNew Foundations page explaining run pinning, recovery, and explicit upgrade boundaries.
docs/content/docs/v4/foundations/versioning.mdxv4 counterpart; uses step-wrapped continueDigest/continueExportOnLatest helpers.
docs/content/docs/v{4,5}/foundations/{meta.json,index.mdx}Surface the new Versioning page in nav and the foundations index.
docs/content/docs/v{4,5}/deploying/world/vercel-world.mdxLink the deployment-pinning section to the new Versioning page.
docs/content/docs/v{4,5}/how-it-works/code-transform.mdxLink "atomic versioning" reference; fix "function assume" / "from being upgraded" wording.
docs/content/docs/v{4,5}/api-reference/workflow-api/start.mdxSoften "Vercel-specific" to "Vercelism", mention possible version rename, link Versioning. v5 also notes native workflow-context start().
docs/content/docs/v5/foundations/starting-workflows.mdxNote v5 can call start() from workflows; link Composition + Versioning.
docs/content/docs/v5/cookbook/common-patterns/workflow-composition.mdxReplace step-wrapped child spawn with direct start() call.
docs/content/docs/v5/cookbook/advanced/child-workflows.mdxInline batched start() calls; rename spawnReportChunkstartReportChunk; update tips.
docs/content/docs/v{4,5}/cookbook/common-patterns/scheduling.mdxCallout linking to Versioning for long-lived schedules.
docs/content/docs/v{4,5}/cookbook/agent-patterns/durable-agent.mdxCallout linking to Versioning for multi-turn agents.
docs/content/docs/v{4,5}/cookbook/integrations/{ai-sdk,chat-sdk,sandbox}.mdxCallouts linking to Versioning for long-lived sessions.
docs/content/docs/v4/cookbook/common-patterns/workflow-composition.mdxUpdate deploymentId: "latest" callout wording + link to Versioning.
docs/content/docs/v4/cookbook/advanced/child-workflows.mdxLink Versioning from the deploymentId: "latest" tip.
docs/content/docs/v4/changelog/eager-processing.mdxReword to "step-wrapped start() helper" to match v4 phrasing.
docs/content/docs/v5/migration-guides/{migrating-from-trigger-dev,migrating-from-temporal,migrating-from-inngest,migrating-from-aws-step-functions}.mdxUpdate to v5 native workflow-context start(); only collect step retains "use step".

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

@TooTallNateTooTallNate left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Comment-only review

The new versioning foundations page is a useful addition — the four sections (default pinning → recovery → self-upgrade via start({ deploymentId: "latest" }) → carrying serializable context forward) cover the model clearly, and the v4-vs-v5 differentiation (step-wrapped start() vs direct start() from workflow context, gated on whether PR #1491 has landed on the target branch) is correctly handled. The cross-links from cookbook patterns to the new foundations page tie everything together nicely.

Three observations — see inline.

Inline comments

  1. Wording: this PR introduces "Vercelism" as a new term and uses it 6 times across the diff, including replacing existing "Vercel-specific feature" wording in two <Callout>s. "Vercelism" reads as informal slang and isn't part of the established docs vocabulary. The existing tone uses "Vercel-specific", "Vercel deployments", "Vercel World", "non-Vercel" — all precise. Suggested restoring the prior phrasing. This is the only thing I'd consider blocking.
  2. Broken link in v4: versioning.mdx references /docs/foundations/cancellation in its related frontmatter, but that page is v5-only. Easy fix.
  3. Missing changeset: convention for docs-only PRs is an empty ---\n--- file.

A few small things I noticed

  • The pre-emptively check for a conflict with getHookByToken() example (line 96 of versioning.mdx) — nice that you noted the race window in a later doc (#2011 callout), but this page doesn't have that warning. Worth a cross-link or <Callout type="warn"> here too, since the recovery pattern uses both start() and deploymentId: "latest" together.
  • The _idempotency / using syntax is great. Worth confirming the docs site's syntax highlighter renders it — I noticed #1988 recently fixed a homepage link lint regression, and the using syntax is TypeScript 5.2+ specific.
  • dailyDigest example (line 137-152): the state parameter is DigestState but the workflow doesn't actually use state.userId after the first sendDigest call — pattern is fine, just noting if you wanted to make the example illustrate state evolution more vividly, having sendDigest read state.lastSentAt (e.g. to avoid sending duplicates) would make the carry-forward intent clearer.

Overall the page reads well — once the Vercelism wording is restored and the v4 link is fixed, this should be good to go.

Comment threaddocs/content/docs/v5/api-reference/workflow-api/start.mdx Outdated
Comment threaddocs/content/docs/v4/foundations/versioning.mdx
Comment threaddocs/content/docs/v5/foundations/versioning.mdx

@TooTallNateTooTallNate left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

All three review comments addressed in 7eff96c — Vercelism wording reverted, v4 broken cancellation link fixed, empty changeset added. LGTM, approving.

@github-actions

Copy link
Copy Markdown
Contributor

Backport PR opened against stable: #2014. Merge conflicts were resolved by AI — please review carefully.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

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

Add workflow versioning docs - #2010

Merged
pranaygp merged 10 commits into
mainfrom
pranaygp/codex/docs-versioning-page
May 18, 2026
Merged

Add workflow versioning docs#2010
pranaygp merged 10 commits into
mainfrom
pranaygp/codex/docs-versioning-page

Conversation

@pranaygp

@pranaygppranaygp commented May 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a new Foundations page explaining Workflow SDK versioning semantics for both v5 and v4 docs.

The page covers:

  • default run pinning to the deployment that started the run
  • canceling and rerunning affected in-flight runs on the latest deployment
  • explicit self-upgrade patterns using deploymentId: "latest"
  • carrying serializable context such as streams and abort signals across child runs

This also links existing versioning and deploymentId: "latest" mentions back to the new Foundations page, and calls out that deploymentId is currently a Vercelism that may become a more generic version concept in the World spec later.

Follow-up cookbook pass added targeted callouts for long-lived or multi-turn patterns:

  • scheduled workflows
  • DurableAgent
  • AI SDK multi-turn sessions
  • Chat SDK sessions
  • Sandbox sessions

The docs now also distinguish v5 from v4 for child-run starts. Native start() from workflow context was added by e295bae41 / #1491, which is on main but not stable, so v5 examples encourage direct workflow-context start() and v4 keeps the step-wrapped pattern.

Validation

  • git diff --check
  • Parsed the updated v4/v5 Foundations meta.json files as JSON
  • Verified v4/v5 copies of the touched cookbook pages match before the v5-only native-start pass
  • Searched docs/content for stale v5 step-wrapped start() guidance and v4 direct-start guidance
  • Confirmed origin/stable lacks the 'use step' directive in packages/core/src/runtime/start.ts, while main has it via e295bae41 / feat: allow start() to be called directly inside workflow functions #1491

Full docs lint/typecheck were not run because this checkout does not have node_modules installed, so biome, vitest, and changeset are unavailable locally.

@vercel

vercelBot commented May 18, 2026

Copy link
Copy Markdown
Contributor

@changeset-bot

changeset-botBot commented May 18, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7eff96c

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

This PR includes changesets to release 0 packages

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

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

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

@github-actions

github-actionsBot commented May 18, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

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

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Nitro0.031s (-28.3% 🟢)1.005s (~)0.974s101.00x
💻 LocalExpress0.036s (-19.6% 🟢)1.005s (~)0.970s101.15x
🐘 PostgresExpress0.045s (-21.9% 🟢)1.011s (~)0.966s101.47x
🐘 PostgresNitro0.046s (-51.3% 🟢)1.013s (-2.9%)0.967s101.50x
workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.070s (-4.9%)2.006s (~)0.936s101.00x
💻 LocalNitro1.071s (-5.3% 🟢)2.006s (~)0.935s101.00x
🐘 PostgresExpress1.079s (-5.9% 🟢)2.009s (~)0.930s101.01x
🐘 PostgresNitro1.081s (-5.2% 🟢)2.010s (~)0.929s101.01x
workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro10.396s (-4.4%)11.018s (~)0.622s31.00x
🐘 PostgresExpress10.402s (-5.1% 🟢)11.016s (~)0.614s31.00x
💻 LocalExpress10.411s (-4.7%)11.023s (~)0.612s31.00x
💻 LocalNitro10.412s (-4.9%)11.022s (~)0.610s31.00x
workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express13.432s (-10.3% 🟢)14.027s (-6.7% 🟢)0.595s51.00x
🐘 PostgresExpress13.435s (-7.9% 🟢)14.017s (-6.7% 🟢)0.581s51.00x
🐘 PostgresNitro13.484s (-7.6% 🟢)14.017s (-6.7% 🟢)0.533s51.00x
💻 LocalNitro13.489s (-10.4% 🟢)14.027s (-12.5% 🟢)0.538s51.00x
workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Nitro11.875s (-29.2% 🟢)12.022s (-29.4% 🟢)0.147s81.00x
💻 LocalExpress11.890s (-28.4% 🟢)12.022s (-29.4% 🟢)0.132s81.00x
🐘 PostgresExpress11.941s (-14.7% 🟢)12.391s (-15.1% 🟢)0.450s81.01x
🐘 PostgresNitro11.944s (-14.5% 🟢)12.266s (-14.3% 🟢)0.321s81.01x
Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.136s (-9.8% 🟢)2.007s (~)0.870s151.00x
🐘 PostgresNitro1.137s (-10.8% 🟢)2.007s (~)0.870s151.00x
💻 LocalNitro1.172s (-28.2% 🟢)2.006s (-3.3%)0.834s151.03x
💻 LocalExpress1.183s (-20.6% 🟢)2.006s (~)0.823s151.04x
Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.192s (-49.3% 🟢)2.007s (-33.3% 🟢)0.815s151.00x
🐘 PostgresExpress1.224s (-48.2% 🟢)2.007s (-33.3% 🟢)0.783s151.03x
💻 LocalExpress1.703s (-42.3% 🟢)2.005s (-41.9% 🟢)0.303s151.43x
💻 LocalNitro1.704s (-45.8% 🟢)2.005s (-48.4% 🟢)0.302s151.43x
Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.305s (-62.5% 🟢)2.008s (-49.9% 🟢)0.702s151.00x
🐘 PostgresExpress1.324s (-62.0% 🟢)2.008s (-49.9% 🟢)0.684s151.01x
💻 LocalExpress4.638s (-44.4% 🟢)5.179s (-42.6% 🟢)0.541s63.55x
💻 LocalNitro4.910s (-41.2% 🟢)5.511s (-38.9% 🟢)0.601s63.76x
Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.155s (-8.1% 🟢)2.009s (~)0.854s151.00x
🐘 PostgresNitro1.163s (-7.5% 🟢)2.010s (~)0.847s151.01x
💻 LocalExpress1.386s (-26.8% 🟢)2.006s (-15.2% 🟢)0.620s151.20x
💻 LocalNitro1.388s (-25.6% 🟢)2.006s (-14.3% 🟢)0.618s151.20x
Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.199s (-48.8% 🟢)2.008s (-33.3% 🟢)0.810s151.00x
🐘 PostgresNitro1.199s (-48.7% 🟢)2.007s (-33.3% 🟢)0.808s151.00x
💻 LocalExpress1.828s (-41.6% 🟢)2.222s (-40.9% 🟢)0.394s141.53x
💻 LocalNitro1.935s (-36.9% 🟢)2.316s (-40.4% 🟢)0.381s131.61x
Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.305s (-62.7% 🟢)2.008s (-49.9% 🟢)0.702s151.00x
🐘 PostgresNitro1.309s (-62.4% 🟢)2.009s (-49.9% 🟢)0.700s151.00x
💻 LocalExpress5.446s (-38.1% 🟢)5.849s (-36.9% 🟢)0.403s64.17x
💻 LocalNitro5.557s (-39.2% 🟢)6.179s (-38.4% 🟢)0.622s64.26x
workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.418s (-50.1% 🟢)1.006s (-1.6%)0.588s601.00x
🐘 PostgresNitro0.459s (-44.0% 🟢)1.006s (~)0.547s601.10x
💻 LocalNitro0.468s (-52.2% 🟢)1.004s (-8.2% 🟢)0.535s601.12x
💻 LocalExpress0.469s (-52.4% 🟢)1.004s (-6.7% 🟢)0.535s601.12x
workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.047s (-47.0% 🟢)1.705s (-24.5% 🟢)0.659s531.00x
🐘 PostgresNitro1.066s (-44.7% 🟢)1.576s (-25.0% 🟢)0.510s581.02x
💻 LocalNitro1.185s (-61.0% 🟢)2.006s (-46.6% 🟢)0.821s451.13x
💻 LocalExpress1.191s (-60.5% 🟢)2.005s (-44.1% 🟢)0.815s451.14x
workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express2.030s (-49.1% 🟢)2.427s (-44.4% 🟢)0.397s501.00x
🐘 PostgresNitro2.128s (-48.2% 🟢)2.660s (-42.2% 🟢)0.532s461.05x
💻 LocalNitro2.704s (-70.9% 🟢)3.032s (-69.7% 🟢)0.328s401.33x
💻 LocalExpress2.719s (-70.5% 🟢)3.057s (-69.5% 🟢)0.338s401.34x
workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.163s (-42.4% 🟢)1.005s (~)0.843s601.00x
🐘 PostgresNitro0.178s (-37.0% 🟢)1.006s (~)0.827s601.10x
💻 LocalExpress0.455s (-18.8% 🟢)1.004s (~)0.550s602.80x
💻 LocalNitro0.469s (-22.4% 🟢)1.004s (-1.7%)0.535s602.89x
workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.286s (-43.9% 🟢)1.006s (~)0.720s901.00x
🐘 PostgresNitro0.295s (-40.5% 🟢)1.006s (~)0.711s901.03x
💻 LocalNitro2.205s (-13.1% 🟢)2.944s (-2.2%)0.738s317.71x
💻 LocalExpress2.226s (-11.4% 🟢)2.943s (-2.2%)0.717s317.78x
workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.582s (-28.9% 🟢)1.007s (-1.0%)0.425s1201.00x
🐘 PostgresNitro0.634s (-19.7% 🟢)1.006s (~)0.372s1201.09x
💻 LocalNitro10.021s (-10.5% 🟢)10.611s (-9.0% 🟢)0.590s1217.21x
💻 LocalExpress10.042s (-10.3% 🟢)10.694s (-10.4% 🟢)0.652s1217.25x
Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.132s (+468.5% 🔺)2.005s (+99.6% 🔺)0.011s (-13.2% 🟢)2.018s (+98.2% 🔺)0.886s101.00x
💻 LocalNitro1.133s (+430.4% 🔺)2.005s (+99.6% 🔺)0.011s (-15.2% 🟢)2.018s (+98.1% 🔺)0.885s101.00x
🐘 PostgresNitro1.135s (+453.6% 🔺)2.001s (+100.2% 🔺)0.001s (-20.0% 🟢)2.010s (+98.7% 🔺)0.875s101.00x
🐘 PostgresExpress1.135s (+453.5% 🔺)1.999s (+100.2% 🔺)0.001s (-25.0% 🟢)2.010s (+98.7% 🔺)0.875s101.00x
stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.492s (+136.8% 🔺)2.002s (+98.9% 🔺)0.003s (-30.4% 🟢)2.023s (+97.8% 🔺)0.531s301.00x
🐘 PostgresNitro1.519s (+143.4% 🔺)2.004s (+99.0% 🔺)0.004s (-2.5%)2.027s (+98.2% 🔺)0.507s301.02x
💻 LocalNitro1.707s (+103.5% 🔺)2.013s (+98.9% 🔺)0.009s (-4.3%)2.203s (+97.4% 🔺)0.496s281.14x
💻 LocalExpress1.923s (+154.0% 🔺)2.011s (+95.4% 🔺)0.009s (-8.2% 🟢)2.422s (+132.9% 🔺)0.499s251.29x
10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.627s (-34.7% 🟢)1.033s (-19.2% 🟢)0.000s (-20.7% 🟢)1.045s (-20.0% 🟢)0.418s581.00x
🐘 PostgresNitro0.662s (-31.7% 🟢)1.029s (-17.5% 🟢)0.000s (-17.2% 🟢)1.049s (-16.6% 🟢)0.387s581.05x
💻 LocalExpress1.365s (+11.5% 🔺)2.015s (~)0.000s (+40.0% 🔺)2.018s (~)0.652s302.18x
💻 LocalNitro1.561s (+27.6% 🔺)2.016s (~)0.000s (+364.3% 🔺)2.197s (+8.7% 🔺)0.636s282.49x
fan-out fan-in 10 streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.228s (-30.7% 🟢)1.869s (-14.2% 🟢)0.000s (NaN%)1.900s (-13.6% 🟢)0.673s321.00x
🐘 PostgresNitro1.325s (-26.1% 🟢)1.997s (-6.7% 🟢)0.000s (+86.7% 🔺)2.019s (-7.2% 🟢)0.694s301.08x
💻 LocalExpress3.158s (-8.9% 🟢)4.028s (~)0.001s (-33.3% 🟢)4.030s (~)0.873s152.57x
💻 LocalNitro3.187s (-5.9% 🟢)4.029s (~)0.000s (-75.0% 🟢)4.031s (~)0.844s152.60x

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalExpress12/21
🐘 PostgresExpress17/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres16/21
Nitro🐘 Postgres17/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.

@github-actions

github-actionsBot commented May 18, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
❌ ▲ Vercel Production119642191419
✅ 💻 Local Development158702191806
✅ 📦 Local Production145802191677
❌ 🐘 Local Postgres158522191806
✅ 🪟 Windows12900129
✅ 📋 Other7270176903
Total6682610527740

❌ Failed Tests

▲ Vercel Production (4 failed)

astro (1 failed):

  • AbortController abortFromStepWorkflow: step abort cancels an in-flight sibling step

hono (2 failed):

  • outputStreamWorkflow no startIndex (reads all chunks)
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KRYMPWTNKF0CE4BP27X7R946 | 🔍 observability

nextjs-webpack (1 failed):

🐘 Local Postgres (2 failed)

nextjs-webpack-stable-lazy-discovery-disabled (1 failed):

  • DurableAgent e2e core basic text response

nextjs-webpack-stable-lazy-discovery-enabled (1 failed):

  • addTenWorkflow | wrun_01KRYMBT8QHFK9EZ9FDY03D9G0

Details by Category

❌ ▲ Vercel Production
AppPassedFailedSkipped
❌ astro102126
✅ example103026
✅ express103026
✅ fastify103026
❌ hono101226
✅ nextjs-turbopack12702
❌ nextjs-webpack12612
✅ nitro103026
✅ nuxt103026
✅ sveltekit12207
✅ vite103026
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable104025
✅ express-stable104025
✅ fastify-stable104025
✅ hono-stable104025
✅ nextjs-turbopack-canary110019
✅ nextjs-turbopack-stable-lazy-discovery-disabled12900
✅ nextjs-turbopack-stable-lazy-discovery-enabled12900
✅ nextjs-webpack-canary110019
✅ nextjs-webpack-stable-lazy-discovery-disabled12900
✅ nextjs-webpack-stable-lazy-discovery-enabled12900
✅ nitro-stable104025
✅ nuxt-stable104025
✅ sveltekit-stable12306
✅ vite-stable104025
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable104025
✅ express-stable104025
✅ fastify-stable104025
✅ hono-stable104025
✅ nextjs-turbopack-canary110019
✅ nextjs-turbopack-stable-lazy-discovery-disabled12900
✅ nextjs-webpack-canary110019
✅ nextjs-webpack-stable-lazy-discovery-disabled12900
✅ nextjs-webpack-stable-lazy-discovery-enabled12900
✅ nitro-stable104025
✅ nuxt-stable104025
✅ sveltekit-stable12306
✅ vite-stable104025
❌ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable104025
✅ express-stable104025
✅ fastify-stable104025
✅ hono-stable104025
✅ nextjs-turbopack-canary110019
✅ nextjs-turbopack-stable-lazy-discovery-disabled12900
✅ nextjs-turbopack-stable-lazy-discovery-enabled12900
✅ nextjs-webpack-canary110019
❌ nextjs-webpack-stable-lazy-discovery-disabled12810
❌ nextjs-webpack-stable-lazy-discovery-enabled12810
✅ nitro-stable104025
✅ nuxt-stable104025
✅ sveltekit-stable12306
✅ vite-stable104025
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack12900
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable104025
✅ e2e-local-dev-tanstack-start-104025
✅ e2e-local-postgres-nest-stable104025
✅ e2e-local-postgres-tanstack-start-104025
✅ e2e-local-prod-nest-stable104025
✅ e2e-local-prod-tanstack-start-104025
✅ e2e-vercel-prod-tanstack-start103026

📋 View full workflow run


Some E2E test jobs failed:

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

Check the workflow run for details.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a new "Versioning" Foundations page (v4 and v5) explaining default run pinning to deployments, recovery via cancel + rerun, opting into newer code with deploymentId: "latest", and carrying serializable state/streams across child-run continuations. Existing references to deploymentId: "latest" and versioning behavior are linked back to the new page. Cookbook pages also pick up callouts about long-lived / multi-turn patterns and, on v5 only, are updated to reflect that start() can now be called directly inside "use workflow" functions (via #1491), while v4 retains the step-wrapped pattern.

Changes:

  • New foundations/versioning.mdx for both v4 and v5, plus meta.json + index.mdx + linkbacks from vercel-world, start.mdx, and code-transform.mdx.
  • v5 cookbook + migration guides updated to drop "use step" wrappers around start() in favor of calling start() directly from the workflow function; v4 keeps the step-wrapped pattern.
  • Added "Versioning" callouts to scheduling, durable-agent, ai-sdk, chat-sdk, and sandbox cookbooks; fixed a few small wording/grammar issues in code-transform.mdx.

Reviewed changes

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

Show a summary per file
FileDescription
docs/content/docs/v5/foundations/versioning.mdxNew Foundations page explaining run pinning, recovery, and explicit upgrade boundaries.
docs/content/docs/v4/foundations/versioning.mdxv4 counterpart; uses step-wrapped continueDigest/continueExportOnLatest helpers.
docs/content/docs/v{4,5}/foundations/{meta.json,index.mdx}Surface the new Versioning page in nav and the foundations index.
docs/content/docs/v{4,5}/deploying/world/vercel-world.mdxLink the deployment-pinning section to the new Versioning page.
docs/content/docs/v{4,5}/how-it-works/code-transform.mdxLink "atomic versioning" reference; fix "function assume" / "from being upgraded" wording.
docs/content/docs/v{4,5}/api-reference/workflow-api/start.mdxSoften "Vercel-specific" to "Vercelism", mention possible version rename, link Versioning. v5 also notes native workflow-context start().
docs/content/docs/v5/foundations/starting-workflows.mdxNote v5 can call start() from workflows; link Composition + Versioning.
docs/content/docs/v5/cookbook/common-patterns/workflow-composition.mdxReplace step-wrapped child spawn with direct start() call.
docs/content/docs/v5/cookbook/advanced/child-workflows.mdxInline batched start() calls; rename spawnReportChunkstartReportChunk; update tips.
docs/content/docs/v{4,5}/cookbook/common-patterns/scheduling.mdxCallout linking to Versioning for long-lived schedules.
docs/content/docs/v{4,5}/cookbook/agent-patterns/durable-agent.mdxCallout linking to Versioning for multi-turn agents.
docs/content/docs/v{4,5}/cookbook/integrations/{ai-sdk,chat-sdk,sandbox}.mdxCallouts linking to Versioning for long-lived sessions.
docs/content/docs/v4/cookbook/common-patterns/workflow-composition.mdxUpdate deploymentId: "latest" callout wording + link to Versioning.
docs/content/docs/v4/cookbook/advanced/child-workflows.mdxLink Versioning from the deploymentId: "latest" tip.
docs/content/docs/v4/changelog/eager-processing.mdxReword to "step-wrapped start() helper" to match v4 phrasing.
docs/content/docs/v5/migration-guides/{migrating-from-trigger-dev,migrating-from-temporal,migrating-from-inngest,migrating-from-aws-step-functions}.mdxUpdate to v5 native workflow-context start(); only collect step retains "use step".

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

@TooTallNateTooTallNate left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Comment-only review

The new versioning foundations page is a useful addition — the four sections (default pinning → recovery → self-upgrade via start({ deploymentId: "latest" }) → carrying serializable context forward) cover the model clearly, and the v4-vs-v5 differentiation (step-wrapped start() vs direct start() from workflow context, gated on whether PR #1491 has landed on the target branch) is correctly handled. The cross-links from cookbook patterns to the new foundations page tie everything together nicely.

Three observations — see inline.

Inline comments

  1. Wording: this PR introduces "Vercelism" as a new term and uses it 6 times across the diff, including replacing existing "Vercel-specific feature" wording in two <Callout>s. "Vercelism" reads as informal slang and isn't part of the established docs vocabulary. The existing tone uses "Vercel-specific", "Vercel deployments", "Vercel World", "non-Vercel" — all precise. Suggested restoring the prior phrasing. This is the only thing I'd consider blocking.
  2. Broken link in v4: versioning.mdx references /docs/foundations/cancellation in its related frontmatter, but that page is v5-only. Easy fix.
  3. Missing changeset: convention for docs-only PRs is an empty ---\n--- file.

A few small things I noticed

  • The pre-emptively check for a conflict with getHookByToken() example (line 96 of versioning.mdx) — nice that you noted the race window in a later doc (#2011 callout), but this page doesn't have that warning. Worth a cross-link or <Callout type="warn"> here too, since the recovery pattern uses both start() and deploymentId: "latest" together.
  • The _idempotency / using syntax is great. Worth confirming the docs site's syntax highlighter renders it — I noticed #1988 recently fixed a homepage link lint regression, and the using syntax is TypeScript 5.2+ specific.
  • dailyDigest example (line 137-152): the state parameter is DigestState but the workflow doesn't actually use state.userId after the first sendDigest call — pattern is fine, just noting if you wanted to make the example illustrate state evolution more vividly, having sendDigest read state.lastSentAt (e.g. to avoid sending duplicates) would make the carry-forward intent clearer.

Overall the page reads well — once the Vercelism wording is restored and the v4 link is fixed, this should be good to go.

Comment threaddocs/content/docs/v5/api-reference/workflow-api/start.mdx Outdated
Comment threaddocs/content/docs/v4/foundations/versioning.mdx
Comment threaddocs/content/docs/v5/foundations/versioning.mdx

@TooTallNateTooTallNate left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

All three review comments addressed in 7eff96c — Vercelism wording reverted, v4 broken cancellation link fixed, empty changeset added. LGTM, approving.

@github-actions

Copy link
Copy Markdown
Contributor

Backport PR opened against stable: #2014. Merge conflicts were resolved by AI — please review carefully.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

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

Add workflow versioning docs - #2010

Merged
pranaygp merged 10 commits into
mainfrom
pranaygp/codex/docs-versioning-page
May 18, 2026
Merged

Add workflow versioning docs#2010
pranaygp merged 10 commits into
mainfrom
pranaygp/codex/docs-versioning-page

Conversation

@pranaygp

@pranaygppranaygp commented May 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a new Foundations page explaining Workflow SDK versioning semantics for both v5 and v4 docs.

The page covers:

  • default run pinning to the deployment that started the run
  • canceling and rerunning affected in-flight runs on the latest deployment
  • explicit self-upgrade patterns using deploymentId: "latest"
  • carrying serializable context such as streams and abort signals across child runs

This also links existing versioning and deploymentId: "latest" mentions back to the new Foundations page, and calls out that deploymentId is currently a Vercelism that may become a more generic version concept in the World spec later.

Follow-up cookbook pass added targeted callouts for long-lived or multi-turn patterns:

  • scheduled workflows
  • DurableAgent
  • AI SDK multi-turn sessions
  • Chat SDK sessions
  • Sandbox sessions

The docs now also distinguish v5 from v4 for child-run starts. Native start() from workflow context was added by e295bae41 / #1491, which is on main but not stable, so v5 examples encourage direct workflow-context start() and v4 keeps the step-wrapped pattern.

Validation

  • git diff --check
  • Parsed the updated v4/v5 Foundations meta.json files as JSON
  • Verified v4/v5 copies of the touched cookbook pages match before the v5-only native-start pass
  • Searched docs/content for stale v5 step-wrapped start() guidance and v4 direct-start guidance
  • Confirmed origin/stable lacks the 'use step' directive in packages/core/src/runtime/start.ts, while main has it via e295bae41 / feat: allow start() to be called directly inside workflow functions #1491

Full docs lint/typecheck were not run because this checkout does not have node_modules installed, so biome, vitest, and changeset are unavailable locally.

@vercel

vercelBot commented May 18, 2026

Copy link
Copy Markdown
Contributor

@changeset-bot

changeset-botBot commented May 18, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7eff96c

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

This PR includes changesets to release 0 packages

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

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

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

@github-actions

github-actionsBot commented May 18, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

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

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Nitro0.031s (-28.3% 🟢)1.005s (~)0.974s101.00x
💻 LocalExpress0.036s (-19.6% 🟢)1.005s (~)0.970s101.15x
🐘 PostgresExpress0.045s (-21.9% 🟢)1.011s (~)0.966s101.47x
🐘 PostgresNitro0.046s (-51.3% 🟢)1.013s (-2.9%)0.967s101.50x
workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.070s (-4.9%)2.006s (~)0.936s101.00x
💻 LocalNitro1.071s (-5.3% 🟢)2.006s (~)0.935s101.00x
🐘 PostgresExpress1.079s (-5.9% 🟢)2.009s (~)0.930s101.01x
🐘 PostgresNitro1.081s (-5.2% 🟢)2.010s (~)0.929s101.01x
workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro10.396s (-4.4%)11.018s (~)0.622s31.00x
🐘 PostgresExpress10.402s (-5.1% 🟢)11.016s (~)0.614s31.00x
💻 LocalExpress10.411s (-4.7%)11.023s (~)0.612s31.00x
💻 LocalNitro10.412s (-4.9%)11.022s (~)0.610s31.00x
workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express13.432s (-10.3% 🟢)14.027s (-6.7% 🟢)0.595s51.00x
🐘 PostgresExpress13.435s (-7.9% 🟢)14.017s (-6.7% 🟢)0.581s51.00x
🐘 PostgresNitro13.484s (-7.6% 🟢)14.017s (-6.7% 🟢)0.533s51.00x
💻 LocalNitro13.489s (-10.4% 🟢)14.027s (-12.5% 🟢)0.538s51.00x
workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Nitro11.875s (-29.2% 🟢)12.022s (-29.4% 🟢)0.147s81.00x
💻 LocalExpress11.890s (-28.4% 🟢)12.022s (-29.4% 🟢)0.132s81.00x
🐘 PostgresExpress11.941s (-14.7% 🟢)12.391s (-15.1% 🟢)0.450s81.01x
🐘 PostgresNitro11.944s (-14.5% 🟢)12.266s (-14.3% 🟢)0.321s81.01x
Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.136s (-9.8% 🟢)2.007s (~)0.870s151.00x
🐘 PostgresNitro1.137s (-10.8% 🟢)2.007s (~)0.870s151.00x
💻 LocalNitro1.172s (-28.2% 🟢)2.006s (-3.3%)0.834s151.03x
💻 LocalExpress1.183s (-20.6% 🟢)2.006s (~)0.823s151.04x
Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.192s (-49.3% 🟢)2.007s (-33.3% 🟢)0.815s151.00x
🐘 PostgresExpress1.224s (-48.2% 🟢)2.007s (-33.3% 🟢)0.783s151.03x
💻 LocalExpress1.703s (-42.3% 🟢)2.005s (-41.9% 🟢)0.303s151.43x
💻 LocalNitro1.704s (-45.8% 🟢)2.005s (-48.4% 🟢)0.302s151.43x
Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.305s (-62.5% 🟢)2.008s (-49.9% 🟢)0.702s151.00x
🐘 PostgresExpress1.324s (-62.0% 🟢)2.008s (-49.9% 🟢)0.684s151.01x
💻 LocalExpress4.638s (-44.4% 🟢)5.179s (-42.6% 🟢)0.541s63.55x
💻 LocalNitro4.910s (-41.2% 🟢)5.511s (-38.9% 🟢)0.601s63.76x
Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.155s (-8.1% 🟢)2.009s (~)0.854s151.00x
🐘 PostgresNitro1.163s (-7.5% 🟢)2.010s (~)0.847s151.01x
💻 LocalExpress1.386s (-26.8% 🟢)2.006s (-15.2% 🟢)0.620s151.20x
💻 LocalNitro1.388s (-25.6% 🟢)2.006s (-14.3% 🟢)0.618s151.20x
Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.199s (-48.8% 🟢)2.008s (-33.3% 🟢)0.810s151.00x
🐘 PostgresNitro1.199s (-48.7% 🟢)2.007s (-33.3% 🟢)0.808s151.00x
💻 LocalExpress1.828s (-41.6% 🟢)2.222s (-40.9% 🟢)0.394s141.53x
💻 LocalNitro1.935s (-36.9% 🟢)2.316s (-40.4% 🟢)0.381s131.61x
Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.305s (-62.7% 🟢)2.008s (-49.9% 🟢)0.702s151.00x
🐘 PostgresNitro1.309s (-62.4% 🟢)2.009s (-49.9% 🟢)0.700s151.00x
💻 LocalExpress5.446s (-38.1% 🟢)5.849s (-36.9% 🟢)0.403s64.17x
💻 LocalNitro5.557s (-39.2% 🟢)6.179s (-38.4% 🟢)0.622s64.26x
workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.418s (-50.1% 🟢)1.006s (-1.6%)0.588s601.00x
🐘 PostgresNitro0.459s (-44.0% 🟢)1.006s (~)0.547s601.10x
💻 LocalNitro0.468s (-52.2% 🟢)1.004s (-8.2% 🟢)0.535s601.12x
💻 LocalExpress0.469s (-52.4% 🟢)1.004s (-6.7% 🟢)0.535s601.12x
workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.047s (-47.0% 🟢)1.705s (-24.5% 🟢)0.659s531.00x
🐘 PostgresNitro1.066s (-44.7% 🟢)1.576s (-25.0% 🟢)0.510s581.02x
💻 LocalNitro1.185s (-61.0% 🟢)2.006s (-46.6% 🟢)0.821s451.13x
💻 LocalExpress1.191s (-60.5% 🟢)2.005s (-44.1% 🟢)0.815s451.14x
workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express2.030s (-49.1% 🟢)2.427s (-44.4% 🟢)0.397s501.00x
🐘 PostgresNitro2.128s (-48.2% 🟢)2.660s (-42.2% 🟢)0.532s461.05x
💻 LocalNitro2.704s (-70.9% 🟢)3.032s (-69.7% 🟢)0.328s401.33x
💻 LocalExpress2.719s (-70.5% 🟢)3.057s (-69.5% 🟢)0.338s401.34x
workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.163s (-42.4% 🟢)1.005s (~)0.843s601.00x
🐘 PostgresNitro0.178s (-37.0% 🟢)1.006s (~)0.827s601.10x
💻 LocalExpress0.455s (-18.8% 🟢)1.004s (~)0.550s602.80x
💻 LocalNitro0.469s (-22.4% 🟢)1.004s (-1.7%)0.535s602.89x
workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.286s (-43.9% 🟢)1.006s (~)0.720s901.00x
🐘 PostgresNitro0.295s (-40.5% 🟢)1.006s (~)0.711s901.03x
💻 LocalNitro2.205s (-13.1% 🟢)2.944s (-2.2%)0.738s317.71x
💻 LocalExpress2.226s (-11.4% 🟢)2.943s (-2.2%)0.717s317.78x
workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.582s (-28.9% 🟢)1.007s (-1.0%)0.425s1201.00x
🐘 PostgresNitro0.634s (-19.7% 🟢)1.006s (~)0.372s1201.09x
💻 LocalNitro10.021s (-10.5% 🟢)10.611s (-9.0% 🟢)0.590s1217.21x
💻 LocalExpress10.042s (-10.3% 🟢)10.694s (-10.4% 🟢)0.652s1217.25x
Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.132s (+468.5% 🔺)2.005s (+99.6% 🔺)0.011s (-13.2% 🟢)2.018s (+98.2% 🔺)0.886s101.00x
💻 LocalNitro1.133s (+430.4% 🔺)2.005s (+99.6% 🔺)0.011s (-15.2% 🟢)2.018s (+98.1% 🔺)0.885s101.00x
🐘 PostgresNitro1.135s (+453.6% 🔺)2.001s (+100.2% 🔺)0.001s (-20.0% 🟢)2.010s (+98.7% 🔺)0.875s101.00x
🐘 PostgresExpress1.135s (+453.5% 🔺)1.999s (+100.2% 🔺)0.001s (-25.0% 🟢)2.010s (+98.7% 🔺)0.875s101.00x
stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.492s (+136.8% 🔺)2.002s (+98.9% 🔺)0.003s (-30.4% 🟢)2.023s (+97.8% 🔺)0.531s301.00x
🐘 PostgresNitro1.519s (+143.4% 🔺)2.004s (+99.0% 🔺)0.004s (-2.5%)2.027s (+98.2% 🔺)0.507s301.02x
💻 LocalNitro1.707s (+103.5% 🔺)2.013s (+98.9% 🔺)0.009s (-4.3%)2.203s (+97.4% 🔺)0.496s281.14x
💻 LocalExpress1.923s (+154.0% 🔺)2.011s (+95.4% 🔺)0.009s (-8.2% 🟢)2.422s (+132.9% 🔺)0.499s251.29x
10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.627s (-34.7% 🟢)1.033s (-19.2% 🟢)0.000s (-20.7% 🟢)1.045s (-20.0% 🟢)0.418s581.00x
🐘 PostgresNitro0.662s (-31.7% 🟢)1.029s (-17.5% 🟢)0.000s (-17.2% 🟢)1.049s (-16.6% 🟢)0.387s581.05x
💻 LocalExpress1.365s (+11.5% 🔺)2.015s (~)0.000s (+40.0% 🔺)2.018s (~)0.652s302.18x
💻 LocalNitro1.561s (+27.6% 🔺)2.016s (~)0.000s (+364.3% 🔺)2.197s (+8.7% 🔺)0.636s282.49x
fan-out fan-in 10 streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.228s (-30.7% 🟢)1.869s (-14.2% 🟢)0.000s (NaN%)1.900s (-13.6% 🟢)0.673s321.00x
🐘 PostgresNitro1.325s (-26.1% 🟢)1.997s (-6.7% 🟢)0.000s (+86.7% 🔺)2.019s (-7.2% 🟢)0.694s301.08x
💻 LocalExpress3.158s (-8.9% 🟢)4.028s (~)0.001s (-33.3% 🟢)4.030s (~)0.873s152.57x
💻 LocalNitro3.187s (-5.9% 🟢)4.029s (~)0.000s (-75.0% 🟢)4.031s (~)0.844s152.60x

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalExpress12/21
🐘 PostgresExpress17/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres16/21
Nitro🐘 Postgres17/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.

@github-actions

github-actionsBot commented May 18, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
❌ ▲ Vercel Production119642191419
✅ 💻 Local Development158702191806
✅ 📦 Local Production145802191677
❌ 🐘 Local Postgres158522191806
✅ 🪟 Windows12900129
✅ 📋 Other7270176903
Total6682610527740

❌ Failed Tests

▲ Vercel Production (4 failed)

astro (1 failed):

  • AbortController abortFromStepWorkflow: step abort cancels an in-flight sibling step

hono (2 failed):

  • outputStreamWorkflow no startIndex (reads all chunks)
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KRYMPWTNKF0CE4BP27X7R946 | 🔍 observability

nextjs-webpack (1 failed):

🐘 Local Postgres (2 failed)

nextjs-webpack-stable-lazy-discovery-disabled (1 failed):

  • DurableAgent e2e core basic text response

nextjs-webpack-stable-lazy-discovery-enabled (1 failed):

  • addTenWorkflow | wrun_01KRYMBT8QHFK9EZ9FDY03D9G0

Details by Category

❌ ▲ Vercel Production
AppPassedFailedSkipped
❌ astro102126
✅ example103026
✅ express103026
✅ fastify103026
❌ hono101226
✅ nextjs-turbopack12702
❌ nextjs-webpack12612
✅ nitro103026
✅ nuxt103026
✅ sveltekit12207
✅ vite103026
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable104025
✅ express-stable104025
✅ fastify-stable104025
✅ hono-stable104025
✅ nextjs-turbopack-canary110019
✅ nextjs-turbopack-stable-lazy-discovery-disabled12900
✅ nextjs-turbopack-stable-lazy-discovery-enabled12900
✅ nextjs-webpack-canary110019
✅ nextjs-webpack-stable-lazy-discovery-disabled12900
✅ nextjs-webpack-stable-lazy-discovery-enabled12900
✅ nitro-stable104025
✅ nuxt-stable104025
✅ sveltekit-stable12306
✅ vite-stable104025
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable104025
✅ express-stable104025
✅ fastify-stable104025
✅ hono-stable104025
✅ nextjs-turbopack-canary110019
✅ nextjs-turbopack-stable-lazy-discovery-disabled12900
✅ nextjs-webpack-canary110019
✅ nextjs-webpack-stable-lazy-discovery-disabled12900
✅ nextjs-webpack-stable-lazy-discovery-enabled12900
✅ nitro-stable104025
✅ nuxt-stable104025
✅ sveltekit-stable12306
✅ vite-stable104025
❌ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable104025
✅ express-stable104025
✅ fastify-stable104025
✅ hono-stable104025
✅ nextjs-turbopack-canary110019
✅ nextjs-turbopack-stable-lazy-discovery-disabled12900
✅ nextjs-turbopack-stable-lazy-discovery-enabled12900
✅ nextjs-webpack-canary110019
❌ nextjs-webpack-stable-lazy-discovery-disabled12810
❌ nextjs-webpack-stable-lazy-discovery-enabled12810
✅ nitro-stable104025
✅ nuxt-stable104025
✅ sveltekit-stable12306
✅ vite-stable104025
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack12900
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable104025
✅ e2e-local-dev-tanstack-start-104025
✅ e2e-local-postgres-nest-stable104025
✅ e2e-local-postgres-tanstack-start-104025
✅ e2e-local-prod-nest-stable104025
✅ e2e-local-prod-tanstack-start-104025
✅ e2e-vercel-prod-tanstack-start103026

📋 View full workflow run


Some E2E test jobs failed:

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

Check the workflow run for details.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a new "Versioning" Foundations page (v4 and v5) explaining default run pinning to deployments, recovery via cancel + rerun, opting into newer code with deploymentId: "latest", and carrying serializable state/streams across child-run continuations. Existing references to deploymentId: "latest" and versioning behavior are linked back to the new page. Cookbook pages also pick up callouts about long-lived / multi-turn patterns and, on v5 only, are updated to reflect that start() can now be called directly inside "use workflow" functions (via #1491), while v4 retains the step-wrapped pattern.

Changes:

  • New foundations/versioning.mdx for both v4 and v5, plus meta.json + index.mdx + linkbacks from vercel-world, start.mdx, and code-transform.mdx.
  • v5 cookbook + migration guides updated to drop "use step" wrappers around start() in favor of calling start() directly from the workflow function; v4 keeps the step-wrapped pattern.
  • Added "Versioning" callouts to scheduling, durable-agent, ai-sdk, chat-sdk, and sandbox cookbooks; fixed a few small wording/grammar issues in code-transform.mdx.

Reviewed changes

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

Show a summary per file
FileDescription
docs/content/docs/v5/foundations/versioning.mdxNew Foundations page explaining run pinning, recovery, and explicit upgrade boundaries.
docs/content/docs/v4/foundations/versioning.mdxv4 counterpart; uses step-wrapped continueDigest/continueExportOnLatest helpers.
docs/content/docs/v{4,5}/foundations/{meta.json,index.mdx}Surface the new Versioning page in nav and the foundations index.
docs/content/docs/v{4,5}/deploying/world/vercel-world.mdxLink the deployment-pinning section to the new Versioning page.
docs/content/docs/v{4,5}/how-it-works/code-transform.mdxLink "atomic versioning" reference; fix "function assume" / "from being upgraded" wording.
docs/content/docs/v{4,5}/api-reference/workflow-api/start.mdxSoften "Vercel-specific" to "Vercelism", mention possible version rename, link Versioning. v5 also notes native workflow-context start().
docs/content/docs/v5/foundations/starting-workflows.mdxNote v5 can call start() from workflows; link Composition + Versioning.
docs/content/docs/v5/cookbook/common-patterns/workflow-composition.mdxReplace step-wrapped child spawn with direct start() call.
docs/content/docs/v5/cookbook/advanced/child-workflows.mdxInline batched start() calls; rename spawnReportChunkstartReportChunk; update tips.
docs/content/docs/v{4,5}/cookbook/common-patterns/scheduling.mdxCallout linking to Versioning for long-lived schedules.
docs/content/docs/v{4,5}/cookbook/agent-patterns/durable-agent.mdxCallout linking to Versioning for multi-turn agents.
docs/content/docs/v{4,5}/cookbook/integrations/{ai-sdk,chat-sdk,sandbox}.mdxCallouts linking to Versioning for long-lived sessions.
docs/content/docs/v4/cookbook/common-patterns/workflow-composition.mdxUpdate deploymentId: "latest" callout wording + link to Versioning.
docs/content/docs/v4/cookbook/advanced/child-workflows.mdxLink Versioning from the deploymentId: "latest" tip.
docs/content/docs/v4/changelog/eager-processing.mdxReword to "step-wrapped start() helper" to match v4 phrasing.
docs/content/docs/v5/migration-guides/{migrating-from-trigger-dev,migrating-from-temporal,migrating-from-inngest,migrating-from-aws-step-functions}.mdxUpdate to v5 native workflow-context start(); only collect step retains "use step".

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

@TooTallNateTooTallNate left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Comment-only review

The new versioning foundations page is a useful addition — the four sections (default pinning → recovery → self-upgrade via start({ deploymentId: "latest" }) → carrying serializable context forward) cover the model clearly, and the v4-vs-v5 differentiation (step-wrapped start() vs direct start() from workflow context, gated on whether PR #1491 has landed on the target branch) is correctly handled. The cross-links from cookbook patterns to the new foundations page tie everything together nicely.

Three observations — see inline.

Inline comments

  1. Wording: this PR introduces "Vercelism" as a new term and uses it 6 times across the diff, including replacing existing "Vercel-specific feature" wording in two <Callout>s. "Vercelism" reads as informal slang and isn't part of the established docs vocabulary. The existing tone uses "Vercel-specific", "Vercel deployments", "Vercel World", "non-Vercel" — all precise. Suggested restoring the prior phrasing. This is the only thing I'd consider blocking.
  2. Broken link in v4: versioning.mdx references /docs/foundations/cancellation in its related frontmatter, but that page is v5-only. Easy fix.
  3. Missing changeset: convention for docs-only PRs is an empty ---\n--- file.

A few small things I noticed

  • The pre-emptively check for a conflict with getHookByToken() example (line 96 of versioning.mdx) — nice that you noted the race window in a later doc (#2011 callout), but this page doesn't have that warning. Worth a cross-link or <Callout type="warn"> here too, since the recovery pattern uses both start() and deploymentId: "latest" together.
  • The _idempotency / using syntax is great. Worth confirming the docs site's syntax highlighter renders it — I noticed #1988 recently fixed a homepage link lint regression, and the using syntax is TypeScript 5.2+ specific.
  • dailyDigest example (line 137-152): the state parameter is DigestState but the workflow doesn't actually use state.userId after the first sendDigest call — pattern is fine, just noting if you wanted to make the example illustrate state evolution more vividly, having sendDigest read state.lastSentAt (e.g. to avoid sending duplicates) would make the carry-forward intent clearer.

Overall the page reads well — once the Vercelism wording is restored and the v4 link is fixed, this should be good to go.

Comment threaddocs/content/docs/v5/api-reference/workflow-api/start.mdx Outdated
Comment threaddocs/content/docs/v4/foundations/versioning.mdx
Comment threaddocs/content/docs/v5/foundations/versioning.mdx

@TooTallNateTooTallNate left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

All three review comments addressed in 7eff96c — Vercelism wording reverted, v4 broken cancellation link fixed, empty changeset added. LGTM, approving.

@github-actions

Copy link
Copy Markdown
Contributor

Backport PR opened against stable: #2014. Merge conflicts were resolved by AI — please review carefully.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

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

Add workflow versioning docs - #2010

Merged
pranaygp merged 10 commits into
mainfrom
pranaygp/codex/docs-versioning-page
May 18, 2026
Merged

Add workflow versioning docs#2010
pranaygp merged 10 commits into
mainfrom
pranaygp/codex/docs-versioning-page

Conversation

@pranaygp

@pranaygppranaygp commented May 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a new Foundations page explaining Workflow SDK versioning semantics for both v5 and v4 docs.

The page covers:

  • default run pinning to the deployment that started the run
  • canceling and rerunning affected in-flight runs on the latest deployment
  • explicit self-upgrade patterns using deploymentId: "latest"
  • carrying serializable context such as streams and abort signals across child runs

This also links existing versioning and deploymentId: "latest" mentions back to the new Foundations page, and calls out that deploymentId is currently a Vercelism that may become a more generic version concept in the World spec later.

Follow-up cookbook pass added targeted callouts for long-lived or multi-turn patterns:

  • scheduled workflows
  • DurableAgent
  • AI SDK multi-turn sessions
  • Chat SDK sessions
  • Sandbox sessions

The docs now also distinguish v5 from v4 for child-run starts. Native start() from workflow context was added by e295bae41 / #1491, which is on main but not stable, so v5 examples encourage direct workflow-context start() and v4 keeps the step-wrapped pattern.

Validation

  • git diff --check
  • Parsed the updated v4/v5 Foundations meta.json files as JSON
  • Verified v4/v5 copies of the touched cookbook pages match before the v5-only native-start pass
  • Searched docs/content for stale v5 step-wrapped start() guidance and v4 direct-start guidance
  • Confirmed origin/stable lacks the 'use step' directive in packages/core/src/runtime/start.ts, while main has it via e295bae41 / feat: allow start() to be called directly inside workflow functions #1491

Full docs lint/typecheck were not run because this checkout does not have node_modules installed, so biome, vitest, and changeset are unavailable locally.

@vercel

vercelBot commented May 18, 2026

Copy link
Copy Markdown
Contributor

@changeset-bot

changeset-botBot commented May 18, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7eff96c

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

This PR includes changesets to release 0 packages

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

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

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

@github-actions

github-actionsBot commented May 18, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

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

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Nitro0.031s (-28.3% 🟢)1.005s (~)0.974s101.00x
💻 LocalExpress0.036s (-19.6% 🟢)1.005s (~)0.970s101.15x
🐘 PostgresExpress0.045s (-21.9% 🟢)1.011s (~)0.966s101.47x
🐘 PostgresNitro0.046s (-51.3% 🟢)1.013s (-2.9%)0.967s101.50x
workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.070s (-4.9%)2.006s (~)0.936s101.00x
💻 LocalNitro1.071s (-5.3% 🟢)2.006s (~)0.935s101.00x
🐘 PostgresExpress1.079s (-5.9% 🟢)2.009s (~)0.930s101.01x
🐘 PostgresNitro1.081s (-5.2% 🟢)2.010s (~)0.929s101.01x
workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro10.396s (-4.4%)11.018s (~)0.622s31.00x
🐘 PostgresExpress10.402s (-5.1% 🟢)11.016s (~)0.614s31.00x
💻 LocalExpress10.411s (-4.7%)11.023s (~)0.612s31.00x
💻 LocalNitro10.412s (-4.9%)11.022s (~)0.610s31.00x
workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express13.432s (-10.3% 🟢)14.027s (-6.7% 🟢)0.595s51.00x
🐘 PostgresExpress13.435s (-7.9% 🟢)14.017s (-6.7% 🟢)0.581s51.00x
🐘 PostgresNitro13.484s (-7.6% 🟢)14.017s (-6.7% 🟢)0.533s51.00x
💻 LocalNitro13.489s (-10.4% 🟢)14.027s (-12.5% 🟢)0.538s51.00x
workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Nitro11.875s (-29.2% 🟢)12.022s (-29.4% 🟢)0.147s81.00x
💻 LocalExpress11.890s (-28.4% 🟢)12.022s (-29.4% 🟢)0.132s81.00x
🐘 PostgresExpress11.941s (-14.7% 🟢)12.391s (-15.1% 🟢)0.450s81.01x
🐘 PostgresNitro11.944s (-14.5% 🟢)12.266s (-14.3% 🟢)0.321s81.01x
Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.136s (-9.8% 🟢)2.007s (~)0.870s151.00x
🐘 PostgresNitro1.137s (-10.8% 🟢)2.007s (~)0.870s151.00x
💻 LocalNitro1.172s (-28.2% 🟢)2.006s (-3.3%)0.834s151.03x
💻 LocalExpress1.183s (-20.6% 🟢)2.006s (~)0.823s151.04x
Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.192s (-49.3% 🟢)2.007s (-33.3% 🟢)0.815s151.00x
🐘 PostgresExpress1.224s (-48.2% 🟢)2.007s (-33.3% 🟢)0.783s151.03x
💻 LocalExpress1.703s (-42.3% 🟢)2.005s (-41.9% 🟢)0.303s151.43x
💻 LocalNitro1.704s (-45.8% 🟢)2.005s (-48.4% 🟢)0.302s151.43x
Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.305s (-62.5% 🟢)2.008s (-49.9% 🟢)0.702s151.00x
🐘 PostgresExpress1.324s (-62.0% 🟢)2.008s (-49.9% 🟢)0.684s151.01x
💻 LocalExpress4.638s (-44.4% 🟢)5.179s (-42.6% 🟢)0.541s63.55x
💻 LocalNitro4.910s (-41.2% 🟢)5.511s (-38.9% 🟢)0.601s63.76x
Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.155s (-8.1% 🟢)2.009s (~)0.854s151.00x
🐘 PostgresNitro1.163s (-7.5% 🟢)2.010s (~)0.847s151.01x
💻 LocalExpress1.386s (-26.8% 🟢)2.006s (-15.2% 🟢)0.620s151.20x
💻 LocalNitro1.388s (-25.6% 🟢)2.006s (-14.3% 🟢)0.618s151.20x
Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.199s (-48.8% 🟢)2.008s (-33.3% 🟢)0.810s151.00x
🐘 PostgresNitro1.199s (-48.7% 🟢)2.007s (-33.3% 🟢)0.808s151.00x
💻 LocalExpress1.828s (-41.6% 🟢)2.222s (-40.9% 🟢)0.394s141.53x
💻 LocalNitro1.935s (-36.9% 🟢)2.316s (-40.4% 🟢)0.381s131.61x
Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.305s (-62.7% 🟢)2.008s (-49.9% 🟢)0.702s151.00x
🐘 PostgresNitro1.309s (-62.4% 🟢)2.009s (-49.9% 🟢)0.700s151.00x
💻 LocalExpress5.446s (-38.1% 🟢)5.849s (-36.9% 🟢)0.403s64.17x
💻 LocalNitro5.557s (-39.2% 🟢)6.179s (-38.4% 🟢)0.622s64.26x
workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.418s (-50.1% 🟢)1.006s (-1.6%)0.588s601.00x
🐘 PostgresNitro0.459s (-44.0% 🟢)1.006s (~)0.547s601.10x
💻 LocalNitro0.468s (-52.2% 🟢)1.004s (-8.2% 🟢)0.535s601.12x
💻 LocalExpress0.469s (-52.4% 🟢)1.004s (-6.7% 🟢)0.535s601.12x
workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.047s (-47.0% 🟢)1.705s (-24.5% 🟢)0.659s531.00x
🐘 PostgresNitro1.066s (-44.7% 🟢)1.576s (-25.0% 🟢)0.510s581.02x
💻 LocalNitro1.185s (-61.0% 🟢)2.006s (-46.6% 🟢)0.821s451.13x
💻 LocalExpress1.191s (-60.5% 🟢)2.005s (-44.1% 🟢)0.815s451.14x
workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express2.030s (-49.1% 🟢)2.427s (-44.4% 🟢)0.397s501.00x
🐘 PostgresNitro2.128s (-48.2% 🟢)2.660s (-42.2% 🟢)0.532s461.05x
💻 LocalNitro2.704s (-70.9% 🟢)3.032s (-69.7% 🟢)0.328s401.33x
💻 LocalExpress2.719s (-70.5% 🟢)3.057s (-69.5% 🟢)0.338s401.34x
workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.163s (-42.4% 🟢)1.005s (~)0.843s601.00x
🐘 PostgresNitro0.178s (-37.0% 🟢)1.006s (~)0.827s601.10x
💻 LocalExpress0.455s (-18.8% 🟢)1.004s (~)0.550s602.80x
💻 LocalNitro0.469s (-22.4% 🟢)1.004s (-1.7%)0.535s602.89x
workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.286s (-43.9% 🟢)1.006s (~)0.720s901.00x
🐘 PostgresNitro0.295s (-40.5% 🟢)1.006s (~)0.711s901.03x
💻 LocalNitro2.205s (-13.1% 🟢)2.944s (-2.2%)0.738s317.71x
💻 LocalExpress2.226s (-11.4% 🟢)2.943s (-2.2%)0.717s317.78x
workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.582s (-28.9% 🟢)1.007s (-1.0%)0.425s1201.00x
🐘 PostgresNitro0.634s (-19.7% 🟢)1.006s (~)0.372s1201.09x
💻 LocalNitro10.021s (-10.5% 🟢)10.611s (-9.0% 🟢)0.590s1217.21x
💻 LocalExpress10.042s (-10.3% 🟢)10.694s (-10.4% 🟢)0.652s1217.25x
Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.132s (+468.5% 🔺)2.005s (+99.6% 🔺)0.011s (-13.2% 🟢)2.018s (+98.2% 🔺)0.886s101.00x
💻 LocalNitro1.133s (+430.4% 🔺)2.005s (+99.6% 🔺)0.011s (-15.2% 🟢)2.018s (+98.1% 🔺)0.885s101.00x
🐘 PostgresNitro1.135s (+453.6% 🔺)2.001s (+100.2% 🔺)0.001s (-20.0% 🟢)2.010s (+98.7% 🔺)0.875s101.00x
🐘 PostgresExpress1.135s (+453.5% 🔺)1.999s (+100.2% 🔺)0.001s (-25.0% 🟢)2.010s (+98.7% 🔺)0.875s101.00x
stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.492s (+136.8% 🔺)2.002s (+98.9% 🔺)0.003s (-30.4% 🟢)2.023s (+97.8% 🔺)0.531s301.00x
🐘 PostgresNitro1.519s (+143.4% 🔺)2.004s (+99.0% 🔺)0.004s (-2.5%)2.027s (+98.2% 🔺)0.507s301.02x
💻 LocalNitro1.707s (+103.5% 🔺)2.013s (+98.9% 🔺)0.009s (-4.3%)2.203s (+97.4% 🔺)0.496s281.14x
💻 LocalExpress1.923s (+154.0% 🔺)2.011s (+95.4% 🔺)0.009s (-8.2% 🟢)2.422s (+132.9% 🔺)0.499s251.29x
10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.627s (-34.7% 🟢)1.033s (-19.2% 🟢)0.000s (-20.7% 🟢)1.045s (-20.0% 🟢)0.418s581.00x
🐘 PostgresNitro0.662s (-31.7% 🟢)1.029s (-17.5% 🟢)0.000s (-17.2% 🟢)1.049s (-16.6% 🟢)0.387s581.05x
💻 LocalExpress1.365s (+11.5% 🔺)2.015s (~)0.000s (+40.0% 🔺)2.018s (~)0.652s302.18x
💻 LocalNitro1.561s (+27.6% 🔺)2.016s (~)0.000s (+364.3% 🔺)2.197s (+8.7% 🔺)0.636s282.49x
fan-out fan-in 10 streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.228s (-30.7% 🟢)1.869s (-14.2% 🟢)0.000s (NaN%)1.900s (-13.6% 🟢)0.673s321.00x
🐘 PostgresNitro1.325s (-26.1% 🟢)1.997s (-6.7% 🟢)0.000s (+86.7% 🔺)2.019s (-7.2% 🟢)0.694s301.08x
💻 LocalExpress3.158s (-8.9% 🟢)4.028s (~)0.001s (-33.3% 🟢)4.030s (~)0.873s152.57x
💻 LocalNitro3.187s (-5.9% 🟢)4.029s (~)0.000s (-75.0% 🟢)4.031s (~)0.844s152.60x

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalExpress12/21
🐘 PostgresExpress17/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres16/21
Nitro🐘 Postgres17/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.

@github-actions

github-actionsBot commented May 18, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
❌ ▲ Vercel Production119642191419
✅ 💻 Local Development158702191806
✅ 📦 Local Production145802191677
❌ 🐘 Local Postgres158522191806
✅ 🪟 Windows12900129
✅ 📋 Other7270176903
Total6682610527740

❌ Failed Tests

▲ Vercel Production (4 failed)

astro (1 failed):

  • AbortController abortFromStepWorkflow: step abort cancels an in-flight sibling step

hono (2 failed):

  • outputStreamWorkflow no startIndex (reads all chunks)
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KRYMPWTNKF0CE4BP27X7R946 | 🔍 observability

nextjs-webpack (1 failed):

🐘 Local Postgres (2 failed)

nextjs-webpack-stable-lazy-discovery-disabled (1 failed):

  • DurableAgent e2e core basic text response

nextjs-webpack-stable-lazy-discovery-enabled (1 failed):

  • addTenWorkflow | wrun_01KRYMBT8QHFK9EZ9FDY03D9G0

Details by Category

❌ ▲ Vercel Production
AppPassedFailedSkipped
❌ astro102126
✅ example103026
✅ express103026
✅ fastify103026
❌ hono101226
✅ nextjs-turbopack12702
❌ nextjs-webpack12612
✅ nitro103026
✅ nuxt103026
✅ sveltekit12207
✅ vite103026
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable104025
✅ express-stable104025
✅ fastify-stable104025
✅ hono-stable104025
✅ nextjs-turbopack-canary110019
✅ nextjs-turbopack-stable-lazy-discovery-disabled12900
✅ nextjs-turbopack-stable-lazy-discovery-enabled12900
✅ nextjs-webpack-canary110019
✅ nextjs-webpack-stable-lazy-discovery-disabled12900
✅ nextjs-webpack-stable-lazy-discovery-enabled12900
✅ nitro-stable104025
✅ nuxt-stable104025
✅ sveltekit-stable12306
✅ vite-stable104025
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable104025
✅ express-stable104025
✅ fastify-stable104025
✅ hono-stable104025
✅ nextjs-turbopack-canary110019
✅ nextjs-turbopack-stable-lazy-discovery-disabled12900
✅ nextjs-webpack-canary110019
✅ nextjs-webpack-stable-lazy-discovery-disabled12900
✅ nextjs-webpack-stable-lazy-discovery-enabled12900
✅ nitro-stable104025
✅ nuxt-stable104025
✅ sveltekit-stable12306
✅ vite-stable104025
❌ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable104025
✅ express-stable104025
✅ fastify-stable104025
✅ hono-stable104025
✅ nextjs-turbopack-canary110019
✅ nextjs-turbopack-stable-lazy-discovery-disabled12900
✅ nextjs-turbopack-stable-lazy-discovery-enabled12900
✅ nextjs-webpack-canary110019
❌ nextjs-webpack-stable-lazy-discovery-disabled12810
❌ nextjs-webpack-stable-lazy-discovery-enabled12810
✅ nitro-stable104025
✅ nuxt-stable104025
✅ sveltekit-stable12306
✅ vite-stable104025
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack12900
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable104025
✅ e2e-local-dev-tanstack-start-104025
✅ e2e-local-postgres-nest-stable104025
✅ e2e-local-postgres-tanstack-start-104025
✅ e2e-local-prod-nest-stable104025
✅ e2e-local-prod-tanstack-start-104025
✅ e2e-vercel-prod-tanstack-start103026

📋 View full workflow run


Some E2E test jobs failed:

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

Check the workflow run for details.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a new "Versioning" Foundations page (v4 and v5) explaining default run pinning to deployments, recovery via cancel + rerun, opting into newer code with deploymentId: "latest", and carrying serializable state/streams across child-run continuations. Existing references to deploymentId: "latest" and versioning behavior are linked back to the new page. Cookbook pages also pick up callouts about long-lived / multi-turn patterns and, on v5 only, are updated to reflect that start() can now be called directly inside "use workflow" functions (via #1491), while v4 retains the step-wrapped pattern.

Changes:

  • New foundations/versioning.mdx for both v4 and v5, plus meta.json + index.mdx + linkbacks from vercel-world, start.mdx, and code-transform.mdx.
  • v5 cookbook + migration guides updated to drop "use step" wrappers around start() in favor of calling start() directly from the workflow function; v4 keeps the step-wrapped pattern.
  • Added "Versioning" callouts to scheduling, durable-agent, ai-sdk, chat-sdk, and sandbox cookbooks; fixed a few small wording/grammar issues in code-transform.mdx.

Reviewed changes

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

Show a summary per file
FileDescription
docs/content/docs/v5/foundations/versioning.mdxNew Foundations page explaining run pinning, recovery, and explicit upgrade boundaries.
docs/content/docs/v4/foundations/versioning.mdxv4 counterpart; uses step-wrapped continueDigest/continueExportOnLatest helpers.
docs/content/docs/v{4,5}/foundations/{meta.json,index.mdx}Surface the new Versioning page in nav and the foundations index.
docs/content/docs/v{4,5}/deploying/world/vercel-world.mdxLink the deployment-pinning section to the new Versioning page.
docs/content/docs/v{4,5}/how-it-works/code-transform.mdxLink "atomic versioning" reference; fix "function assume" / "from being upgraded" wording.
docs/content/docs/v{4,5}/api-reference/workflow-api/start.mdxSoften "Vercel-specific" to "Vercelism", mention possible version rename, link Versioning. v5 also notes native workflow-context start().
docs/content/docs/v5/foundations/starting-workflows.mdxNote v5 can call start() from workflows; link Composition + Versioning.
docs/content/docs/v5/cookbook/common-patterns/workflow-composition.mdxReplace step-wrapped child spawn with direct start() call.
docs/content/docs/v5/cookbook/advanced/child-workflows.mdxInline batched start() calls; rename spawnReportChunkstartReportChunk; update tips.
docs/content/docs/v{4,5}/cookbook/common-patterns/scheduling.mdxCallout linking to Versioning for long-lived schedules.
docs/content/docs/v{4,5}/cookbook/agent-patterns/durable-agent.mdxCallout linking to Versioning for multi-turn agents.
docs/content/docs/v{4,5}/cookbook/integrations/{ai-sdk,chat-sdk,sandbox}.mdxCallouts linking to Versioning for long-lived sessions.
docs/content/docs/v4/cookbook/common-patterns/workflow-composition.mdxUpdate deploymentId: "latest" callout wording + link to Versioning.
docs/content/docs/v4/cookbook/advanced/child-workflows.mdxLink Versioning from the deploymentId: "latest" tip.
docs/content/docs/v4/changelog/eager-processing.mdxReword to "step-wrapped start() helper" to match v4 phrasing.
docs/content/docs/v5/migration-guides/{migrating-from-trigger-dev,migrating-from-temporal,migrating-from-inngest,migrating-from-aws-step-functions}.mdxUpdate to v5 native workflow-context start(); only collect step retains "use step".

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

@TooTallNateTooTallNate left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Comment-only review

The new versioning foundations page is a useful addition — the four sections (default pinning → recovery → self-upgrade via start({ deploymentId: "latest" }) → carrying serializable context forward) cover the model clearly, and the v4-vs-v5 differentiation (step-wrapped start() vs direct start() from workflow context, gated on whether PR #1491 has landed on the target branch) is correctly handled. The cross-links from cookbook patterns to the new foundations page tie everything together nicely.

Three observations — see inline.

Inline comments

  1. Wording: this PR introduces "Vercelism" as a new term and uses it 6 times across the diff, including replacing existing "Vercel-specific feature" wording in two <Callout>s. "Vercelism" reads as informal slang and isn't part of the established docs vocabulary. The existing tone uses "Vercel-specific", "Vercel deployments", "Vercel World", "non-Vercel" — all precise. Suggested restoring the prior phrasing. This is the only thing I'd consider blocking.
  2. Broken link in v4: versioning.mdx references /docs/foundations/cancellation in its related frontmatter, but that page is v5-only. Easy fix.
  3. Missing changeset: convention for docs-only PRs is an empty ---\n--- file.

A few small things I noticed

  • The pre-emptively check for a conflict with getHookByToken() example (line 96 of versioning.mdx) — nice that you noted the race window in a later doc (#2011 callout), but this page doesn't have that warning. Worth a cross-link or <Callout type="warn"> here too, since the recovery pattern uses both start() and deploymentId: "latest" together.
  • The _idempotency / using syntax is great. Worth confirming the docs site's syntax highlighter renders it — I noticed #1988 recently fixed a homepage link lint regression, and the using syntax is TypeScript 5.2+ specific.
  • dailyDigest example (line 137-152): the state parameter is DigestState but the workflow doesn't actually use state.userId after the first sendDigest call — pattern is fine, just noting if you wanted to make the example illustrate state evolution more vividly, having sendDigest read state.lastSentAt (e.g. to avoid sending duplicates) would make the carry-forward intent clearer.

Overall the page reads well — once the Vercelism wording is restored and the v4 link is fixed, this should be good to go.

Comment threaddocs/content/docs/v5/api-reference/workflow-api/start.mdx Outdated
Comment threaddocs/content/docs/v4/foundations/versioning.mdx
Comment threaddocs/content/docs/v5/foundations/versioning.mdx

@TooTallNateTooTallNate left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

All three review comments addressed in 7eff96c — Vercelism wording reverted, v4 broken cancellation link fixed, empty changeset added. LGTM, approving.

@github-actions

Copy link
Copy Markdown
Contributor

Backport PR opened against stable: #2014. Merge conflicts were resolved by AI — please review carefully.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

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

Add workflow versioning docs - #2010

Merged
pranaygp merged 10 commits into
mainfrom
pranaygp/codex/docs-versioning-page
May 18, 2026
Merged

Add workflow versioning docs#2010
pranaygp merged 10 commits into
mainfrom
pranaygp/codex/docs-versioning-page

Conversation

@pranaygp

@pranaygppranaygp commented May 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a new Foundations page explaining Workflow SDK versioning semantics for both v5 and v4 docs.

The page covers:

  • default run pinning to the deployment that started the run
  • canceling and rerunning affected in-flight runs on the latest deployment
  • explicit self-upgrade patterns using deploymentId: "latest"
  • carrying serializable context such as streams and abort signals across child runs

This also links existing versioning and deploymentId: "latest" mentions back to the new Foundations page, and calls out that deploymentId is currently a Vercelism that may become a more generic version concept in the World spec later.

Follow-up cookbook pass added targeted callouts for long-lived or multi-turn patterns:

  • scheduled workflows
  • DurableAgent
  • AI SDK multi-turn sessions
  • Chat SDK sessions
  • Sandbox sessions

The docs now also distinguish v5 from v4 for child-run starts. Native start() from workflow context was added by e295bae41 / #1491, which is on main but not stable, so v5 examples encourage direct workflow-context start() and v4 keeps the step-wrapped pattern.

Validation

  • git diff --check
  • Parsed the updated v4/v5 Foundations meta.json files as JSON
  • Verified v4/v5 copies of the touched cookbook pages match before the v5-only native-start pass
  • Searched docs/content for stale v5 step-wrapped start() guidance and v4 direct-start guidance
  • Confirmed origin/stable lacks the 'use step' directive in packages/core/src/runtime/start.ts, while main has it via e295bae41 / feat: allow start() to be called directly inside workflow functions #1491

Full docs lint/typecheck were not run because this checkout does not have node_modules installed, so biome, vitest, and changeset are unavailable locally.

@vercel

vercelBot commented May 18, 2026

Copy link
Copy Markdown
Contributor

@changeset-bot

changeset-botBot commented May 18, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7eff96c

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

This PR includes changesets to release 0 packages

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

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

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

@github-actions

github-actionsBot commented May 18, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

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

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Nitro0.031s (-28.3% 🟢)1.005s (~)0.974s101.00x
💻 LocalExpress0.036s (-19.6% 🟢)1.005s (~)0.970s101.15x
🐘 PostgresExpress0.045s (-21.9% 🟢)1.011s (~)0.966s101.47x
🐘 PostgresNitro0.046s (-51.3% 🟢)1.013s (-2.9%)0.967s101.50x
workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.070s (-4.9%)2.006s (~)0.936s101.00x
💻 LocalNitro1.071s (-5.3% 🟢)2.006s (~)0.935s101.00x
🐘 PostgresExpress1.079s (-5.9% 🟢)2.009s (~)0.930s101.01x
🐘 PostgresNitro1.081s (-5.2% 🟢)2.010s (~)0.929s101.01x
workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro10.396s (-4.4%)11.018s (~)0.622s31.00x
🐘 PostgresExpress10.402s (-5.1% 🟢)11.016s (~)0.614s31.00x
💻 LocalExpress10.411s (-4.7%)11.023s (~)0.612s31.00x
💻 LocalNitro10.412s (-4.9%)11.022s (~)0.610s31.00x
workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express13.432s (-10.3% 🟢)14.027s (-6.7% 🟢)0.595s51.00x
🐘 PostgresExpress13.435s (-7.9% 🟢)14.017s (-6.7% 🟢)0.581s51.00x
🐘 PostgresNitro13.484s (-7.6% 🟢)14.017s (-6.7% 🟢)0.533s51.00x
💻 LocalNitro13.489s (-10.4% 🟢)14.027s (-12.5% 🟢)0.538s51.00x
workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Nitro11.875s (-29.2% 🟢)12.022s (-29.4% 🟢)0.147s81.00x
💻 LocalExpress11.890s (-28.4% 🟢)12.022s (-29.4% 🟢)0.132s81.00x
🐘 PostgresExpress11.941s (-14.7% 🟢)12.391s (-15.1% 🟢)0.450s81.01x
🐘 PostgresNitro11.944s (-14.5% 🟢)12.266s (-14.3% 🟢)0.321s81.01x
Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.136s (-9.8% 🟢)2.007s (~)0.870s151.00x
🐘 PostgresNitro1.137s (-10.8% 🟢)2.007s (~)0.870s151.00x
💻 LocalNitro1.172s (-28.2% 🟢)2.006s (-3.3%)0.834s151.03x
💻 LocalExpress1.183s (-20.6% 🟢)2.006s (~)0.823s151.04x
Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.192s (-49.3% 🟢)2.007s (-33.3% 🟢)0.815s151.00x
🐘 PostgresExpress1.224s (-48.2% 🟢)2.007s (-33.3% 🟢)0.783s151.03x
💻 LocalExpress1.703s (-42.3% 🟢)2.005s (-41.9% 🟢)0.303s151.43x
💻 LocalNitro1.704s (-45.8% 🟢)2.005s (-48.4% 🟢)0.302s151.43x
Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.305s (-62.5% 🟢)2.008s (-49.9% 🟢)0.702s151.00x
🐘 PostgresExpress1.324s (-62.0% 🟢)2.008s (-49.9% 🟢)0.684s151.01x
💻 LocalExpress4.638s (-44.4% 🟢)5.179s (-42.6% 🟢)0.541s63.55x
💻 LocalNitro4.910s (-41.2% 🟢)5.511s (-38.9% 🟢)0.601s63.76x
Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.155s (-8.1% 🟢)2.009s (~)0.854s151.00x
🐘 PostgresNitro1.163s (-7.5% 🟢)2.010s (~)0.847s151.01x
💻 LocalExpress1.386s (-26.8% 🟢)2.006s (-15.2% 🟢)0.620s151.20x
💻 LocalNitro1.388s (-25.6% 🟢)2.006s (-14.3% 🟢)0.618s151.20x
Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.199s (-48.8% 🟢)2.008s (-33.3% 🟢)0.810s151.00x
🐘 PostgresNitro1.199s (-48.7% 🟢)2.007s (-33.3% 🟢)0.808s151.00x
💻 LocalExpress1.828s (-41.6% 🟢)2.222s (-40.9% 🟢)0.394s141.53x
💻 LocalNitro1.935s (-36.9% 🟢)2.316s (-40.4% 🟢)0.381s131.61x
Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.305s (-62.7% 🟢)2.008s (-49.9% 🟢)0.702s151.00x
🐘 PostgresNitro1.309s (-62.4% 🟢)2.009s (-49.9% 🟢)0.700s151.00x
💻 LocalExpress5.446s (-38.1% 🟢)5.849s (-36.9% 🟢)0.403s64.17x
💻 LocalNitro5.557s (-39.2% 🟢)6.179s (-38.4% 🟢)0.622s64.26x
workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.418s (-50.1% 🟢)1.006s (-1.6%)0.588s601.00x
🐘 PostgresNitro0.459s (-44.0% 🟢)1.006s (~)0.547s601.10x
💻 LocalNitro0.468s (-52.2% 🟢)1.004s (-8.2% 🟢)0.535s601.12x
💻 LocalExpress0.469s (-52.4% 🟢)1.004s (-6.7% 🟢)0.535s601.12x
workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.047s (-47.0% 🟢)1.705s (-24.5% 🟢)0.659s531.00x
🐘 PostgresNitro1.066s (-44.7% 🟢)1.576s (-25.0% 🟢)0.510s581.02x
💻 LocalNitro1.185s (-61.0% 🟢)2.006s (-46.6% 🟢)0.821s451.13x
💻 LocalExpress1.191s (-60.5% 🟢)2.005s (-44.1% 🟢)0.815s451.14x
workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express2.030s (-49.1% 🟢)2.427s (-44.4% 🟢)0.397s501.00x
🐘 PostgresNitro2.128s (-48.2% 🟢)2.660s (-42.2% 🟢)0.532s461.05x
💻 LocalNitro2.704s (-70.9% 🟢)3.032s (-69.7% 🟢)0.328s401.33x
💻 LocalExpress2.719s (-70.5% 🟢)3.057s (-69.5% 🟢)0.338s401.34x
workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.163s (-42.4% 🟢)1.005s (~)0.843s601.00x
🐘 PostgresNitro0.178s (-37.0% 🟢)1.006s (~)0.827s601.10x
💻 LocalExpress0.455s (-18.8% 🟢)1.004s (~)0.550s602.80x
💻 LocalNitro0.469s (-22.4% 🟢)1.004s (-1.7%)0.535s602.89x
workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.286s (-43.9% 🟢)1.006s (~)0.720s901.00x
🐘 PostgresNitro0.295s (-40.5% 🟢)1.006s (~)0.711s901.03x
💻 LocalNitro2.205s (-13.1% 🟢)2.944s (-2.2%)0.738s317.71x
💻 LocalExpress2.226s (-11.4% 🟢)2.943s (-2.2%)0.717s317.78x
workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.582s (-28.9% 🟢)1.007s (-1.0%)0.425s1201.00x
🐘 PostgresNitro0.634s (-19.7% 🟢)1.006s (~)0.372s1201.09x
💻 LocalNitro10.021s (-10.5% 🟢)10.611s (-9.0% 🟢)0.590s1217.21x
💻 LocalExpress10.042s (-10.3% 🟢)10.694s (-10.4% 🟢)0.652s1217.25x
Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.132s (+468.5% 🔺)2.005s (+99.6% 🔺)0.011s (-13.2% 🟢)2.018s (+98.2% 🔺)0.886s101.00x
💻 LocalNitro1.133s (+430.4% 🔺)2.005s (+99.6% 🔺)0.011s (-15.2% 🟢)2.018s (+98.1% 🔺)0.885s101.00x
🐘 PostgresNitro1.135s (+453.6% 🔺)2.001s (+100.2% 🔺)0.001s (-20.0% 🟢)2.010s (+98.7% 🔺)0.875s101.00x
🐘 PostgresExpress1.135s (+453.5% 🔺)1.999s (+100.2% 🔺)0.001s (-25.0% 🟢)2.010s (+98.7% 🔺)0.875s101.00x
stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.492s (+136.8% 🔺)2.002s (+98.9% 🔺)0.003s (-30.4% 🟢)2.023s (+97.8% 🔺)0.531s301.00x
🐘 PostgresNitro1.519s (+143.4% 🔺)2.004s (+99.0% 🔺)0.004s (-2.5%)2.027s (+98.2% 🔺)0.507s301.02x
💻 LocalNitro1.707s (+103.5% 🔺)2.013s (+98.9% 🔺)0.009s (-4.3%)2.203s (+97.4% 🔺)0.496s281.14x
💻 LocalExpress1.923s (+154.0% 🔺)2.011s (+95.4% 🔺)0.009s (-8.2% 🟢)2.422s (+132.9% 🔺)0.499s251.29x
10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.627s (-34.7% 🟢)1.033s (-19.2% 🟢)0.000s (-20.7% 🟢)1.045s (-20.0% 🟢)0.418s581.00x
🐘 PostgresNitro0.662s (-31.7% 🟢)1.029s (-17.5% 🟢)0.000s (-17.2% 🟢)1.049s (-16.6% 🟢)0.387s581.05x
💻 LocalExpress1.365s (+11.5% 🔺)2.015s (~)0.000s (+40.0% 🔺)2.018s (~)0.652s302.18x
💻 LocalNitro1.561s (+27.6% 🔺)2.016s (~)0.000s (+364.3% 🔺)2.197s (+8.7% 🔺)0.636s282.49x
fan-out fan-in 10 streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.228s (-30.7% 🟢)1.869s (-14.2% 🟢)0.000s (NaN%)1.900s (-13.6% 🟢)0.673s321.00x
🐘 PostgresNitro1.325s (-26.1% 🟢)1.997s (-6.7% 🟢)0.000s (+86.7% 🔺)2.019s (-7.2% 🟢)0.694s301.08x
💻 LocalExpress3.158s (-8.9% 🟢)4.028s (~)0.001s (-33.3% 🟢)4.030s (~)0.873s152.57x
💻 LocalNitro3.187s (-5.9% 🟢)4.029s (~)0.000s (-75.0% 🟢)4.031s (~)0.844s152.60x

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalExpress12/21
🐘 PostgresExpress17/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres16/21
Nitro🐘 Postgres17/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.

@github-actions

github-actionsBot commented May 18, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
❌ ▲ Vercel Production119642191419
✅ 💻 Local Development158702191806
✅ 📦 Local Production145802191677
❌ 🐘 Local Postgres158522191806
✅ 🪟 Windows12900129
✅ 📋 Other7270176903
Total6682610527740

❌ Failed Tests

▲ Vercel Production (4 failed)

astro (1 failed):

  • AbortController abortFromStepWorkflow: step abort cancels an in-flight sibling step

hono (2 failed):

  • outputStreamWorkflow no startIndex (reads all chunks)
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KRYMPWTNKF0CE4BP27X7R946 | 🔍 observability

nextjs-webpack (1 failed):

🐘 Local Postgres (2 failed)

nextjs-webpack-stable-lazy-discovery-disabled (1 failed):

  • DurableAgent e2e core basic text response

nextjs-webpack-stable-lazy-discovery-enabled (1 failed):

  • addTenWorkflow | wrun_01KRYMBT8QHFK9EZ9FDY03D9G0

Details by Category

❌ ▲ Vercel Production
AppPassedFailedSkipped
❌ astro102126
✅ example103026
✅ express103026
✅ fastify103026
❌ hono101226
✅ nextjs-turbopack12702
❌ nextjs-webpack12612
✅ nitro103026
✅ nuxt103026
✅ sveltekit12207
✅ vite103026
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable104025
✅ express-stable104025
✅ fastify-stable104025
✅ hono-stable104025
✅ nextjs-turbopack-canary110019
✅ nextjs-turbopack-stable-lazy-discovery-disabled12900
✅ nextjs-turbopack-stable-lazy-discovery-enabled12900
✅ nextjs-webpack-canary110019
✅ nextjs-webpack-stable-lazy-discovery-disabled12900
✅ nextjs-webpack-stable-lazy-discovery-enabled12900
✅ nitro-stable104025
✅ nuxt-stable104025
✅ sveltekit-stable12306
✅ vite-stable104025
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable104025
✅ express-stable104025
✅ fastify-stable104025
✅ hono-stable104025
✅ nextjs-turbopack-canary110019
✅ nextjs-turbopack-stable-lazy-discovery-disabled12900
✅ nextjs-webpack-canary110019
✅ nextjs-webpack-stable-lazy-discovery-disabled12900
✅ nextjs-webpack-stable-lazy-discovery-enabled12900
✅ nitro-stable104025
✅ nuxt-stable104025
✅ sveltekit-stable12306
✅ vite-stable104025
❌ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable104025
✅ express-stable104025
✅ fastify-stable104025
✅ hono-stable104025
✅ nextjs-turbopack-canary110019
✅ nextjs-turbopack-stable-lazy-discovery-disabled12900
✅ nextjs-turbopack-stable-lazy-discovery-enabled12900
✅ nextjs-webpack-canary110019
❌ nextjs-webpack-stable-lazy-discovery-disabled12810
❌ nextjs-webpack-stable-lazy-discovery-enabled12810
✅ nitro-stable104025
✅ nuxt-stable104025
✅ sveltekit-stable12306
✅ vite-stable104025
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack12900
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable104025
✅ e2e-local-dev-tanstack-start-104025
✅ e2e-local-postgres-nest-stable104025
✅ e2e-local-postgres-tanstack-start-104025
✅ e2e-local-prod-nest-stable104025
✅ e2e-local-prod-tanstack-start-104025
✅ e2e-vercel-prod-tanstack-start103026

📋 View full workflow run


Some E2E test jobs failed:

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

Check the workflow run for details.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a new "Versioning" Foundations page (v4 and v5) explaining default run pinning to deployments, recovery via cancel + rerun, opting into newer code with deploymentId: "latest", and carrying serializable state/streams across child-run continuations. Existing references to deploymentId: "latest" and versioning behavior are linked back to the new page. Cookbook pages also pick up callouts about long-lived / multi-turn patterns and, on v5 only, are updated to reflect that start() can now be called directly inside "use workflow" functions (via #1491), while v4 retains the step-wrapped pattern.

Changes:

  • New foundations/versioning.mdx for both v4 and v5, plus meta.json + index.mdx + linkbacks from vercel-world, start.mdx, and code-transform.mdx.
  • v5 cookbook + migration guides updated to drop "use step" wrappers around start() in favor of calling start() directly from the workflow function; v4 keeps the step-wrapped pattern.
  • Added "Versioning" callouts to scheduling, durable-agent, ai-sdk, chat-sdk, and sandbox cookbooks; fixed a few small wording/grammar issues in code-transform.mdx.

Reviewed changes

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

Show a summary per file
FileDescription
docs/content/docs/v5/foundations/versioning.mdxNew Foundations page explaining run pinning, recovery, and explicit upgrade boundaries.
docs/content/docs/v4/foundations/versioning.mdxv4 counterpart; uses step-wrapped continueDigest/continueExportOnLatest helpers.
docs/content/docs/v{4,5}/foundations/{meta.json,index.mdx}Surface the new Versioning page in nav and the foundations index.
docs/content/docs/v{4,5}/deploying/world/vercel-world.mdxLink the deployment-pinning section to the new Versioning page.
docs/content/docs/v{4,5}/how-it-works/code-transform.mdxLink "atomic versioning" reference; fix "function assume" / "from being upgraded" wording.
docs/content/docs/v{4,5}/api-reference/workflow-api/start.mdxSoften "Vercel-specific" to "Vercelism", mention possible version rename, link Versioning. v5 also notes native workflow-context start().
docs/content/docs/v5/foundations/starting-workflows.mdxNote v5 can call start() from workflows; link Composition + Versioning.
docs/content/docs/v5/cookbook/common-patterns/workflow-composition.mdxReplace step-wrapped child spawn with direct start() call.
docs/content/docs/v5/cookbook/advanced/child-workflows.mdxInline batched start() calls; rename spawnReportChunkstartReportChunk; update tips.
docs/content/docs/v{4,5}/cookbook/common-patterns/scheduling.mdxCallout linking to Versioning for long-lived schedules.
docs/content/docs/v{4,5}/cookbook/agent-patterns/durable-agent.mdxCallout linking to Versioning for multi-turn agents.
docs/content/docs/v{4,5}/cookbook/integrations/{ai-sdk,chat-sdk,sandbox}.mdxCallouts linking to Versioning for long-lived sessions.
docs/content/docs/v4/cookbook/common-patterns/workflow-composition.mdxUpdate deploymentId: "latest" callout wording + link to Versioning.
docs/content/docs/v4/cookbook/advanced/child-workflows.mdxLink Versioning from the deploymentId: "latest" tip.
docs/content/docs/v4/changelog/eager-processing.mdxReword to "step-wrapped start() helper" to match v4 phrasing.
docs/content/docs/v5/migration-guides/{migrating-from-trigger-dev,migrating-from-temporal,migrating-from-inngest,migrating-from-aws-step-functions}.mdxUpdate to v5 native workflow-context start(); only collect step retains "use step".

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

@TooTallNateTooTallNate left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Comment-only review

The new versioning foundations page is a useful addition — the four sections (default pinning → recovery → self-upgrade via start({ deploymentId: "latest" }) → carrying serializable context forward) cover the model clearly, and the v4-vs-v5 differentiation (step-wrapped start() vs direct start() from workflow context, gated on whether PR #1491 has landed on the target branch) is correctly handled. The cross-links from cookbook patterns to the new foundations page tie everything together nicely.

Three observations — see inline.

Inline comments

  1. Wording: this PR introduces "Vercelism" as a new term and uses it 6 times across the diff, including replacing existing "Vercel-specific feature" wording in two <Callout>s. "Vercelism" reads as informal slang and isn't part of the established docs vocabulary. The existing tone uses "Vercel-specific", "Vercel deployments", "Vercel World", "non-Vercel" — all precise. Suggested restoring the prior phrasing. This is the only thing I'd consider blocking.
  2. Broken link in v4: versioning.mdx references /docs/foundations/cancellation in its related frontmatter, but that page is v5-only. Easy fix.
  3. Missing changeset: convention for docs-only PRs is an empty ---\n--- file.

A few small things I noticed

  • The pre-emptively check for a conflict with getHookByToken() example (line 96 of versioning.mdx) — nice that you noted the race window in a later doc (#2011 callout), but this page doesn't have that warning. Worth a cross-link or <Callout type="warn"> here too, since the recovery pattern uses both start() and deploymentId: "latest" together.
  • The _idempotency / using syntax is great. Worth confirming the docs site's syntax highlighter renders it — I noticed #1988 recently fixed a homepage link lint regression, and the using syntax is TypeScript 5.2+ specific.
  • dailyDigest example (line 137-152): the state parameter is DigestState but the workflow doesn't actually use state.userId after the first sendDigest call — pattern is fine, just noting if you wanted to make the example illustrate state evolution more vividly, having sendDigest read state.lastSentAt (e.g. to avoid sending duplicates) would make the carry-forward intent clearer.

Overall the page reads well — once the Vercelism wording is restored and the v4 link is fixed, this should be good to go.

Comment threaddocs/content/docs/v5/api-reference/workflow-api/start.mdx Outdated
Comment threaddocs/content/docs/v4/foundations/versioning.mdx
Comment threaddocs/content/docs/v5/foundations/versioning.mdx

@TooTallNateTooTallNate left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

All three review comments addressed in 7eff96c — Vercelism wording reverted, v4 broken cancellation link fixed, empty changeset added. LGTM, approving.

@github-actions

Copy link
Copy Markdown
Contributor

Backport PR opened against stable: #2014. Merge conflicts were resolved by AI — please review carefully.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

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

Add workflow versioning docs - #2010

Merged
pranaygp merged 10 commits into
mainfrom
pranaygp/codex/docs-versioning-page
May 18, 2026
Merged

Add workflow versioning docs#2010
pranaygp merged 10 commits into
mainfrom
pranaygp/codex/docs-versioning-page

Conversation

@pranaygp

@pranaygppranaygp commented May 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a new Foundations page explaining Workflow SDK versioning semantics for both v5 and v4 docs.

The page covers:

  • default run pinning to the deployment that started the run
  • canceling and rerunning affected in-flight runs on the latest deployment
  • explicit self-upgrade patterns using deploymentId: "latest"
  • carrying serializable context such as streams and abort signals across child runs

This also links existing versioning and deploymentId: "latest" mentions back to the new Foundations page, and calls out that deploymentId is currently a Vercelism that may become a more generic version concept in the World spec later.

Follow-up cookbook pass added targeted callouts for long-lived or multi-turn patterns:

  • scheduled workflows
  • DurableAgent
  • AI SDK multi-turn sessions
  • Chat SDK sessions
  • Sandbox sessions

The docs now also distinguish v5 from v4 for child-run starts. Native start() from workflow context was added by e295bae41 / #1491, which is on main but not stable, so v5 examples encourage direct workflow-context start() and v4 keeps the step-wrapped pattern.

Validation

  • git diff --check
  • Parsed the updated v4/v5 Foundations meta.json files as JSON
  • Verified v4/v5 copies of the touched cookbook pages match before the v5-only native-start pass
  • Searched docs/content for stale v5 step-wrapped start() guidance and v4 direct-start guidance
  • Confirmed origin/stable lacks the 'use step' directive in packages/core/src/runtime/start.ts, while main has it via e295bae41 / feat: allow start() to be called directly inside workflow functions #1491

Full docs lint/typecheck were not run because this checkout does not have node_modules installed, so biome, vitest, and changeset are unavailable locally.

@vercel

vercelBot commented May 18, 2026

Copy link
Copy Markdown
Contributor

@changeset-bot

changeset-botBot commented May 18, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7eff96c

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

This PR includes changesets to release 0 packages

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

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

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

@github-actions

github-actionsBot commented May 18, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

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

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Nitro0.031s (-28.3% 🟢)1.005s (~)0.974s101.00x
💻 LocalExpress0.036s (-19.6% 🟢)1.005s (~)0.970s101.15x
🐘 PostgresExpress0.045s (-21.9% 🟢)1.011s (~)0.966s101.47x
🐘 PostgresNitro0.046s (-51.3% 🟢)1.013s (-2.9%)0.967s101.50x
workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.070s (-4.9%)2.006s (~)0.936s101.00x
💻 LocalNitro1.071s (-5.3% 🟢)2.006s (~)0.935s101.00x
🐘 PostgresExpress1.079s (-5.9% 🟢)2.009s (~)0.930s101.01x
🐘 PostgresNitro1.081s (-5.2% 🟢)2.010s (~)0.929s101.01x
workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro10.396s (-4.4%)11.018s (~)0.622s31.00x
🐘 PostgresExpress10.402s (-5.1% 🟢)11.016s (~)0.614s31.00x
💻 LocalExpress10.411s (-4.7%)11.023s (~)0.612s31.00x
💻 LocalNitro10.412s (-4.9%)11.022s (~)0.610s31.00x
workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express13.432s (-10.3% 🟢)14.027s (-6.7% 🟢)0.595s51.00x
🐘 PostgresExpress13.435s (-7.9% 🟢)14.017s (-6.7% 🟢)0.581s51.00x
🐘 PostgresNitro13.484s (-7.6% 🟢)14.017s (-6.7% 🟢)0.533s51.00x
💻 LocalNitro13.489s (-10.4% 🟢)14.027s (-12.5% 🟢)0.538s51.00x
workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Nitro11.875s (-29.2% 🟢)12.022s (-29.4% 🟢)0.147s81.00x
💻 LocalExpress11.890s (-28.4% 🟢)12.022s (-29.4% 🟢)0.132s81.00x
🐘 PostgresExpress11.941s (-14.7% 🟢)12.391s (-15.1% 🟢)0.450s81.01x
🐘 PostgresNitro11.944s (-14.5% 🟢)12.266s (-14.3% 🟢)0.321s81.01x
Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.136s (-9.8% 🟢)2.007s (~)0.870s151.00x
🐘 PostgresNitro1.137s (-10.8% 🟢)2.007s (~)0.870s151.00x
💻 LocalNitro1.172s (-28.2% 🟢)2.006s (-3.3%)0.834s151.03x
💻 LocalExpress1.183s (-20.6% 🟢)2.006s (~)0.823s151.04x
Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.192s (-49.3% 🟢)2.007s (-33.3% 🟢)0.815s151.00x
🐘 PostgresExpress1.224s (-48.2% 🟢)2.007s (-33.3% 🟢)0.783s151.03x
💻 LocalExpress1.703s (-42.3% 🟢)2.005s (-41.9% 🟢)0.303s151.43x
💻 LocalNitro1.704s (-45.8% 🟢)2.005s (-48.4% 🟢)0.302s151.43x
Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.305s (-62.5% 🟢)2.008s (-49.9% 🟢)0.702s151.00x
🐘 PostgresExpress1.324s (-62.0% 🟢)2.008s (-49.9% 🟢)0.684s151.01x
💻 LocalExpress4.638s (-44.4% 🟢)5.179s (-42.6% 🟢)0.541s63.55x
💻 LocalNitro4.910s (-41.2% 🟢)5.511s (-38.9% 🟢)0.601s63.76x
Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.155s (-8.1% 🟢)2.009s (~)0.854s151.00x
🐘 PostgresNitro1.163s (-7.5% 🟢)2.010s (~)0.847s151.01x
💻 LocalExpress1.386s (-26.8% 🟢)2.006s (-15.2% 🟢)0.620s151.20x
💻 LocalNitro1.388s (-25.6% 🟢)2.006s (-14.3% 🟢)0.618s151.20x
Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.199s (-48.8% 🟢)2.008s (-33.3% 🟢)0.810s151.00x
🐘 PostgresNitro1.199s (-48.7% 🟢)2.007s (-33.3% 🟢)0.808s151.00x
💻 LocalExpress1.828s (-41.6% 🟢)2.222s (-40.9% 🟢)0.394s141.53x
💻 LocalNitro1.935s (-36.9% 🟢)2.316s (-40.4% 🟢)0.381s131.61x
Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.305s (-62.7% 🟢)2.008s (-49.9% 🟢)0.702s151.00x
🐘 PostgresNitro1.309s (-62.4% 🟢)2.009s (-49.9% 🟢)0.700s151.00x
💻 LocalExpress5.446s (-38.1% 🟢)5.849s (-36.9% 🟢)0.403s64.17x
💻 LocalNitro5.557s (-39.2% 🟢)6.179s (-38.4% 🟢)0.622s64.26x
workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.418s (-50.1% 🟢)1.006s (-1.6%)0.588s601.00x
🐘 PostgresNitro0.459s (-44.0% 🟢)1.006s (~)0.547s601.10x
💻 LocalNitro0.468s (-52.2% 🟢)1.004s (-8.2% 🟢)0.535s601.12x
💻 LocalExpress0.469s (-52.4% 🟢)1.004s (-6.7% 🟢)0.535s601.12x
workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.047s (-47.0% 🟢)1.705s (-24.5% 🟢)0.659s531.00x
🐘 PostgresNitro1.066s (-44.7% 🟢)1.576s (-25.0% 🟢)0.510s581.02x
💻 LocalNitro1.185s (-61.0% 🟢)2.006s (-46.6% 🟢)0.821s451.13x
💻 LocalExpress1.191s (-60.5% 🟢)2.005s (-44.1% 🟢)0.815s451.14x
workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express2.030s (-49.1% 🟢)2.427s (-44.4% 🟢)0.397s501.00x
🐘 PostgresNitro2.128s (-48.2% 🟢)2.660s (-42.2% 🟢)0.532s461.05x
💻 LocalNitro2.704s (-70.9% 🟢)3.032s (-69.7% 🟢)0.328s401.33x
💻 LocalExpress2.719s (-70.5% 🟢)3.057s (-69.5% 🟢)0.338s401.34x
workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.163s (-42.4% 🟢)1.005s (~)0.843s601.00x
🐘 PostgresNitro0.178s (-37.0% 🟢)1.006s (~)0.827s601.10x
💻 LocalExpress0.455s (-18.8% 🟢)1.004s (~)0.550s602.80x
💻 LocalNitro0.469s (-22.4% 🟢)1.004s (-1.7%)0.535s602.89x
workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.286s (-43.9% 🟢)1.006s (~)0.720s901.00x
🐘 PostgresNitro0.295s (-40.5% 🟢)1.006s (~)0.711s901.03x
💻 LocalNitro2.205s (-13.1% 🟢)2.944s (-2.2%)0.738s317.71x
💻 LocalExpress2.226s (-11.4% 🟢)2.943s (-2.2%)0.717s317.78x
workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.582s (-28.9% 🟢)1.007s (-1.0%)0.425s1201.00x
🐘 PostgresNitro0.634s (-19.7% 🟢)1.006s (~)0.372s1201.09x
💻 LocalNitro10.021s (-10.5% 🟢)10.611s (-9.0% 🟢)0.590s1217.21x
💻 LocalExpress10.042s (-10.3% 🟢)10.694s (-10.4% 🟢)0.652s1217.25x
Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.132s (+468.5% 🔺)2.005s (+99.6% 🔺)0.011s (-13.2% 🟢)2.018s (+98.2% 🔺)0.886s101.00x
💻 LocalNitro1.133s (+430.4% 🔺)2.005s (+99.6% 🔺)0.011s (-15.2% 🟢)2.018s (+98.1% 🔺)0.885s101.00x
🐘 PostgresNitro1.135s (+453.6% 🔺)2.001s (+100.2% 🔺)0.001s (-20.0% 🟢)2.010s (+98.7% 🔺)0.875s101.00x
🐘 PostgresExpress1.135s (+453.5% 🔺)1.999s (+100.2% 🔺)0.001s (-25.0% 🟢)2.010s (+98.7% 🔺)0.875s101.00x
stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.492s (+136.8% 🔺)2.002s (+98.9% 🔺)0.003s (-30.4% 🟢)2.023s (+97.8% 🔺)0.531s301.00x
🐘 PostgresNitro1.519s (+143.4% 🔺)2.004s (+99.0% 🔺)0.004s (-2.5%)2.027s (+98.2% 🔺)0.507s301.02x
💻 LocalNitro1.707s (+103.5% 🔺)2.013s (+98.9% 🔺)0.009s (-4.3%)2.203s (+97.4% 🔺)0.496s281.14x
💻 LocalExpress1.923s (+154.0% 🔺)2.011s (+95.4% 🔺)0.009s (-8.2% 🟢)2.422s (+132.9% 🔺)0.499s251.29x
10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.627s (-34.7% 🟢)1.033s (-19.2% 🟢)0.000s (-20.7% 🟢)1.045s (-20.0% 🟢)0.418s581.00x
🐘 PostgresNitro0.662s (-31.7% 🟢)1.029s (-17.5% 🟢)0.000s (-17.2% 🟢)1.049s (-16.6% 🟢)0.387s581.05x
💻 LocalExpress1.365s (+11.5% 🔺)2.015s (~)0.000s (+40.0% 🔺)2.018s (~)0.652s302.18x
💻 LocalNitro1.561s (+27.6% 🔺)2.016s (~)0.000s (+364.3% 🔺)2.197s (+8.7% 🔺)0.636s282.49x
fan-out fan-in 10 streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.228s (-30.7% 🟢)1.869s (-14.2% 🟢)0.000s (NaN%)1.900s (-13.6% 🟢)0.673s321.00x
🐘 PostgresNitro1.325s (-26.1% 🟢)1.997s (-6.7% 🟢)0.000s (+86.7% 🔺)2.019s (-7.2% 🟢)0.694s301.08x
💻 LocalExpress3.158s (-8.9% 🟢)4.028s (~)0.001s (-33.3% 🟢)4.030s (~)0.873s152.57x
💻 LocalNitro3.187s (-5.9% 🟢)4.029s (~)0.000s (-75.0% 🟢)4.031s (~)0.844s152.60x

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalExpress12/21
🐘 PostgresExpress17/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres16/21
Nitro🐘 Postgres17/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.

@github-actions

github-actionsBot commented May 18, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
❌ ▲ Vercel Production119642191419
✅ 💻 Local Development158702191806
✅ 📦 Local Production145802191677
❌ 🐘 Local Postgres158522191806
✅ 🪟 Windows12900129
✅ 📋 Other7270176903
Total6682610527740

❌ Failed Tests

▲ Vercel Production (4 failed)

astro (1 failed):

  • AbortController abortFromStepWorkflow: step abort cancels an in-flight sibling step

hono (2 failed):

  • outputStreamWorkflow no startIndex (reads all chunks)
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KRYMPWTNKF0CE4BP27X7R946 | 🔍 observability

nextjs-webpack (1 failed):

🐘 Local Postgres (2 failed)

nextjs-webpack-stable-lazy-discovery-disabled (1 failed):

  • DurableAgent e2e core basic text response

nextjs-webpack-stable-lazy-discovery-enabled (1 failed):

  • addTenWorkflow | wrun_01KRYMBT8QHFK9EZ9FDY03D9G0

Details by Category

❌ ▲ Vercel Production
AppPassedFailedSkipped
❌ astro102126
✅ example103026
✅ express103026
✅ fastify103026
❌ hono101226
✅ nextjs-turbopack12702
❌ nextjs-webpack12612
✅ nitro103026
✅ nuxt103026
✅ sveltekit12207
✅ vite103026
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable104025
✅ express-stable104025
✅ fastify-stable104025
✅ hono-stable104025
✅ nextjs-turbopack-canary110019
✅ nextjs-turbopack-stable-lazy-discovery-disabled12900
✅ nextjs-turbopack-stable-lazy-discovery-enabled12900
✅ nextjs-webpack-canary110019
✅ nextjs-webpack-stable-lazy-discovery-disabled12900
✅ nextjs-webpack-stable-lazy-discovery-enabled12900
✅ nitro-stable104025
✅ nuxt-stable104025
✅ sveltekit-stable12306
✅ vite-stable104025
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable104025
✅ express-stable104025
✅ fastify-stable104025
✅ hono-stable104025
✅ nextjs-turbopack-canary110019
✅ nextjs-turbopack-stable-lazy-discovery-disabled12900
✅ nextjs-webpack-canary110019
✅ nextjs-webpack-stable-lazy-discovery-disabled12900
✅ nextjs-webpack-stable-lazy-discovery-enabled12900
✅ nitro-stable104025
✅ nuxt-stable104025
✅ sveltekit-stable12306
✅ vite-stable104025
❌ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable104025
✅ express-stable104025
✅ fastify-stable104025
✅ hono-stable104025
✅ nextjs-turbopack-canary110019
✅ nextjs-turbopack-stable-lazy-discovery-disabled12900
✅ nextjs-turbopack-stable-lazy-discovery-enabled12900
✅ nextjs-webpack-canary110019
❌ nextjs-webpack-stable-lazy-discovery-disabled12810
❌ nextjs-webpack-stable-lazy-discovery-enabled12810
✅ nitro-stable104025
✅ nuxt-stable104025
✅ sveltekit-stable12306
✅ vite-stable104025
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack12900
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable104025
✅ e2e-local-dev-tanstack-start-104025
✅ e2e-local-postgres-nest-stable104025
✅ e2e-local-postgres-tanstack-start-104025
✅ e2e-local-prod-nest-stable104025
✅ e2e-local-prod-tanstack-start-104025
✅ e2e-vercel-prod-tanstack-start103026

📋 View full workflow run


Some E2E test jobs failed:

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

Check the workflow run for details.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a new "Versioning" Foundations page (v4 and v5) explaining default run pinning to deployments, recovery via cancel + rerun, opting into newer code with deploymentId: "latest", and carrying serializable state/streams across child-run continuations. Existing references to deploymentId: "latest" and versioning behavior are linked back to the new page. Cookbook pages also pick up callouts about long-lived / multi-turn patterns and, on v5 only, are updated to reflect that start() can now be called directly inside "use workflow" functions (via #1491), while v4 retains the step-wrapped pattern.

Changes:

  • New foundations/versioning.mdx for both v4 and v5, plus meta.json + index.mdx + linkbacks from vercel-world, start.mdx, and code-transform.mdx.
  • v5 cookbook + migration guides updated to drop "use step" wrappers around start() in favor of calling start() directly from the workflow function; v4 keeps the step-wrapped pattern.
  • Added "Versioning" callouts to scheduling, durable-agent, ai-sdk, chat-sdk, and sandbox cookbooks; fixed a few small wording/grammar issues in code-transform.mdx.

Reviewed changes

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

Show a summary per file
FileDescription
docs/content/docs/v5/foundations/versioning.mdxNew Foundations page explaining run pinning, recovery, and explicit upgrade boundaries.
docs/content/docs/v4/foundations/versioning.mdxv4 counterpart; uses step-wrapped continueDigest/continueExportOnLatest helpers.
docs/content/docs/v{4,5}/foundations/{meta.json,index.mdx}Surface the new Versioning page in nav and the foundations index.
docs/content/docs/v{4,5}/deploying/world/vercel-world.mdxLink the deployment-pinning section to the new Versioning page.
docs/content/docs/v{4,5}/how-it-works/code-transform.mdxLink "atomic versioning" reference; fix "function assume" / "from being upgraded" wording.
docs/content/docs/v{4,5}/api-reference/workflow-api/start.mdxSoften "Vercel-specific" to "Vercelism", mention possible version rename, link Versioning. v5 also notes native workflow-context start().
docs/content/docs/v5/foundations/starting-workflows.mdxNote v5 can call start() from workflows; link Composition + Versioning.
docs/content/docs/v5/cookbook/common-patterns/workflow-composition.mdxReplace step-wrapped child spawn with direct start() call.
docs/content/docs/v5/cookbook/advanced/child-workflows.mdxInline batched start() calls; rename spawnReportChunkstartReportChunk; update tips.
docs/content/docs/v{4,5}/cookbook/common-patterns/scheduling.mdxCallout linking to Versioning for long-lived schedules.
docs/content/docs/v{4,5}/cookbook/agent-patterns/durable-agent.mdxCallout linking to Versioning for multi-turn agents.
docs/content/docs/v{4,5}/cookbook/integrations/{ai-sdk,chat-sdk,sandbox}.mdxCallouts linking to Versioning for long-lived sessions.
docs/content/docs/v4/cookbook/common-patterns/workflow-composition.mdxUpdate deploymentId: "latest" callout wording + link to Versioning.
docs/content/docs/v4/cookbook/advanced/child-workflows.mdxLink Versioning from the deploymentId: "latest" tip.
docs/content/docs/v4/changelog/eager-processing.mdxReword to "step-wrapped start() helper" to match v4 phrasing.
docs/content/docs/v5/migration-guides/{migrating-from-trigger-dev,migrating-from-temporal,migrating-from-inngest,migrating-from-aws-step-functions}.mdxUpdate to v5 native workflow-context start(); only collect step retains "use step".

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

@TooTallNateTooTallNate left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Comment-only review

The new versioning foundations page is a useful addition — the four sections (default pinning → recovery → self-upgrade via start({ deploymentId: "latest" }) → carrying serializable context forward) cover the model clearly, and the v4-vs-v5 differentiation (step-wrapped start() vs direct start() from workflow context, gated on whether PR #1491 has landed on the target branch) is correctly handled. The cross-links from cookbook patterns to the new foundations page tie everything together nicely.

Three observations — see inline.

Inline comments

  1. Wording: this PR introduces "Vercelism" as a new term and uses it 6 times across the diff, including replacing existing "Vercel-specific feature" wording in two <Callout>s. "Vercelism" reads as informal slang and isn't part of the established docs vocabulary. The existing tone uses "Vercel-specific", "Vercel deployments", "Vercel World", "non-Vercel" — all precise. Suggested restoring the prior phrasing. This is the only thing I'd consider blocking.
  2. Broken link in v4: versioning.mdx references /docs/foundations/cancellation in its related frontmatter, but that page is v5-only. Easy fix.
  3. Missing changeset: convention for docs-only PRs is an empty ---\n--- file.

A few small things I noticed

  • The pre-emptively check for a conflict with getHookByToken() example (line 96 of versioning.mdx) — nice that you noted the race window in a later doc (#2011 callout), but this page doesn't have that warning. Worth a cross-link or <Callout type="warn"> here too, since the recovery pattern uses both start() and deploymentId: "latest" together.
  • The _idempotency / using syntax is great. Worth confirming the docs site's syntax highlighter renders it — I noticed #1988 recently fixed a homepage link lint regression, and the using syntax is TypeScript 5.2+ specific.
  • dailyDigest example (line 137-152): the state parameter is DigestState but the workflow doesn't actually use state.userId after the first sendDigest call — pattern is fine, just noting if you wanted to make the example illustrate state evolution more vividly, having sendDigest read state.lastSentAt (e.g. to avoid sending duplicates) would make the carry-forward intent clearer.

Overall the page reads well — once the Vercelism wording is restored and the v4 link is fixed, this should be good to go.

Comment threaddocs/content/docs/v5/api-reference/workflow-api/start.mdx Outdated
Comment threaddocs/content/docs/v4/foundations/versioning.mdx
Comment threaddocs/content/docs/v5/foundations/versioning.mdx

@TooTallNateTooTallNate left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

All three review comments addressed in 7eff96c — Vercelism wording reverted, v4 broken cancellation link fixed, empty changeset added. LGTM, approving.

@github-actions

Copy link
Copy Markdown
Contributor

Backport PR opened against stable: #2014. Merge conflicts were resolved by AI — please review carefully.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

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

Add workflow versioning docs - #2010

Merged
pranaygp merged 10 commits into
mainfrom
pranaygp/codex/docs-versioning-page
May 18, 2026
Merged

Add workflow versioning docs#2010
pranaygp merged 10 commits into
mainfrom
pranaygp/codex/docs-versioning-page

Conversation

@pranaygp

@pranaygppranaygp commented May 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a new Foundations page explaining Workflow SDK versioning semantics for both v5 and v4 docs.

The page covers:

  • default run pinning to the deployment that started the run
  • canceling and rerunning affected in-flight runs on the latest deployment
  • explicit self-upgrade patterns using deploymentId: "latest"
  • carrying serializable context such as streams and abort signals across child runs

This also links existing versioning and deploymentId: "latest" mentions back to the new Foundations page, and calls out that deploymentId is currently a Vercelism that may become a more generic version concept in the World spec later.

Follow-up cookbook pass added targeted callouts for long-lived or multi-turn patterns:

  • scheduled workflows
  • DurableAgent
  • AI SDK multi-turn sessions
  • Chat SDK sessions
  • Sandbox sessions

The docs now also distinguish v5 from v4 for child-run starts. Native start() from workflow context was added by e295bae41 / #1491, which is on main but not stable, so v5 examples encourage direct workflow-context start() and v4 keeps the step-wrapped pattern.

Validation

  • git diff --check
  • Parsed the updated v4/v5 Foundations meta.json files as JSON
  • Verified v4/v5 copies of the touched cookbook pages match before the v5-only native-start pass
  • Searched docs/content for stale v5 step-wrapped start() guidance and v4 direct-start guidance
  • Confirmed origin/stable lacks the 'use step' directive in packages/core/src/runtime/start.ts, while main has it via e295bae41 / feat: allow start() to be called directly inside workflow functions #1491

Full docs lint/typecheck were not run because this checkout does not have node_modules installed, so biome, vitest, and changeset are unavailable locally.

@vercel

vercelBot commented May 18, 2026

Copy link
Copy Markdown
Contributor

@changeset-bot

changeset-botBot commented May 18, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7eff96c

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

This PR includes changesets to release 0 packages

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

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

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

@github-actions

github-actionsBot commented May 18, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

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

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Nitro0.031s (-28.3% 🟢)1.005s (~)0.974s101.00x
💻 LocalExpress0.036s (-19.6% 🟢)1.005s (~)0.970s101.15x
🐘 PostgresExpress0.045s (-21.9% 🟢)1.011s (~)0.966s101.47x
🐘 PostgresNitro0.046s (-51.3% 🟢)1.013s (-2.9%)0.967s101.50x
workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.070s (-4.9%)2.006s (~)0.936s101.00x
💻 LocalNitro1.071s (-5.3% 🟢)2.006s (~)0.935s101.00x
🐘 PostgresExpress1.079s (-5.9% 🟢)2.009s (~)0.930s101.01x
🐘 PostgresNitro1.081s (-5.2% 🟢)2.010s (~)0.929s101.01x
workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro10.396s (-4.4%)11.018s (~)0.622s31.00x
🐘 PostgresExpress10.402s (-5.1% 🟢)11.016s (~)0.614s31.00x
💻 LocalExpress10.411s (-4.7%)11.023s (~)0.612s31.00x
💻 LocalNitro10.412s (-4.9%)11.022s (~)0.610s31.00x
workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express13.432s (-10.3% 🟢)14.027s (-6.7% 🟢)0.595s51.00x
🐘 PostgresExpress13.435s (-7.9% 🟢)14.017s (-6.7% 🟢)0.581s51.00x
🐘 PostgresNitro13.484s (-7.6% 🟢)14.017s (-6.7% 🟢)0.533s51.00x
💻 LocalNitro13.489s (-10.4% 🟢)14.027s (-12.5% 🟢)0.538s51.00x
workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Nitro11.875s (-29.2% 🟢)12.022s (-29.4% 🟢)0.147s81.00x
💻 LocalExpress11.890s (-28.4% 🟢)12.022s (-29.4% 🟢)0.132s81.00x
🐘 PostgresExpress11.941s (-14.7% 🟢)12.391s (-15.1% 🟢)0.450s81.01x
🐘 PostgresNitro11.944s (-14.5% 🟢)12.266s (-14.3% 🟢)0.321s81.01x
Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.136s (-9.8% 🟢)2.007s (~)0.870s151.00x
🐘 PostgresNitro1.137s (-10.8% 🟢)2.007s (~)0.870s151.00x
💻 LocalNitro1.172s (-28.2% 🟢)2.006s (-3.3%)0.834s151.03x
💻 LocalExpress1.183s (-20.6% 🟢)2.006s (~)0.823s151.04x
Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.192s (-49.3% 🟢)2.007s (-33.3% 🟢)0.815s151.00x
🐘 PostgresExpress1.224s (-48.2% 🟢)2.007s (-33.3% 🟢)0.783s151.03x
💻 LocalExpress1.703s (-42.3% 🟢)2.005s (-41.9% 🟢)0.303s151.43x
💻 LocalNitro1.704s (-45.8% 🟢)2.005s (-48.4% 🟢)0.302s151.43x
Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.305s (-62.5% 🟢)2.008s (-49.9% 🟢)0.702s151.00x
🐘 PostgresExpress1.324s (-62.0% 🟢)2.008s (-49.9% 🟢)0.684s151.01x
💻 LocalExpress4.638s (-44.4% 🟢)5.179s (-42.6% 🟢)0.541s63.55x
💻 LocalNitro4.910s (-41.2% 🟢)5.511s (-38.9% 🟢)0.601s63.76x
Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.155s (-8.1% 🟢)2.009s (~)0.854s151.00x
🐘 PostgresNitro1.163s (-7.5% 🟢)2.010s (~)0.847s151.01x
💻 LocalExpress1.386s (-26.8% 🟢)2.006s (-15.2% 🟢)0.620s151.20x
💻 LocalNitro1.388s (-25.6% 🟢)2.006s (-14.3% 🟢)0.618s151.20x
Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.199s (-48.8% 🟢)2.008s (-33.3% 🟢)0.810s151.00x
🐘 PostgresNitro1.199s (-48.7% 🟢)2.007s (-33.3% 🟢)0.808s151.00x
💻 LocalExpress1.828s (-41.6% 🟢)2.222s (-40.9% 🟢)0.394s141.53x
💻 LocalNitro1.935s (-36.9% 🟢)2.316s (-40.4% 🟢)0.381s131.61x
Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.305s (-62.7% 🟢)2.008s (-49.9% 🟢)0.702s151.00x
🐘 PostgresNitro1.309s (-62.4% 🟢)2.009s (-49.9% 🟢)0.700s151.00x
💻 LocalExpress5.446s (-38.1% 🟢)5.849s (-36.9% 🟢)0.403s64.17x
💻 LocalNitro5.557s (-39.2% 🟢)6.179s (-38.4% 🟢)0.622s64.26x
workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.418s (-50.1% 🟢)1.006s (-1.6%)0.588s601.00x
🐘 PostgresNitro0.459s (-44.0% 🟢)1.006s (~)0.547s601.10x
💻 LocalNitro0.468s (-52.2% 🟢)1.004s (-8.2% 🟢)0.535s601.12x
💻 LocalExpress0.469s (-52.4% 🟢)1.004s (-6.7% 🟢)0.535s601.12x
workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.047s (-47.0% 🟢)1.705s (-24.5% 🟢)0.659s531.00x
🐘 PostgresNitro1.066s (-44.7% 🟢)1.576s (-25.0% 🟢)0.510s581.02x
💻 LocalNitro1.185s (-61.0% 🟢)2.006s (-46.6% 🟢)0.821s451.13x
💻 LocalExpress1.191s (-60.5% 🟢)2.005s (-44.1% 🟢)0.815s451.14x
workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express2.030s (-49.1% 🟢)2.427s (-44.4% 🟢)0.397s501.00x
🐘 PostgresNitro2.128s (-48.2% 🟢)2.660s (-42.2% 🟢)0.532s461.05x
💻 LocalNitro2.704s (-70.9% 🟢)3.032s (-69.7% 🟢)0.328s401.33x
💻 LocalExpress2.719s (-70.5% 🟢)3.057s (-69.5% 🟢)0.338s401.34x
workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.163s (-42.4% 🟢)1.005s (~)0.843s601.00x
🐘 PostgresNitro0.178s (-37.0% 🟢)1.006s (~)0.827s601.10x
💻 LocalExpress0.455s (-18.8% 🟢)1.004s (~)0.550s602.80x
💻 LocalNitro0.469s (-22.4% 🟢)1.004s (-1.7%)0.535s602.89x
workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.286s (-43.9% 🟢)1.006s (~)0.720s901.00x
🐘 PostgresNitro0.295s (-40.5% 🟢)1.006s (~)0.711s901.03x
💻 LocalNitro2.205s (-13.1% 🟢)2.944s (-2.2%)0.738s317.71x
💻 LocalExpress2.226s (-11.4% 🟢)2.943s (-2.2%)0.717s317.78x
workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.582s (-28.9% 🟢)1.007s (-1.0%)0.425s1201.00x
🐘 PostgresNitro0.634s (-19.7% 🟢)1.006s (~)0.372s1201.09x
💻 LocalNitro10.021s (-10.5% 🟢)10.611s (-9.0% 🟢)0.590s1217.21x
💻 LocalExpress10.042s (-10.3% 🟢)10.694s (-10.4% 🟢)0.652s1217.25x
Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.132s (+468.5% 🔺)2.005s (+99.6% 🔺)0.011s (-13.2% 🟢)2.018s (+98.2% 🔺)0.886s101.00x
💻 LocalNitro1.133s (+430.4% 🔺)2.005s (+99.6% 🔺)0.011s (-15.2% 🟢)2.018s (+98.1% 🔺)0.885s101.00x
🐘 PostgresNitro1.135s (+453.6% 🔺)2.001s (+100.2% 🔺)0.001s (-20.0% 🟢)2.010s (+98.7% 🔺)0.875s101.00x
🐘 PostgresExpress1.135s (+453.5% 🔺)1.999s (+100.2% 🔺)0.001s (-25.0% 🟢)2.010s (+98.7% 🔺)0.875s101.00x
stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.492s (+136.8% 🔺)2.002s (+98.9% 🔺)0.003s (-30.4% 🟢)2.023s (+97.8% 🔺)0.531s301.00x
🐘 PostgresNitro1.519s (+143.4% 🔺)2.004s (+99.0% 🔺)0.004s (-2.5%)2.027s (+98.2% 🔺)0.507s301.02x
💻 LocalNitro1.707s (+103.5% 🔺)2.013s (+98.9% 🔺)0.009s (-4.3%)2.203s (+97.4% 🔺)0.496s281.14x
💻 LocalExpress1.923s (+154.0% 🔺)2.011s (+95.4% 🔺)0.009s (-8.2% 🟢)2.422s (+132.9% 🔺)0.499s251.29x
10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.627s (-34.7% 🟢)1.033s (-19.2% 🟢)0.000s (-20.7% 🟢)1.045s (-20.0% 🟢)0.418s581.00x
🐘 PostgresNitro0.662s (-31.7% 🟢)1.029s (-17.5% 🟢)0.000s (-17.2% 🟢)1.049s (-16.6% 🟢)0.387s581.05x
💻 LocalExpress1.365s (+11.5% 🔺)2.015s (~)0.000s (+40.0% 🔺)2.018s (~)0.652s302.18x
💻 LocalNitro1.561s (+27.6% 🔺)2.016s (~)0.000s (+364.3% 🔺)2.197s (+8.7% 🔺)0.636s282.49x
fan-out fan-in 10 streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.228s (-30.7% 🟢)1.869s (-14.2% 🟢)0.000s (NaN%)1.900s (-13.6% 🟢)0.673s321.00x
🐘 PostgresNitro1.325s (-26.1% 🟢)1.997s (-6.7% 🟢)0.000s (+86.7% 🔺)2.019s (-7.2% 🟢)0.694s301.08x
💻 LocalExpress3.158s (-8.9% 🟢)4.028s (~)0.001s (-33.3% 🟢)4.030s (~)0.873s152.57x
💻 LocalNitro3.187s (-5.9% 🟢)4.029s (~)0.000s (-75.0% 🟢)4.031s (~)0.844s152.60x

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalExpress12/21
🐘 PostgresExpress17/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres16/21
Nitro🐘 Postgres17/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.

@github-actions

github-actionsBot commented May 18, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
❌ ▲ Vercel Production119642191419
✅ 💻 Local Development158702191806
✅ 📦 Local Production145802191677
❌ 🐘 Local Postgres158522191806
✅ 🪟 Windows12900129
✅ 📋 Other7270176903
Total6682610527740

❌ Failed Tests

▲ Vercel Production (4 failed)

astro (1 failed):

  • AbortController abortFromStepWorkflow: step abort cancels an in-flight sibling step

hono (2 failed):

  • outputStreamWorkflow no startIndex (reads all chunks)
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KRYMPWTNKF0CE4BP27X7R946 | 🔍 observability

nextjs-webpack (1 failed):

🐘 Local Postgres (2 failed)

nextjs-webpack-stable-lazy-discovery-disabled (1 failed):

  • DurableAgent e2e core basic text response

nextjs-webpack-stable-lazy-discovery-enabled (1 failed):

  • addTenWorkflow | wrun_01KRYMBT8QHFK9EZ9FDY03D9G0

Details by Category

❌ ▲ Vercel Production
AppPassedFailedSkipped
❌ astro102126
✅ example103026
✅ express103026
✅ fastify103026
❌ hono101226
✅ nextjs-turbopack12702
❌ nextjs-webpack12612
✅ nitro103026
✅ nuxt103026
✅ sveltekit12207
✅ vite103026
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable104025
✅ express-stable104025
✅ fastify-stable104025
✅ hono-stable104025
✅ nextjs-turbopack-canary110019
✅ nextjs-turbopack-stable-lazy-discovery-disabled12900
✅ nextjs-turbopack-stable-lazy-discovery-enabled12900
✅ nextjs-webpack-canary110019
✅ nextjs-webpack-stable-lazy-discovery-disabled12900
✅ nextjs-webpack-stable-lazy-discovery-enabled12900
✅ nitro-stable104025
✅ nuxt-stable104025
✅ sveltekit-stable12306
✅ vite-stable104025
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable104025
✅ express-stable104025
✅ fastify-stable104025
✅ hono-stable104025
✅ nextjs-turbopack-canary110019
✅ nextjs-turbopack-stable-lazy-discovery-disabled12900
✅ nextjs-webpack-canary110019
✅ nextjs-webpack-stable-lazy-discovery-disabled12900
✅ nextjs-webpack-stable-lazy-discovery-enabled12900
✅ nitro-stable104025
✅ nuxt-stable104025
✅ sveltekit-stable12306
✅ vite-stable104025
❌ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable104025
✅ express-stable104025
✅ fastify-stable104025
✅ hono-stable104025
✅ nextjs-turbopack-canary110019
✅ nextjs-turbopack-stable-lazy-discovery-disabled12900
✅ nextjs-turbopack-stable-lazy-discovery-enabled12900
✅ nextjs-webpack-canary110019
❌ nextjs-webpack-stable-lazy-discovery-disabled12810
❌ nextjs-webpack-stable-lazy-discovery-enabled12810
✅ nitro-stable104025
✅ nuxt-stable104025
✅ sveltekit-stable12306
✅ vite-stable104025
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack12900
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable104025
✅ e2e-local-dev-tanstack-start-104025
✅ e2e-local-postgres-nest-stable104025
✅ e2e-local-postgres-tanstack-start-104025
✅ e2e-local-prod-nest-stable104025
✅ e2e-local-prod-tanstack-start-104025
✅ e2e-vercel-prod-tanstack-start103026

📋 View full workflow run


Some E2E test jobs failed:

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

Check the workflow run for details.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a new "Versioning" Foundations page (v4 and v5) explaining default run pinning to deployments, recovery via cancel + rerun, opting into newer code with deploymentId: "latest", and carrying serializable state/streams across child-run continuations. Existing references to deploymentId: "latest" and versioning behavior are linked back to the new page. Cookbook pages also pick up callouts about long-lived / multi-turn patterns and, on v5 only, are updated to reflect that start() can now be called directly inside "use workflow" functions (via #1491), while v4 retains the step-wrapped pattern.

Changes:

  • New foundations/versioning.mdx for both v4 and v5, plus meta.json + index.mdx + linkbacks from vercel-world, start.mdx, and code-transform.mdx.
  • v5 cookbook + migration guides updated to drop "use step" wrappers around start() in favor of calling start() directly from the workflow function; v4 keeps the step-wrapped pattern.
  • Added "Versioning" callouts to scheduling, durable-agent, ai-sdk, chat-sdk, and sandbox cookbooks; fixed a few small wording/grammar issues in code-transform.mdx.

Reviewed changes

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

Show a summary per file
FileDescription
docs/content/docs/v5/foundations/versioning.mdxNew Foundations page explaining run pinning, recovery, and explicit upgrade boundaries.
docs/content/docs/v4/foundations/versioning.mdxv4 counterpart; uses step-wrapped continueDigest/continueExportOnLatest helpers.
docs/content/docs/v{4,5}/foundations/{meta.json,index.mdx}Surface the new Versioning page in nav and the foundations index.
docs/content/docs/v{4,5}/deploying/world/vercel-world.mdxLink the deployment-pinning section to the new Versioning page.
docs/content/docs/v{4,5}/how-it-works/code-transform.mdxLink "atomic versioning" reference; fix "function assume" / "from being upgraded" wording.
docs/content/docs/v{4,5}/api-reference/workflow-api/start.mdxSoften "Vercel-specific" to "Vercelism", mention possible version rename, link Versioning. v5 also notes native workflow-context start().
docs/content/docs/v5/foundations/starting-workflows.mdxNote v5 can call start() from workflows; link Composition + Versioning.
docs/content/docs/v5/cookbook/common-patterns/workflow-composition.mdxReplace step-wrapped child spawn with direct start() call.
docs/content/docs/v5/cookbook/advanced/child-workflows.mdxInline batched start() calls; rename spawnReportChunkstartReportChunk; update tips.
docs/content/docs/v{4,5}/cookbook/common-patterns/scheduling.mdxCallout linking to Versioning for long-lived schedules.
docs/content/docs/v{4,5}/cookbook/agent-patterns/durable-agent.mdxCallout linking to Versioning for multi-turn agents.
docs/content/docs/v{4,5}/cookbook/integrations/{ai-sdk,chat-sdk,sandbox}.mdxCallouts linking to Versioning for long-lived sessions.
docs/content/docs/v4/cookbook/common-patterns/workflow-composition.mdxUpdate deploymentId: "latest" callout wording + link to Versioning.
docs/content/docs/v4/cookbook/advanced/child-workflows.mdxLink Versioning from the deploymentId: "latest" tip.
docs/content/docs/v4/changelog/eager-processing.mdxReword to "step-wrapped start() helper" to match v4 phrasing.
docs/content/docs/v5/migration-guides/{migrating-from-trigger-dev,migrating-from-temporal,migrating-from-inngest,migrating-from-aws-step-functions}.mdxUpdate to v5 native workflow-context start(); only collect step retains "use step".

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

@TooTallNateTooTallNate left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Comment-only review

The new versioning foundations page is a useful addition — the four sections (default pinning → recovery → self-upgrade via start({ deploymentId: "latest" }) → carrying serializable context forward) cover the model clearly, and the v4-vs-v5 differentiation (step-wrapped start() vs direct start() from workflow context, gated on whether PR #1491 has landed on the target branch) is correctly handled. The cross-links from cookbook patterns to the new foundations page tie everything together nicely.

Three observations — see inline.

Inline comments

  1. Wording: this PR introduces "Vercelism" as a new term and uses it 6 times across the diff, including replacing existing "Vercel-specific feature" wording in two <Callout>s. "Vercelism" reads as informal slang and isn't part of the established docs vocabulary. The existing tone uses "Vercel-specific", "Vercel deployments", "Vercel World", "non-Vercel" — all precise. Suggested restoring the prior phrasing. This is the only thing I'd consider blocking.
  2. Broken link in v4: versioning.mdx references /docs/foundations/cancellation in its related frontmatter, but that page is v5-only. Easy fix.
  3. Missing changeset: convention for docs-only PRs is an empty ---\n--- file.

A few small things I noticed

  • The pre-emptively check for a conflict with getHookByToken() example (line 96 of versioning.mdx) — nice that you noted the race window in a later doc (#2011 callout), but this page doesn't have that warning. Worth a cross-link or <Callout type="warn"> here too, since the recovery pattern uses both start() and deploymentId: "latest" together.
  • The _idempotency / using syntax is great. Worth confirming the docs site's syntax highlighter renders it — I noticed #1988 recently fixed a homepage link lint regression, and the using syntax is TypeScript 5.2+ specific.
  • dailyDigest example (line 137-152): the state parameter is DigestState but the workflow doesn't actually use state.userId after the first sendDigest call — pattern is fine, just noting if you wanted to make the example illustrate state evolution more vividly, having sendDigest read state.lastSentAt (e.g. to avoid sending duplicates) would make the carry-forward intent clearer.

Overall the page reads well — once the Vercelism wording is restored and the v4 link is fixed, this should be good to go.

Comment threaddocs/content/docs/v5/api-reference/workflow-api/start.mdx Outdated
Comment threaddocs/content/docs/v4/foundations/versioning.mdx
Comment threaddocs/content/docs/v5/foundations/versioning.mdx

@TooTallNateTooTallNate left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

All three review comments addressed in 7eff96c — Vercelism wording reverted, v4 broken cancellation link fixed, empty changeset added. LGTM, approving.

@github-actions

Copy link
Copy Markdown
Contributor

Backport PR opened against stable: #2014. Merge conflicts were resolved by AI — please review carefully.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

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

Add workflow versioning docs - #2010

Merged
pranaygp merged 10 commits into
mainfrom
pranaygp/codex/docs-versioning-page
May 18, 2026
Merged

Add workflow versioning docs#2010
pranaygp merged 10 commits into
mainfrom
pranaygp/codex/docs-versioning-page

Conversation

@pranaygp

@pranaygppranaygp commented May 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a new Foundations page explaining Workflow SDK versioning semantics for both v5 and v4 docs.

The page covers:

  • default run pinning to the deployment that started the run
  • canceling and rerunning affected in-flight runs on the latest deployment
  • explicit self-upgrade patterns using deploymentId: "latest"
  • carrying serializable context such as streams and abort signals across child runs

This also links existing versioning and deploymentId: "latest" mentions back to the new Foundations page, and calls out that deploymentId is currently a Vercelism that may become a more generic version concept in the World spec later.

Follow-up cookbook pass added targeted callouts for long-lived or multi-turn patterns:

  • scheduled workflows
  • DurableAgent
  • AI SDK multi-turn sessions
  • Chat SDK sessions
  • Sandbox sessions

The docs now also distinguish v5 from v4 for child-run starts. Native start() from workflow context was added by e295bae41 / #1491, which is on main but not stable, so v5 examples encourage direct workflow-context start() and v4 keeps the step-wrapped pattern.

Validation

  • git diff --check
  • Parsed the updated v4/v5 Foundations meta.json files as JSON
  • Verified v4/v5 copies of the touched cookbook pages match before the v5-only native-start pass
  • Searched docs/content for stale v5 step-wrapped start() guidance and v4 direct-start guidance
  • Confirmed origin/stable lacks the 'use step' directive in packages/core/src/runtime/start.ts, while main has it via e295bae41 / feat: allow start() to be called directly inside workflow functions #1491

Full docs lint/typecheck were not run because this checkout does not have node_modules installed, so biome, vitest, and changeset are unavailable locally.

@vercel

vercelBot commented May 18, 2026

Copy link
Copy Markdown
Contributor

@changeset-bot

changeset-botBot commented May 18, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7eff96c

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

This PR includes changesets to release 0 packages

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

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

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

@github-actions

github-actionsBot commented May 18, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

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

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Nitro0.031s (-28.3% 🟢)1.005s (~)0.974s101.00x
💻 LocalExpress0.036s (-19.6% 🟢)1.005s (~)0.970s101.15x
🐘 PostgresExpress0.045s (-21.9% 🟢)1.011s (~)0.966s101.47x
🐘 PostgresNitro0.046s (-51.3% 🟢)1.013s (-2.9%)0.967s101.50x
workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.070s (-4.9%)2.006s (~)0.936s101.00x
💻 LocalNitro1.071s (-5.3% 🟢)2.006s (~)0.935s101.00x
🐘 PostgresExpress1.079s (-5.9% 🟢)2.009s (~)0.930s101.01x
🐘 PostgresNitro1.081s (-5.2% 🟢)2.010s (~)0.929s101.01x
workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro10.396s (-4.4%)11.018s (~)0.622s31.00x
🐘 PostgresExpress10.402s (-5.1% 🟢)11.016s (~)0.614s31.00x
💻 LocalExpress10.411s (-4.7%)11.023s (~)0.612s31.00x
💻 LocalNitro10.412s (-4.9%)11.022s (~)0.610s31.00x
workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express13.432s (-10.3% 🟢)14.027s (-6.7% 🟢)0.595s51.00x
🐘 PostgresExpress13.435s (-7.9% 🟢)14.017s (-6.7% 🟢)0.581s51.00x
🐘 PostgresNitro13.484s (-7.6% 🟢)14.017s (-6.7% 🟢)0.533s51.00x
💻 LocalNitro13.489s (-10.4% 🟢)14.027s (-12.5% 🟢)0.538s51.00x
workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Nitro11.875s (-29.2% 🟢)12.022s (-29.4% 🟢)0.147s81.00x
💻 LocalExpress11.890s (-28.4% 🟢)12.022s (-29.4% 🟢)0.132s81.00x
🐘 PostgresExpress11.941s (-14.7% 🟢)12.391s (-15.1% 🟢)0.450s81.01x
🐘 PostgresNitro11.944s (-14.5% 🟢)12.266s (-14.3% 🟢)0.321s81.01x
Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.136s (-9.8% 🟢)2.007s (~)0.870s151.00x
🐘 PostgresNitro1.137s (-10.8% 🟢)2.007s (~)0.870s151.00x
💻 LocalNitro1.172s (-28.2% 🟢)2.006s (-3.3%)0.834s151.03x
💻 LocalExpress1.183s (-20.6% 🟢)2.006s (~)0.823s151.04x
Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.192s (-49.3% 🟢)2.007s (-33.3% 🟢)0.815s151.00x
🐘 PostgresExpress1.224s (-48.2% 🟢)2.007s (-33.3% 🟢)0.783s151.03x
💻 LocalExpress1.703s (-42.3% 🟢)2.005s (-41.9% 🟢)0.303s151.43x
💻 LocalNitro1.704s (-45.8% 🟢)2.005s (-48.4% 🟢)0.302s151.43x
Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.305s (-62.5% 🟢)2.008s (-49.9% 🟢)0.702s151.00x
🐘 PostgresExpress1.324s (-62.0% 🟢)2.008s (-49.9% 🟢)0.684s151.01x
💻 LocalExpress4.638s (-44.4% 🟢)5.179s (-42.6% 🟢)0.541s63.55x
💻 LocalNitro4.910s (-41.2% 🟢)5.511s (-38.9% 🟢)0.601s63.76x
Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.155s (-8.1% 🟢)2.009s (~)0.854s151.00x
🐘 PostgresNitro1.163s (-7.5% 🟢)2.010s (~)0.847s151.01x
💻 LocalExpress1.386s (-26.8% 🟢)2.006s (-15.2% 🟢)0.620s151.20x
💻 LocalNitro1.388s (-25.6% 🟢)2.006s (-14.3% 🟢)0.618s151.20x
Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.199s (-48.8% 🟢)2.008s (-33.3% 🟢)0.810s151.00x
🐘 PostgresNitro1.199s (-48.7% 🟢)2.007s (-33.3% 🟢)0.808s151.00x
💻 LocalExpress1.828s (-41.6% 🟢)2.222s (-40.9% 🟢)0.394s141.53x
💻 LocalNitro1.935s (-36.9% 🟢)2.316s (-40.4% 🟢)0.381s131.61x
Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.305s (-62.7% 🟢)2.008s (-49.9% 🟢)0.702s151.00x
🐘 PostgresNitro1.309s (-62.4% 🟢)2.009s (-49.9% 🟢)0.700s151.00x
💻 LocalExpress5.446s (-38.1% 🟢)5.849s (-36.9% 🟢)0.403s64.17x
💻 LocalNitro5.557s (-39.2% 🟢)6.179s (-38.4% 🟢)0.622s64.26x
workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.418s (-50.1% 🟢)1.006s (-1.6%)0.588s601.00x
🐘 PostgresNitro0.459s (-44.0% 🟢)1.006s (~)0.547s601.10x
💻 LocalNitro0.468s (-52.2% 🟢)1.004s (-8.2% 🟢)0.535s601.12x
💻 LocalExpress0.469s (-52.4% 🟢)1.004s (-6.7% 🟢)0.535s601.12x
workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.047s (-47.0% 🟢)1.705s (-24.5% 🟢)0.659s531.00x
🐘 PostgresNitro1.066s (-44.7% 🟢)1.576s (-25.0% 🟢)0.510s581.02x
💻 LocalNitro1.185s (-61.0% 🟢)2.006s (-46.6% 🟢)0.821s451.13x
💻 LocalExpress1.191s (-60.5% 🟢)2.005s (-44.1% 🟢)0.815s451.14x
workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express2.030s (-49.1% 🟢)2.427s (-44.4% 🟢)0.397s501.00x
🐘 PostgresNitro2.128s (-48.2% 🟢)2.660s (-42.2% 🟢)0.532s461.05x
💻 LocalNitro2.704s (-70.9% 🟢)3.032s (-69.7% 🟢)0.328s401.33x
💻 LocalExpress2.719s (-70.5% 🟢)3.057s (-69.5% 🟢)0.338s401.34x
workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.163s (-42.4% 🟢)1.005s (~)0.843s601.00x
🐘 PostgresNitro0.178s (-37.0% 🟢)1.006s (~)0.827s601.10x
💻 LocalExpress0.455s (-18.8% 🟢)1.004s (~)0.550s602.80x
💻 LocalNitro0.469s (-22.4% 🟢)1.004s (-1.7%)0.535s602.89x
workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.286s (-43.9% 🟢)1.006s (~)0.720s901.00x
🐘 PostgresNitro0.295s (-40.5% 🟢)1.006s (~)0.711s901.03x
💻 LocalNitro2.205s (-13.1% 🟢)2.944s (-2.2%)0.738s317.71x
💻 LocalExpress2.226s (-11.4% 🟢)2.943s (-2.2%)0.717s317.78x
workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.582s (-28.9% 🟢)1.007s (-1.0%)0.425s1201.00x
🐘 PostgresNitro0.634s (-19.7% 🟢)1.006s (~)0.372s1201.09x
💻 LocalNitro10.021s (-10.5% 🟢)10.611s (-9.0% 🟢)0.590s1217.21x
💻 LocalExpress10.042s (-10.3% 🟢)10.694s (-10.4% 🟢)0.652s1217.25x
Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.132s (+468.5% 🔺)2.005s (+99.6% 🔺)0.011s (-13.2% 🟢)2.018s (+98.2% 🔺)0.886s101.00x
💻 LocalNitro1.133s (+430.4% 🔺)2.005s (+99.6% 🔺)0.011s (-15.2% 🟢)2.018s (+98.1% 🔺)0.885s101.00x
🐘 PostgresNitro1.135s (+453.6% 🔺)2.001s (+100.2% 🔺)0.001s (-20.0% 🟢)2.010s (+98.7% 🔺)0.875s101.00x
🐘 PostgresExpress1.135s (+453.5% 🔺)1.999s (+100.2% 🔺)0.001s (-25.0% 🟢)2.010s (+98.7% 🔺)0.875s101.00x
stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.492s (+136.8% 🔺)2.002s (+98.9% 🔺)0.003s (-30.4% 🟢)2.023s (+97.8% 🔺)0.531s301.00x
🐘 PostgresNitro1.519s (+143.4% 🔺)2.004s (+99.0% 🔺)0.004s (-2.5%)2.027s (+98.2% 🔺)0.507s301.02x
💻 LocalNitro1.707s (+103.5% 🔺)2.013s (+98.9% 🔺)0.009s (-4.3%)2.203s (+97.4% 🔺)0.496s281.14x
💻 LocalExpress1.923s (+154.0% 🔺)2.011s (+95.4% 🔺)0.009s (-8.2% 🟢)2.422s (+132.9% 🔺)0.499s251.29x
10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.627s (-34.7% 🟢)1.033s (-19.2% 🟢)0.000s (-20.7% 🟢)1.045s (-20.0% 🟢)0.418s581.00x
🐘 PostgresNitro0.662s (-31.7% 🟢)1.029s (-17.5% 🟢)0.000s (-17.2% 🟢)1.049s (-16.6% 🟢)0.387s581.05x
💻 LocalExpress1.365s (+11.5% 🔺)2.015s (~)0.000s (+40.0% 🔺)2.018s (~)0.652s302.18x
💻 LocalNitro1.561s (+27.6% 🔺)2.016s (~)0.000s (+364.3% 🔺)2.197s (+8.7% 🔺)0.636s282.49x
fan-out fan-in 10 streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.228s (-30.7% 🟢)1.869s (-14.2% 🟢)0.000s (NaN%)1.900s (-13.6% 🟢)0.673s321.00x
🐘 PostgresNitro1.325s (-26.1% 🟢)1.997s (-6.7% 🟢)0.000s (+86.7% 🔺)2.019s (-7.2% 🟢)0.694s301.08x
💻 LocalExpress3.158s (-8.9% 🟢)4.028s (~)0.001s (-33.3% 🟢)4.030s (~)0.873s152.57x
💻 LocalNitro3.187s (-5.9% 🟢)4.029s (~)0.000s (-75.0% 🟢)4.031s (~)0.844s152.60x

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalExpress12/21
🐘 PostgresExpress17/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres16/21
Nitro🐘 Postgres17/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.

@github-actions

github-actionsBot commented May 18, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

Some tests failed

Summary

PassedFailedSkippedTotal
❌ ▲ Vercel Production119642191419
✅ 💻 Local Development158702191806
✅ 📦 Local Production145802191677
❌ 🐘 Local Postgres158522191806
✅ 🪟 Windows12900129
✅ 📋 Other7270176903
Total6682610527740

❌ Failed Tests

▲ Vercel Production (4 failed)

astro (1 failed):

  • AbortController abortFromStepWorkflow: step abort cancels an in-flight sibling step

hono (2 failed):

  • outputStreamWorkflow no startIndex (reads all chunks)
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KRYMPWTNKF0CE4BP27X7R946 | 🔍 observability

nextjs-webpack (1 failed):

🐘 Local Postgres (2 failed)

nextjs-webpack-stable-lazy-discovery-disabled (1 failed):

  • DurableAgent e2e core basic text response

nextjs-webpack-stable-lazy-discovery-enabled (1 failed):

  • addTenWorkflow | wrun_01KRYMBT8QHFK9EZ9FDY03D9G0

Details by Category

❌ ▲ Vercel Production
AppPassedFailedSkipped
❌ astro102126
✅ example103026
✅ express103026
✅ fastify103026
❌ hono101226
✅ nextjs-turbopack12702
❌ nextjs-webpack12612
✅ nitro103026
✅ nuxt103026
✅ sveltekit12207
✅ vite103026
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable104025
✅ express-stable104025
✅ fastify-stable104025
✅ hono-stable104025
✅ nextjs-turbopack-canary110019
✅ nextjs-turbopack-stable-lazy-discovery-disabled12900
✅ nextjs-turbopack-stable-lazy-discovery-enabled12900
✅ nextjs-webpack-canary110019
✅ nextjs-webpack-stable-lazy-discovery-disabled12900
✅ nextjs-webpack-stable-lazy-discovery-enabled12900
✅ nitro-stable104025
✅ nuxt-stable104025
✅ sveltekit-stable12306
✅ vite-stable104025
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable104025
✅ express-stable104025
✅ fastify-stable104025
✅ hono-stable104025
✅ nextjs-turbopack-canary110019
✅ nextjs-turbopack-stable-lazy-discovery-disabled12900
✅ nextjs-webpack-canary110019
✅ nextjs-webpack-stable-lazy-discovery-disabled12900
✅ nextjs-webpack-stable-lazy-discovery-enabled12900
✅ nitro-stable104025
✅ nuxt-stable104025
✅ sveltekit-stable12306
✅ vite-stable104025
❌ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable104025
✅ express-stable104025
✅ fastify-stable104025
✅ hono-stable104025
✅ nextjs-turbopack-canary110019
✅ nextjs-turbopack-stable-lazy-discovery-disabled12900
✅ nextjs-turbopack-stable-lazy-discovery-enabled12900
✅ nextjs-webpack-canary110019
❌ nextjs-webpack-stable-lazy-discovery-disabled12810
❌ nextjs-webpack-stable-lazy-discovery-enabled12810
✅ nitro-stable104025
✅ nuxt-stable104025
✅ sveltekit-stable12306
✅ vite-stable104025
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack12900
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable104025
✅ e2e-local-dev-tanstack-start-104025
✅ e2e-local-postgres-nest-stable104025
✅ e2e-local-postgres-tanstack-start-104025
✅ e2e-local-prod-nest-stable104025
✅ e2e-local-prod-tanstack-start-104025
✅ e2e-vercel-prod-tanstack-start103026

📋 View full workflow run


Some E2E test jobs failed:

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

Check the workflow run for details.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a new "Versioning" Foundations page (v4 and v5) explaining default run pinning to deployments, recovery via cancel + rerun, opting into newer code with deploymentId: "latest", and carrying serializable state/streams across child-run continuations. Existing references to deploymentId: "latest" and versioning behavior are linked back to the new page. Cookbook pages also pick up callouts about long-lived / multi-turn patterns and, on v5 only, are updated to reflect that start() can now be called directly inside "use workflow" functions (via #1491), while v4 retains the step-wrapped pattern.

Changes:

  • New foundations/versioning.mdx for both v4 and v5, plus meta.json + index.mdx + linkbacks from vercel-world, start.mdx, and code-transform.mdx.
  • v5 cookbook + migration guides updated to drop "use step" wrappers around start() in favor of calling start() directly from the workflow function; v4 keeps the step-wrapped pattern.
  • Added "Versioning" callouts to scheduling, durable-agent, ai-sdk, chat-sdk, and sandbox cookbooks; fixed a few small wording/grammar issues in code-transform.mdx.

Reviewed changes

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

Show a summary per file
FileDescription
docs/content/docs/v5/foundations/versioning.mdxNew Foundations page explaining run pinning, recovery, and explicit upgrade boundaries.
docs/content/docs/v4/foundations/versioning.mdxv4 counterpart; uses step-wrapped continueDigest/continueExportOnLatest helpers.
docs/content/docs/v{4,5}/foundations/{meta.json,index.mdx}Surface the new Versioning page in nav and the foundations index.
docs/content/docs/v{4,5}/deploying/world/vercel-world.mdxLink the deployment-pinning section to the new Versioning page.
docs/content/docs/v{4,5}/how-it-works/code-transform.mdxLink "atomic versioning" reference; fix "function assume" / "from being upgraded" wording.
docs/content/docs/v{4,5}/api-reference/workflow-api/start.mdxSoften "Vercel-specific" to "Vercelism", mention possible version rename, link Versioning. v5 also notes native workflow-context start().
docs/content/docs/v5/foundations/starting-workflows.mdxNote v5 can call start() from workflows; link Composition + Versioning.
docs/content/docs/v5/cookbook/common-patterns/workflow-composition.mdxReplace step-wrapped child spawn with direct start() call.
docs/content/docs/v5/cookbook/advanced/child-workflows.mdxInline batched start() calls; rename spawnReportChunkstartReportChunk; update tips.
docs/content/docs/v{4,5}/cookbook/common-patterns/scheduling.mdxCallout linking to Versioning for long-lived schedules.
docs/content/docs/v{4,5}/cookbook/agent-patterns/durable-agent.mdxCallout linking to Versioning for multi-turn agents.
docs/content/docs/v{4,5}/cookbook/integrations/{ai-sdk,chat-sdk,sandbox}.mdxCallouts linking to Versioning for long-lived sessions.
docs/content/docs/v4/cookbook/common-patterns/workflow-composition.mdxUpdate deploymentId: "latest" callout wording + link to Versioning.
docs/content/docs/v4/cookbook/advanced/child-workflows.mdxLink Versioning from the deploymentId: "latest" tip.
docs/content/docs/v4/changelog/eager-processing.mdxReword to "step-wrapped start() helper" to match v4 phrasing.
docs/content/docs/v5/migration-guides/{migrating-from-trigger-dev,migrating-from-temporal,migrating-from-inngest,migrating-from-aws-step-functions}.mdxUpdate to v5 native workflow-context start(); only collect step retains "use step".

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

@TooTallNateTooTallNate left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Comment-only review

The new versioning foundations page is a useful addition — the four sections (default pinning → recovery → self-upgrade via start({ deploymentId: "latest" }) → carrying serializable context forward) cover the model clearly, and the v4-vs-v5 differentiation (step-wrapped start() vs direct start() from workflow context, gated on whether PR #1491 has landed on the target branch) is correctly handled. The cross-links from cookbook patterns to the new foundations page tie everything together nicely.

Three observations — see inline.

Inline comments

  1. Wording: this PR introduces "Vercelism" as a new term and uses it 6 times across the diff, including replacing existing "Vercel-specific feature" wording in two <Callout>s. "Vercelism" reads as informal slang and isn't part of the established docs vocabulary. The existing tone uses "Vercel-specific", "Vercel deployments", "Vercel World", "non-Vercel" — all precise. Suggested restoring the prior phrasing. This is the only thing I'd consider blocking.
  2. Broken link in v4: versioning.mdx references /docs/foundations/cancellation in its related frontmatter, but that page is v5-only. Easy fix.
  3. Missing changeset: convention for docs-only PRs is an empty ---\n--- file.

A few small things I noticed

  • The pre-emptively check for a conflict with getHookByToken() example (line 96 of versioning.mdx) — nice that you noted the race window in a later doc (#2011 callout), but this page doesn't have that warning. Worth a cross-link or <Callout type="warn"> here too, since the recovery pattern uses both start() and deploymentId: "latest" together.
  • The _idempotency / using syntax is great. Worth confirming the docs site's syntax highlighter renders it — I noticed #1988 recently fixed a homepage link lint regression, and the using syntax is TypeScript 5.2+ specific.
  • dailyDigest example (line 137-152): the state parameter is DigestState but the workflow doesn't actually use state.userId after the first sendDigest call — pattern is fine, just noting if you wanted to make the example illustrate state evolution more vividly, having sendDigest read state.lastSentAt (e.g. to avoid sending duplicates) would make the carry-forward intent clearer.

Overall the page reads well — once the Vercelism wording is restored and the v4 link is fixed, this should be good to go.

Comment threaddocs/content/docs/v5/api-reference/workflow-api/start.mdx Outdated
Comment threaddocs/content/docs/v4/foundations/versioning.mdx
Comment threaddocs/content/docs/v5/foundations/versioning.mdx

@TooTallNateTooTallNate left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

All three review comments addressed in 7eff96c — Vercelism wording reverted, v4 broken cancellation link fixed, empty changeset added. LGTM, approving.

@github-actions

Copy link
Copy Markdown
Contributor

Backport PR opened against stable: #2014. Merge conflicts were resolved by AI — please review carefully.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@pranaygp@TooTallNate