workflow 5.0.0-beta.8 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (262) hide show
  1. package/README.md +68 -23
  2. package/dist/api-workflow.d.ts +3 -1
  3. package/dist/api-workflow.d.ts.map +1 -1
  4. package/dist/api-workflow.js +2 -1
  5. package/dist/api.d.ts +5 -4
  6. package/dist/api.d.ts.map +1 -1
  7. package/dist/api.js +6 -7
  8. package/dist/index.d.ts +1 -0
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +6 -1
  11. package/dist/internal/builtins.d.ts +4 -4
  12. package/dist/internal/builtins.js +6 -6
  13. package/dist/internal/errors.d.ts +1 -1
  14. package/dist/internal/errors.d.ts.map +1 -1
  15. package/dist/internal/errors.js +2 -2
  16. package/dist/nest-builder.d.ts +2 -0
  17. package/dist/nest-builder.d.ts.map +1 -0
  18. package/dist/nest-builder.js +2 -0
  19. package/dist/nest-vercel-builder.d.ts +2 -0
  20. package/dist/nest-vercel-builder.d.ts.map +1 -0
  21. package/dist/nest-vercel-builder.js +2 -0
  22. package/dist/runtime.d.ts +2 -1
  23. package/dist/runtime.d.ts.map +1 -1
  24. package/dist/runtime.js +4 -1
  25. package/docs/advanced/dynamic-workflows.mdx +224 -0
  26. package/docs/ai/chat-session-modeling.mdx +176 -422
  27. package/docs/ai/defining-tools.mdx +6 -7
  28. package/docs/ai/human-in-the-loop.mdx +11 -11
  29. package/docs/ai/index.mdx +67 -72
  30. package/docs/ai/message-queueing.mdx +71 -110
  31. package/docs/ai/meta.json +1 -0
  32. package/docs/ai/resumable-streams.mdx +40 -28
  33. package/docs/ai/sleep-and-delays.mdx +10 -10
  34. package/docs/ai/streaming-updates-from-tools.mdx +6 -6
  35. package/docs/api-reference/index.mdx +25 -1
  36. package/docs/api-reference/meta.json +8 -0
  37. package/docs/api-reference/vitest/index.mdx +68 -15
  38. package/docs/api-reference/workflow/create-hook.mdx +166 -10
  39. package/docs/api-reference/workflow/create-webhook.mdx +16 -15
  40. package/docs/api-reference/workflow/define-hook.mdx +37 -33
  41. package/docs/api-reference/workflow/fatal-error.mdx +30 -8
  42. package/docs/api-reference/workflow/fetch.mdx +14 -10
  43. package/docs/api-reference/workflow/get-step-metadata.mdx +2 -2
  44. package/docs/api-reference/workflow/get-workflow-metadata.mdx +3 -3
  45. package/docs/api-reference/workflow/get-writable.mdx +7 -7
  46. package/docs/api-reference/workflow/index.mdx +4 -1
  47. package/docs/api-reference/workflow/retryable-error.mdx +1 -1
  48. package/docs/api-reference/workflow/set-attributes.mdx +63 -0
  49. package/docs/api-reference/workflow/sleep.mdx +4 -4
  50. package/docs/api-reference/workflow-ai/durable-agent.mdx +63 -101
  51. package/docs/api-reference/workflow-ai/index.mdx +5 -5
  52. package/docs/api-reference/workflow-ai/workflow-chat-transport.mdx +67 -24
  53. package/docs/api-reference/workflow-api/get-hook-by-token.mdx +28 -12
  54. package/docs/api-reference/workflow-api/get-run.mdx +43 -8
  55. package/docs/api-reference/workflow-api/index.mdx +8 -9
  56. package/docs/api-reference/workflow-api/register-lifecycle-hooks.mdx +87 -0
  57. package/docs/api-reference/workflow-api/resume-hook.mdx +73 -12
  58. package/docs/api-reference/workflow-api/resume-webhook.mdx +11 -9
  59. package/docs/api-reference/workflow-api/start.mdx +107 -12
  60. package/docs/api-reference/workflow-astro/index.mdx +18 -0
  61. package/docs/api-reference/workflow-astro/meta.json +4 -0
  62. package/docs/api-reference/workflow-astro/workflow.mdx +45 -0
  63. package/docs/api-reference/workflow-errors/entity-conflict-error.mdx +4 -4
  64. package/docs/api-reference/workflow-errors/hook-conflict-error.mdx +60 -0
  65. package/docs/api-reference/workflow-errors/hook-force-claimed-error.mdx +70 -0
  66. package/docs/api-reference/workflow-errors/hook-not-found-error.mdx +8 -8
  67. package/docs/api-reference/workflow-errors/index.mdx +91 -0
  68. package/docs/api-reference/workflow-errors/meta.json +7 -0
  69. package/docs/api-reference/workflow-errors/precondition-failed-error.mdx +68 -0
  70. package/docs/api-reference/workflow-errors/run-expired-error.mdx +2 -2
  71. package/docs/api-reference/workflow-errors/run-not-supported-error.mdx +58 -0
  72. package/docs/api-reference/workflow-errors/step-not-registered-error.mdx +5 -5
  73. package/docs/api-reference/workflow-errors/throttle-error.mdx +2 -2
  74. package/docs/api-reference/workflow-errors/too-early-error.mdx +2 -2
  75. package/docs/api-reference/workflow-errors/workflow-error.mdx +52 -0
  76. package/docs/api-reference/workflow-errors/workflow-not-registered-error.mdx +5 -6
  77. package/docs/api-reference/workflow-errors/workflow-run-cancelled-error.mdx +13 -6
  78. package/docs/api-reference/workflow-errors/workflow-run-failed-error.mdx +12 -5
  79. package/docs/api-reference/workflow-errors/workflow-run-not-completed-error.mdx +58 -0
  80. package/docs/api-reference/workflow-errors/workflow-run-not-found-error.mdx +4 -4
  81. package/docs/api-reference/workflow-errors/workflow-runtime-error.mdx +58 -0
  82. package/docs/api-reference/workflow-errors/workflow-world-error.mdx +8 -8
  83. package/docs/api-reference/workflow-globals.mdx +15 -11
  84. package/docs/api-reference/workflow-nest/configure-workflow-controller.mdx +37 -0
  85. package/docs/api-reference/workflow-nest/index.mdx +31 -0
  86. package/docs/api-reference/workflow-nest/meta.json +9 -0
  87. package/docs/api-reference/workflow-nest/nest-local-builder.mdx +64 -0
  88. package/docs/api-reference/workflow-nest/workflow-controller.mdx +46 -0
  89. package/docs/api-reference/workflow-nest/workflow-module.mdx +134 -0
  90. package/docs/api-reference/workflow-next/with-workflow.mdx +39 -17
  91. package/docs/api-reference/workflow-nitro/index.mdx +60 -0
  92. package/docs/api-reference/workflow-nuxt/index.mdx +48 -0
  93. package/docs/api-reference/workflow-observability/hydrate-data.mdx +35 -0
  94. package/docs/api-reference/workflow-observability/hydrate-resource-io.mdx +62 -0
  95. package/docs/api-reference/workflow-observability/index.mdx +62 -0
  96. package/docs/api-reference/workflow-observability/meta.json +11 -0
  97. package/docs/api-reference/workflow-observability/observability-revivers.mdx +50 -0
  98. package/docs/api-reference/workflow-observability/parse-class-name.mdx +41 -0
  99. package/docs/api-reference/workflow-observability/parse-step-name.mdx +40 -0
  100. package/docs/api-reference/workflow-observability/parse-workflow-name.mdx +55 -0
  101. package/docs/api-reference/workflow-runtime/create-world.mdx +39 -0
  102. package/docs/api-reference/workflow-runtime/get-world-handlers.mdx +44 -0
  103. package/docs/api-reference/{workflow-api → workflow-runtime}/get-world.mdx +11 -14
  104. package/docs/api-reference/workflow-runtime/health-check.mdx +51 -0
  105. package/docs/api-reference/workflow-runtime/index.mdx +41 -0
  106. package/docs/api-reference/workflow-runtime/meta.json +12 -0
  107. package/docs/api-reference/workflow-runtime/set-world.mdx +51 -0
  108. package/docs/api-reference/workflow-runtime/workflow-entrypoint.mdx +43 -0
  109. package/docs/api-reference/workflow-runtime/world/analytics.mdx +315 -0
  110. package/docs/api-reference/workflow-runtime/world/index.mdx +60 -0
  111. package/docs/api-reference/workflow-runtime/world/meta.json +4 -0
  112. package/docs/api-reference/workflow-runtime/world/queue.mdx +88 -0
  113. package/docs/api-reference/{workflow-api → workflow-runtime}/world/storage.mdx +104 -35
  114. package/docs/api-reference/{workflow-api → workflow-runtime}/world/streams.mdx +8 -8
  115. package/docs/api-reference/workflow-serde/index.mdx +1 -2
  116. package/docs/api-reference/workflow-serde/workflow-deserialize.mdx +3 -4
  117. package/docs/api-reference/workflow-serde/workflow-serialize.mdx +8 -8
  118. package/docs/api-reference/workflow-sveltekit/index.mdx +18 -0
  119. package/docs/api-reference/workflow-sveltekit/meta.json +4 -0
  120. package/docs/api-reference/workflow-sveltekit/workflow-plugin.mdx +42 -0
  121. package/docs/api-reference/workflow-vite/index.mdx +18 -0
  122. package/docs/api-reference/workflow-vite/meta.json +4 -0
  123. package/docs/api-reference/workflow-vite/workflow.mdx +48 -0
  124. package/docs/changelog/attributes-mvp.mdx +61 -46
  125. package/docs/changelog/batched-event-writes.mdx +79 -0
  126. package/docs/changelog/eager-processing.mdx +110 -436
  127. package/docs/changelog/index.mdx +4 -2
  128. package/docs/changelog/lazy-event-creation.md +127 -0
  129. package/docs/changelog/lazy-hook-resume.mdx +78 -0
  130. package/docs/changelog/meta.json +11 -1
  131. package/docs/changelog/resilient-resume.mdx +32 -0
  132. package/docs/changelog/resilient-start.mdx +33 -285
  133. package/docs/changelog/step-message-ownership.mdx +360 -0
  134. package/docs/changelog/turbo-mode.md +87 -0
  135. package/docs/comparisons/index.mdx +66 -0
  136. package/docs/comparisons/meta.json +11 -0
  137. package/docs/comparisons/workflow-sdk-vs-aws-agentcore.mdx +55 -0
  138. package/docs/comparisons/workflow-sdk-vs-aws-step-functions.mdx +111 -0
  139. package/docs/comparisons/workflow-sdk-vs-cloudflare-workflows.mdx +71 -0
  140. package/docs/comparisons/workflow-sdk-vs-inngest.mdx +102 -0
  141. package/docs/comparisons/workflow-sdk-vs-temporal.mdx +123 -0
  142. package/docs/comparisons/workflow-sdk-vs-trigger-dev.mdx +104 -0
  143. package/docs/configuration/build-and-diagnostics.mdx +79 -0
  144. package/docs/configuration/cli-and-web-ui.mdx +241 -0
  145. package/docs/configuration/framework-options.mdx +165 -0
  146. package/docs/configuration/index.mdx +32 -0
  147. package/docs/configuration/meta.json +12 -0
  148. package/docs/configuration/runtime-tuning.mdx +399 -0
  149. package/docs/configuration/worlds.mdx +315 -0
  150. package/docs/cookbook/advanced/child-workflows.mdx +33 -25
  151. package/docs/cookbook/advanced/publishing-libraries.mdx +65 -56
  152. package/docs/cookbook/advanced/serializable-steps.mdx +48 -68
  153. package/docs/cookbook/advanced/upgrading-workflows.mdx +35 -31
  154. package/docs/cookbook/agent-patterns/agent-cancellation.mdx +78 -60
  155. package/docs/cookbook/agent-patterns/durable-agent.mdx +23 -135
  156. package/docs/cookbook/agent-patterns/human-in-the-loop.mdx +180 -195
  157. package/docs/cookbook/common-patterns/batching.mdx +20 -14
  158. package/docs/cookbook/common-patterns/idempotency.mdx +41 -53
  159. package/docs/cookbook/common-patterns/rate-limiting.mdx +8 -4
  160. package/docs/cookbook/common-patterns/saga.mdx +23 -19
  161. package/docs/cookbook/common-patterns/scheduling.mdx +30 -22
  162. package/docs/cookbook/common-patterns/sequential-and-parallel.mdx +29 -25
  163. package/docs/cookbook/common-patterns/timeouts.mdx +26 -21
  164. package/docs/cookbook/common-patterns/webhooks.mdx +10 -6
  165. package/docs/cookbook/common-patterns/workflow-composition.mdx +27 -17
  166. package/docs/cookbook/index.mdx +22 -22
  167. package/docs/cookbook/integrations/ai-sdk.mdx +63 -48
  168. package/docs/cookbook/integrations/chat-sdk.mdx +46 -33
  169. package/docs/cookbook/integrations/sandbox.mdx +58 -45
  170. package/docs/deploying.mdx +106 -0
  171. package/docs/errors/abort-signal-timeout-in-workflow.mdx +16 -12
  172. package/docs/errors/corrupted-event-log.mdx +39 -18
  173. package/docs/errors/deployment-mismatch.mdx +71 -0
  174. package/docs/errors/fetch-in-workflow.mdx +15 -14
  175. package/docs/errors/hook-conflict.mdx +38 -11
  176. package/docs/errors/hook-force-claimed.mdx +96 -0
  177. package/docs/errors/index.mdx +24 -37
  178. package/docs/errors/node-js-module-in-workflow.mdx +9 -5
  179. package/docs/errors/replay-divergence.mdx +27 -0
  180. package/docs/errors/run-expired.mdx +85 -0
  181. package/docs/errors/runtime-decryption-failed.mdx +77 -0
  182. package/docs/errors/serialization-failed.mdx +44 -12
  183. package/docs/errors/start-invalid-workflow-function.mdx +9 -5
  184. package/docs/errors/step-executed-multiple-times.mdx +23 -0
  185. package/docs/errors/step-not-registered.mdx +6 -6
  186. package/docs/errors/timeout-in-workflow.mdx +12 -8
  187. package/docs/errors/webhook-invalid-respond-with-value.mdx +18 -18
  188. package/docs/errors/webhook-response-not-sent.mdx +20 -16
  189. package/docs/errors/workflow-not-registered.mdx +5 -5
  190. package/docs/foundations/cancellation.mdx +31 -32
  191. package/docs/foundations/errors-and-retries.mdx +54 -11
  192. package/docs/foundations/hooks.mdx +98 -35
  193. package/docs/foundations/idempotency.mdx +267 -12
  194. package/docs/foundations/index.mdx +1 -26
  195. package/docs/foundations/serialization.mdx +22 -22
  196. package/docs/foundations/starting-workflows.mdx +104 -30
  197. package/docs/foundations/streaming.mdx +108 -60
  198. package/docs/foundations/versioning.mdx +4 -4
  199. package/docs/foundations/workflows-and-steps.mdx +9 -9
  200. package/docs/getting-started/astro.mdx +22 -18
  201. package/docs/getting-started/express.mdx +15 -11
  202. package/docs/getting-started/fastify.mdx +15 -11
  203. package/docs/getting-started/hono.mdx +15 -11
  204. package/docs/getting-started/index.mdx +10 -3
  205. package/docs/getting-started/meta.json +3 -1
  206. package/docs/getting-started/nestjs.mdx +264 -21
  207. package/docs/getting-started/next.mdx +18 -14
  208. package/docs/getting-started/nitro.mdx +22 -18
  209. package/docs/getting-started/nuxt.mdx +15 -11
  210. package/docs/getting-started/python.mdx +190 -41
  211. package/docs/getting-started/react-router/index.mdx +33 -0
  212. package/docs/getting-started/react-router/meta.json +5 -0
  213. package/docs/getting-started/react-router/v7.mdx +237 -0
  214. package/docs/getting-started/react-router/v8.mdx +232 -0
  215. package/docs/getting-started/sveltekit.mdx +20 -16
  216. package/docs/getting-started/tanstack-start.mdx +17 -13
  217. package/docs/getting-started/vite.mdx +15 -11
  218. package/docs/how-it-works/cancellation.mdx +63 -63
  219. package/docs/how-it-works/code-transform.mdx +82 -66
  220. package/docs/how-it-works/encryption.mdx +30 -26
  221. package/docs/how-it-works/event-sourcing.mdx +132 -35
  222. package/docs/how-it-works/framework-integrations.mdx +96 -337
  223. package/docs/how-it-works/understanding-directives.mdx +22 -22
  224. package/docs/internal/index.mdx +6 -4
  225. package/docs/internal/meta.json +6 -1
  226. package/docs/internal/nitro-native-build.mdx +38 -0
  227. package/docs/internal/nitro-web-ui.mdx +24 -0
  228. package/docs/internal/serializable-abort-controller.mdx +7 -7
  229. package/docs/meta.json +4 -2
  230. package/docs/observability/attributes.mdx +136 -0
  231. package/docs/observability/index.mdx +32 -10
  232. package/docs/observability/lifecycle-hooks.mdx +95 -0
  233. package/docs/observability/meta.json +1 -1
  234. package/docs/observability/retention.mdx +95 -0
  235. package/docs/observability/tracing.mdx +124 -0
  236. package/docs/testing/index.mdx +120 -38
  237. package/docs/testing/server-based.mdx +10 -10
  238. package/docs/whats-new.mdx +190 -0
  239. package/docs/worlds/building-a-world.mdx +538 -0
  240. package/docs/worlds/local.mdx +129 -0
  241. package/docs/worlds/meta.json +10 -0
  242. package/docs/worlds/postgres.mdx +424 -0
  243. package/docs/worlds/upgrading-to-v5.mdx +162 -0
  244. package/docs/worlds/vercel.mdx +345 -0
  245. package/package.json +17 -14
  246. package/docs/api-reference/workflow-api/world/index.mdx +0 -58
  247. package/docs/api-reference/workflow-api/world/meta.json +0 -4
  248. package/docs/api-reference/workflow-api/world/observability.mdx +0 -164
  249. package/docs/api-reference/workflow-api/world/queue.mdx +0 -86
  250. package/docs/deploying/building-a-world.mdx +0 -251
  251. package/docs/deploying/index.mdx +0 -95
  252. package/docs/deploying/meta.json +0 -4
  253. package/docs/deploying/world/local-world.mdx +0 -84
  254. package/docs/deploying/world/meta.json +0 -4
  255. package/docs/deploying/world/postgres-world.mdx +0 -224
  256. package/docs/deploying/world/vercel-world.mdx +0 -181
  257. package/docs/migration-guides/index.mdx +0 -34
  258. package/docs/migration-guides/meta.json +0 -9
  259. package/docs/migration-guides/migrating-from-aws-step-functions.mdx +0 -358
  260. package/docs/migration-guides/migrating-from-inngest.mdx +0 -304
  261. package/docs/migration-guides/migrating-from-temporal.mdx +0 -313
  262. package/docs/migration-guides/migrating-from-trigger-dev.mdx +0 -328
@@ -0,0 +1,315 @@
1
+ ---
2
+ title: Worlds
3
+ description: Configure the Workflow backend that stores runs and delivers queue messages.
4
+ type: reference
5
+ summary: Select and configure Local, Postgres, Vercel, or custom Worlds.
6
+ related:
7
+ - /worlds/local
8
+ - /worlds/postgres
9
+ - /worlds/vercel
10
+ ---
11
+
12
+ A [World](/docs/deploying) stores workflow state and delivers queue messages.
13
+
14
+ ## Selecting a World
15
+
16
+ ### `WORKFLOW_TARGET_WORLD`
17
+
18
+ - Surface: environment variable
19
+ - Default: `local` outside Vercel; automatic Vercel World inside Vercel deployments
20
+ - Selects a non-default World module.
21
+
22
+ Outside Vercel, Workflow defaults to the Local World. On Vercel, leave `WORKFLOW_TARGET_WORLD` unset for the normal case; Workflow detects the Vercel deployment and selects the Vercel World automatically.
23
+
24
+ The World is selected when your app **runs**, from the environment of the process serving it, so changing `WORKFLOW_TARGET_WORLD` takes effect on the next start without a rebuild. Detection keys off `VERCEL_DEPLOYMENT_ID`, which Vercel sets in every deployed function and nothing else sets: with it, the Vercel World; without it, the Local World.
25
+
26
+ Broader signals are deliberately ignored. `vercel env pull` writes `VERCEL=1` into `.env.local`, so a dev server or a production server started on your own machine sees it while running against a writable filesystem, where the Local World is the right choice. Set `WORKFLOW_TARGET_WORLD=vercel` explicitly if you want such a process to talk to the Vercel World; starting a run then fails with an error naming the missing `VERCEL_DEPLOYMENT_ID`.
27
+
28
+ A deployment that pins `WORKFLOW_TARGET_WORLD=local` warns at startup and fails on its first write, because a Vercel deployment's filesystem is read-only.
29
+
30
+ A deployment can land on the Local World without pinning anything, and without that warning, if the project has cleared **Enable access to System Environment Variables** under **Settings**, then **Environment Variables**. That checkbox is what makes Vercel expose `VERCEL_DEPLOYMENT_ID` to your build and your functions; with it off, there is no signal to detect, so detection and the warning both see an ordinary non-Vercel process. See [System environment variables](/worlds/vercel#system-environment-variables) for how to confirm and fix it.
31
+
32
+ Set `WORKFLOW_TARGET_WORLD` only when you want to use a custom or self-hosted World:
33
+
34
+ - `local`: Alias for `@workflow/world-local`.
35
+ - `@workflow/world-postgres`: Postgres World package.
36
+ - `./my-world.ts`: Local module exporting a World, `createWorld()`, or a default factory.
37
+ - Any package specifier: Custom World package.
38
+
39
+ The `vercel` alias exists for manual selection and tooling, but deployed Vercel apps do not need to set it.
40
+
41
+ Export a configured World from a module when you need factory options instead of pure environment configuration:
42
+
43
+ ```typescript title="my-world.ts" lineNumbers
44
+ import { createWorld } from "@workflow/world-postgres";
45
+
46
+ export default createWorld({
47
+ connectionString: process.env.DATABASE_URL!,
48
+ jobPrefix: "myapp_",
49
+ });
50
+ ```
51
+
52
+ ```bash title=".env"
53
+ WORKFLOW_TARGET_WORLD="./my-world.ts"
54
+ ```
55
+
56
+ ## Local World
57
+
58
+ The Local World is the default outside Vercel and is intended for development.
59
+
60
+ ### `dataDir`
61
+
62
+ - Environment variable: `WORKFLOW_LOCAL_DATA_DIR`
63
+ - Default: `.workflow-data`
64
+ - Directory where runs, steps, events, hooks, streams, and the local manifest are written.
65
+
66
+ ### `baseUrl`
67
+
68
+ - Environment variable: `WORKFLOW_LOCAL_BASE_URL`
69
+ - Default: inferred from the app port
70
+ - Full base URL used when queue messages call back into the app.
71
+ - Overrides `port` and `PORT`.
72
+
73
+ ### `port`
74
+
75
+ - Environment variable: `PORT`
76
+ - Default: auto-detected
77
+ - Local app port used to build the callback URL when `baseUrl` is unset.
78
+
79
+ ### `WORKFLOW_LOCAL_QUEUE_CONCURRENCY`
80
+
81
+ - Factory option: none
82
+ - Default: `1000`
83
+ - Maximum number of concurrent local queue message handlers.
84
+
85
+ ### `WORKFLOW_LOCAL_QUEUE_MAX_VISIBILITY`
86
+
87
+ - Factory option: none
88
+ - Default: unlimited
89
+ - Maximum seconds a local queue message stays hidden before the handler rechecks the run.
90
+
91
+ ### `WORKFLOW_LOCAL_HEADERS_TIMEOUT_MS`
92
+
93
+ - Factory option: none
94
+ - Default: `0` (no deadline)
95
+ - Maximum milliseconds to wait for a local queue handler to begin responding before the durable message is redelivered. A value below your longest inline step re-executes that step while it is still running.
96
+
97
+ ### `WORKFLOW_LOCAL_BODY_TIMEOUT_MS`
98
+
99
+ - Factory option: none
100
+ - Default: `0` (no deadline)
101
+ - Maximum gap in milliseconds between response body chunks from a local queue handler before the durable message is redelivered.
102
+
103
+ ### `recoverActiveRuns`
104
+
105
+ - Environment variable: `WORKFLOW_LOCAL_RECOVER_ACTIVE_RUNS`
106
+ - Default: `true`
107
+ - Re-enqueues pending and running local runs when the World starts. Set the environment variable to `0` or `false` to skip recovery; the factory option wins when both are set.
108
+
109
+ ### `WORKFLOW_LOCAL_HOOK_RETENTION_LIMIT_DAYS`
110
+
111
+ - Factory option: none
112
+ - Default: `30`
113
+ - Maximum [`experimental_minRetention`](/docs/api-reference/workflow/create-hook#keep-a-token-unavailable-after-the-run-ends) accepted by the Local World, in days.
114
+ - Set this to the same limit as your production World so oversized values fail during local development.
115
+
116
+ ### `tag`
117
+
118
+ - Environment variable: none
119
+ - Default: unset
120
+ - Scopes local storage files to a tag, mainly for test isolation.
121
+
122
+ ### `streamFlushIntervalMs`
123
+
124
+ - Environment variable fallback: `WORKFLOW_STREAM_FLUSH_INTERVAL_MS`
125
+ - Default: `0` (dispatch the leading chunk of an idle stream immediately)
126
+ - Group-commit window for the leading chunk of an idle stream; a positive value trades first-chunk latency for larger groups. The `WORKFLOW_STREAM_FLUSH_INTERVAL_MS` environment variable, when set, overrides this option; otherwise the World option governs, including the first chunk.
127
+
128
+ ### `WORKFLOW_MAX_EVENTS`
129
+
130
+ - Default: `25000`
131
+ - Per-run event ceiling reported to the runtime. A run whose event log reaches it fails with `MAX_EVENTS_EXCEEDED`, bounding a runaway loop. See [`WORKFLOW_MAX_EVENTS_OVERRIDE`](/docs/configuration/runtime-tuning#workflow_max_events_override) for the runtime-side clamp.
132
+
133
+ ## Postgres World
134
+
135
+ The Postgres World is a self-hosted durable backend for long-running server processes.
136
+
137
+ ### `connectionString`
138
+
139
+ - Environment variable: `WORKFLOW_POSTGRES_URL`, then `DATABASE_URL`
140
+ - Default: `postgres://world:world@localhost:5432/world`
141
+ - PostgreSQL connection string used by the runtime World.
142
+ - The `bootstrap` migration command uses the same precedence.
143
+
144
+ ### `pool`
145
+
146
+ - Environment variable: none
147
+ - Default: new `pg.Pool`
148
+ - Existing `pg.Pool` to use instead of constructing one from `connectionString`.
149
+
150
+ ### `jobPrefix`
151
+
152
+ - Environment variable: `WORKFLOW_POSTGRES_JOB_PREFIX`
153
+ - Default: `workflow_`
154
+ - Prefix for Graphile Worker job names.
155
+
156
+ ### `queueConcurrency`
157
+
158
+ - Environment variable: `WORKFLOW_POSTGRES_WORKER_CONCURRENCY`
159
+ - Default: `50`
160
+ - Number of concurrent workers polling for jobs.
161
+ - Also bounds concurrent parent-to-child workflow return-value polls.
162
+
163
+ ### `applicationManagedShutdown`
164
+
165
+ - Environment variable: `WORKFLOW_POSTGRES_APPLICATION_MANAGED_SHUTDOWN` (`1` enables)
166
+ - Default: `false`
167
+ - Whether the application coordinates shutdown instead of Graphile Worker responding automatically.
168
+ - Set to `true` only when the application awaits `world.close()` before closing its workflow HTTP server and caller-owned pool.
169
+ - Prevents Graphile Worker's default handler from terminating the process before the application's remaining cleanup finishes.
170
+
171
+ ### `maxPoolSize`
172
+
173
+ - Environment variable: `WORKFLOW_POSTGRES_MAX_POOL_SIZE`
174
+ - Default: `pg` default
175
+ - Maximum size of the internal `pg.Pool` when the World creates the pool.
176
+
177
+ ### `WORKFLOW_POSTGRES_HOOK_RETENTION_LIMIT_DAYS`
178
+
179
+ - Factory option: none
180
+ - Default: `30`
181
+ - Maximum [`experimental_minRetention`](/docs/api-reference/workflow/create-hook#keep-a-token-unavailable-after-the-run-ends) accepted by the Postgres World, in days.
182
+ - Set this to the same limit as your production World so oversized values fail during development.
183
+
184
+ ### `namespace`
185
+
186
+ - Environment variable fallback: `WORKFLOW_QUEUE_NAMESPACE`
187
+ - Default: none
188
+ - Queue topic namespace. For example, `custom` changes `__wkf_*` topics to `__custom_wkf_*`.
189
+
190
+ ### `streamFlushIntervalMs`
191
+
192
+ - Environment variable fallback: `WORKFLOW_STREAM_FLUSH_INTERVAL_MS`
193
+ - Default: `0` (dispatch the leading chunk of an idle stream immediately)
194
+ - Group-commit window for the leading chunk of an idle stream; a positive value trades first-chunk latency for larger groups. The `WORKFLOW_STREAM_FLUSH_INTERVAL_MS` environment variable, when set, overrides this option; otherwise the World option governs, including the first chunk.
195
+
196
+ ## Vercel World
197
+
198
+ The Vercel World is configured automatically inside Vercel deployments. The platform provides the deployment ID, project ID, request authentication, queue integration, storage, and encryption material.
199
+
200
+ Most applications should not set `WORKFLOW_VERCEL_*` variables on Vercel. They configure tooling that talks to a Vercel Workflow project from outside a deployment, such as the Workflow CLI, the web user interface (UI), continuous integration (CI), or tests. The runtime warns if these variables are set in a deployed Vercel Function because they do not control runtime configuration there.
201
+
202
+ Platform-provided values such as `VERCEL_DEPLOYMENT_ID`, `VERCEL_PROJECT_ID`, and `VERCEL_DEPLOYMENT_KEY` are read by the runtime inside Vercel deployments. Do not set them yourself; keep [system environment variables](/worlds/vercel#system-environment-variables) enabled for the project so that Vercel provides them.
203
+
204
+ ### `token`
205
+
206
+ - Environment variable: `WORKFLOW_VERCEL_AUTH_TOKEN`, then `VERCEL_TOKEN`, then Vercel CLI login
207
+ - CLI flag: `--authToken`
208
+ - Default: inferred when possible
209
+ - Vercel API token for external tooling. Keep it secret.
210
+
211
+ ### `projectConfig.environment`
212
+
213
+ - Environment variable: `WORKFLOW_VERCEL_ENV`
214
+ - CLI flag: `--env` or `-e`
215
+ - Default: `production`
216
+ - Vercel environment targeted by tooling. Accepts `production` or `preview`.
217
+
218
+ ### `projectConfig.projectId`
219
+
220
+ - Environment variable: `WORKFLOW_VERCEL_PROJECT`
221
+ - CLI flag: `--project`
222
+ - Default: inferred from `.vercel/project.json` when possible
223
+ - Vercel project ID.
224
+
225
+ ### `projectConfig.teamId`
226
+
227
+ - Environment variable: `WORKFLOW_VERCEL_TEAM`
228
+ - CLI flag: `--team`
229
+ - Default: inferred from `.vercel/project.json` when possible
230
+ - Vercel team ID.
231
+
232
+ ### `WORKFLOW_VERCEL_PROJECT_NAME`
233
+
234
+ - Factory option: none
235
+ - CLI flag: none
236
+ - Default: inferred when possible
237
+ - Project slug used for dashboard links.
238
+
239
+ ### `WORKFLOW_VERCEL_BACKEND_URL`
240
+
241
+ - Factory option: none
242
+ - CLI flag: none
243
+ - Default: `https://api.vercel.com/v1/workflow`
244
+ - Workflow API proxy URL for external tooling.
245
+
246
+ ### `WORKFLOW_SEQUENTIAL_REPLAYS`
247
+
248
+ - Default: disabled
249
+ - Set `1` to serialize orchestrator (flow) invocations per run: each run's replays get their own queue topic and the flow trigger is generated with `maxConcurrency: 1`. Inline step executions get per-step topics and keep full parallelism.
250
+ - Read at **both build time and runtime**: set it as a project-level environment variable so the generated trigger and the runtime queue routing agree.
251
+ - Routing each run through a dedicated `maxConcurrency: 1` topic might lead to higher queue performance overhead. See [Vercel World](/worlds/vercel#workflow_sequential_replays) for details.
252
+
253
+ ### `VERCEL_WORKFLOW_SERVER_URL`
254
+
255
+ - Factory option: none
256
+ - CLI flag: none
257
+ - Default: unset
258
+ - Direct workflow-server URL override for testing or custom infrastructure. Normal deployments do not need it.
259
+
260
+ ### `VERCEL_QUEUE_MAX_DELAY_SECONDS`
261
+
262
+ - Factory option: none
263
+ - CLI flag: none
264
+ - Default: `82800` (23 hours)
265
+ - Maximum delay for one Vercel Queues continuation message when implementing `sleep()`.
266
+ - Longer sleeps schedule another continuation when the first one fires.
267
+
268
+ `VERCEL_QUEUE_MAX_DELAY_SECONDS` defaults to 23 hours because Vercel Queues message delays are capped by the message TTL, and the default TTL is 24 hours. Workflow stays inside that default and chains continuation messages for longer sleeps.
269
+
270
+ ### `WORKFLOW_REQUEST_TIMEOUT_MS`
271
+
272
+ - Factory option: none
273
+ - CLI flag: none
274
+ - Default: `60000`
275
+ - Clamp: `10000` to `120000` (values outside are clamped, with a warning)
276
+ - Per-request timeout for Vercel World HTTP calls to workflow-server.
277
+ - At the `10000` floor the run-status long poll disables itself, because its budget is this value minus 10s of headroom.
278
+
279
+ ### `WORKFLOW_MAX_CHUNKS_PER_REQUEST`
280
+
281
+ - Factory option: none
282
+ - CLI flag: none
283
+ - Default: `1000`
284
+ - Maximum stream chunks written in one Vercel World request. Larger batches are split.
285
+
286
+ ### `WORKFLOW_STREAMS_TRANSPORT`
287
+
288
+ - Factory option: none
289
+ - CLI flag: none
290
+ - Default: `http`
291
+ - Experimental stream-write transport capability. Set to exactly `ws` to attempt `workflow-stream-ws/v1`. The server authoritatively accepts or declines each upgrade; a decline uses HTTP directly for that writer lifetime. Stream reads remain HTTP and demand-driven.
292
+ - This is not tenant rollout policy or a package-version check. HTTP remains the compatibility path. `/websockets/v1` is independent of REST v2/v4 and persisted workflow `specVersion` values.
293
+
294
+ ### `WORKFLOW_DISABLE_ANALYTICS_READS`
295
+
296
+ - Factory option: none
297
+ - CLI flag: none
298
+ - Default: disabled
299
+ - Set `1` to turn off the World's metadata-only `analytics` read namespace, forcing `workflow inspect` and web UI list views onto strongly consistent primary storage. Intended for tests and tooling that read entities immediately after writing them.
300
+
301
+ ### `WORKFLOW_BATCH_TRANSITIONS`
302
+
303
+ - Surface: environment variable
304
+ - Default: on
305
+ - Set to `0` (or `false`) to **disable** batched event writes, the escape hatch that restores the exact prior one-write-per-event path.
306
+
307
+ When enabled (the default), a suspension's eager `step_created` and `wait_created` writes fold into batched `events.createBatch` calls (one durable write with per-event outcomes) on Worlds that implement the optional batch API. The fold only engages when the World implements `events.createBatch` (the Vercel World does; Local and Postgres do not), the run's spec version supports slot identity (≥ 6), and the suspension carries no attribute writes or resilient step dispatch. Hook writes in the same suspension go through the single-event path concurrently with the batch. Everything else keeps the single-event path unchanged, so disabling is only needed as an operational escape hatch. Batches are capped at 32 events; larger fan-outs commit in successive batches. See the [batched event writes changelog](/docs/changelog/batched-event-writes) for the World API contract.
308
+
309
+ ### `WORKFLOW_EVENTS_TRANSPORT`
310
+
311
+ - Factory option: none
312
+ - CLI flag: none
313
+ - Default: `http`
314
+ - Set to `ws` to ship workflow run events to the Vercel World over a WebSocket instead of one HTTP request each. Only `ws` (case-insensitive) opts in; any other value, including unset, empty, or `http`, keeps HTTP.
315
+ - Ignored when the World is configured with `projectConfig` and routes through the `api-workflow` proxy: that endpoint is an HTTP-only REST gateway and does not forward a WebSocket upgrade, so events stay on HTTP.
@@ -2,19 +2,26 @@
2
2
  title: Child Workflows
3
3
  description: Spawn child workflows from a parent and wait for completion via hook resume.
4
4
  type: guide
5
- summary: Orchestrate independent child workflows from a parent using start(), defineHook(), and startAndWait() — the child resumes the parent's hook when done instead of polling getRun().status.
5
+ summary: Orchestrate independent child workflows from a parent using start(), defineHook(), and startAndWait(). The child resumes the parent's hook when done instead of polling getRun().status.
6
+ related:
7
+ - /docs/api-reference/workflow-api/start
6
8
  ---
7
9
 
8
- Use child workflows when a single workflow needs to orchestrate many independent units of work. Each child runs as its own workflow with a separate event log, retry boundary, and failure scope -- if one child fails, it doesn't take down the parent or siblings.
10
+ <CopyPrompt
11
+ text="Refactor this workflow to use child workflows. Keep the parent as an exported `&quot;use workflow&quot;` function. Move independent units of durable work into separate exported child workflow functions. From the parent, call `start(childWorkflow, [args])` from `workflow/api` or the documented `startAndWait`/hook pattern where completion must resume the parent. Pass only serializable state to children. For fan-out, start children in parallel with `Promise.all` or bounded batches, collect run IDs, handle partial failures with `Promise.allSettled`, and use `getRun(runId)` when status, cancellation, streams, or return values are needed. Verify child start, completion, failure, and parent resume behavior."
12
+ />
13
+
14
+ Use child workflows when a single workflow needs to orchestrate many independent units of work. Each child runs as its own workflow with a separate event log, retry boundary, and failure scope. If one child fails, it doesn't take down the parent or siblings.
9
15
 
10
16
  ## When to use child workflows
11
17
 
12
18
  Child workflows are the right choice when:
13
19
 
14
- - **Work units are independent.** Each child can run without knowing about the others (e.g., processing individual documents, generating separate reports).
15
- - **You need isolated failure boundaries.** A failing child should not abort unrelated work. The parent decides how to handle failures.
16
- - **You want massive fan-out.** Spawning 50 or 500 children is practical because each runs on its own infrastructure.
17
- - **You need per-item observability.** Each child workflow has its own run ID, status, and event log for monitoring.
20
+ - **Work units are independent**: Each child can run without knowing about the others (for example, when processing individual documents or generating separate reports).
21
+ - **You need isolated failure boundaries**: A failing child should not abort unrelated work. The parent decides how to handle failures.
22
+ - **You want large fan-out**: Spawning 50 or 500 children is practical because each runs on its own infrastructure. The parent still pays for each spawn, so start them in chunks rather than all at once (see [Chunked spawning](#fan-out-pattern-chunked-spawning)).
23
+ - **You need per-item observability**: Each child workflow has its own run ID, status, and event log for monitoring.
24
+ - **One run would otherwise get too big**: A run's event log and step count are both capped, see [Vercel World limits](/worlds/vercel#per-run-limits). Replay reads the whole log, so split before the cap: a run headed for more than a few thousand events belongs in several runs.
18
25
 
19
26
  For simpler cases where steps share a single event log, use [direct await composition](/cookbook/common-patterns/workflow-composition#direct-await-flattening) instead.
20
27
 
@@ -22,7 +29,7 @@ For simpler cases where steps share a single event log, use [direct await compos
22
29
 
23
30
  The recommended pattern has four parts:
24
31
 
25
- 1. A **completion hook** the parent creates and awaits — zero compute while waiting
32
+ 1. A **completion hook** the parent creates and awaits, with zero compute while waiting
26
33
  2. A **wrapped child export** that runs the real child in try/catch/finally and resumes the parent's hook from a step in `finally`
27
34
  3. A **`start()` call** that spawns the wrapped child with the hook token (directly from the workflow in v5)
28
35
  4. A **`startAndWait()` helper** that ties the hook, spawn, and typed result together
@@ -142,12 +149,12 @@ export async function processDocumentBatch(documentIds: string[]) {
142
149
 
143
150
  Polling with `getRun().status` in a `sleep()` loop works, but hook resume is preferable because:
144
151
 
145
- - **Zero compute while waiting** — the parent suspends on the hook instead of waking every poll interval
146
- - **Immediate wake-up** — the parent resumes as soon as the child finishes, not on the next poll tick
147
- - **Typed payloads** — the child sends `{ status, value | error }` directly; no separate `returnValue` fetch step
148
- - **No worker-pool pressure** — `Run#returnValue` polling inside steps can hold worker slots while waiting for children (see [Eager Processing](/changelog/eager-processing))
152
+ - **Zero compute while waiting**: The parent suspends on the hook instead of waking every poll interval.
153
+ - **Immediate wake-up**: The parent resumes as soon as the child finishes, not on the next poll tick.
154
+ - **Typed payloads**: The child sends `{ status, value | error }` directly, with no separate `returnValue` fetch step.
155
+ - **No worker-pool pressure**: `Run#returnValue` polling inside steps can hold worker slots while waiting for children (see [Eager Processing](/docs/changelog/eager-processing)).
149
156
 
150
- When a parent calls a child workflow inline with `await` (flattened into the same run), the same wrapper and hook handshake still works — pass the token and `await processDocumentWithCompletion(...)` inside `startAndWait()` instead of calling `start()`.
157
+ When a parent calls a child workflow inline with `await` (flattened into the same run), the same wrapper and hook handshake still works: pass the token and `await processDocumentWithCompletion(...)` inside `startAndWait()` instead of calling `start()`.
151
158
 
152
159
  ## Fan-out pattern: chunked spawning
153
160
 
@@ -221,7 +228,7 @@ declare function withChildCompletionHook<TResult>(
221
228
 
222
229
  ### Tolerating partial failures
223
230
 
224
- Use `Promise.allSettled` with `startAndWait()` so one failing child doesn't abort siblings. The hook payload already carries `{ status: "failed", error }` — no status polling required.
231
+ Use `Promise.allSettled` with `startAndWait()` so one failing child doesn't abort siblings. The hook payload already carries `{ status: "failed", error }`, so no status polling is required.
225
232
 
226
233
  ```typescript
227
234
  import { start } from "workflow/api";
@@ -296,18 +303,19 @@ async function startAndWaitWithRetries(
296
303
 
297
304
  ## Tips
298
305
 
299
- - **`defineHook().resume()` must be called from a step.** The wrapped child's `finally` block calls a step that resumes the parent hook.
300
- - **Export wrapped children at module scope.** The SDK registers `"use workflow"` functions statically — a runtime higher-order function returned from `withChildCompletionHook()` cannot be passed to `start()`.
301
- - **Use stable hook keys** — document ID, job ID, or index — so parallel children inside one parent run don't collide on tokens.
302
- - **Use chunked spawning for large batches.** Starting 500 children at once can create a large burst of work. Break it into chunks of 10-50.
303
- - **Each child has its own retry semantics.** Steps inside child workflows retry independently. The parent sees the final `{ status, value | error }` payload from the hook.
304
- - **Use `deploymentId: "latest"`** if children should run on the most recent deployment. See [Versioning](/docs/foundations/versioning) for the full model and the [`start()` API reference](/docs/api-reference/workflow-api/start#using-deploymentid-latest) for compatibility considerations.
306
+ - **Call `defineHook().resume()` from a step**: The wrapped child's `finally` block calls a step that resumes the parent hook.
307
+ - **Export wrapped children at module scope**: The SDK registers `"use workflow"` functions statically, so a runtime higher-order function returned from `withChildCompletionHook()` cannot be passed to `start()`.
308
+ - **Use stable hook keys**: Document IDs, job IDs, or indexes prevent token collisions between parallel children in one parent run.
309
+ - **Use chunked spawning for large batches**: Starting 500 children at once can create a large burst of work. Break the work into chunks of 10–50.
310
+ - **Watch the parent's log too**: Each child bounds its own log, but the parent records events for spawning and for collecting every child, so the parent's log grows with the number of children. Count those events per child against the parent's own [run limits](/worlds/vercel#per-run-limits); when the parent alone would exceed them, add a layer, so each parent spawns a modest number of intermediate runs that in turn spawn the leaves.
311
+ - **Account for each child's retry semantics**: Steps inside child workflows retry independently. The parent sees the final `{ status, value | error }` payload from the hook.
312
+ - **Use `deploymentId: "latest"` when children should run on the most recent deployment**: See [Versioning](/docs/foundations/versioning) for the full model and the [`start()` API reference](/docs/api-reference/workflow-api/start#using-deploymentid-latest) for compatibility considerations.
305
313
 
306
314
  ## Key APIs
307
315
 
308
- - [`start()`](/docs/api-reference/workflow-api/start) -- spawn a new workflow run and get its run ID
309
- - [`defineHook()`](/docs/api-reference/workflow/define-hook) -- typed hook for parent/child completion handshakes
310
- - [`resumeHook()`](/docs/api-reference/workflow-api/resume-hook) -- resume a waiting parent from a step (called by the child wrapper)
311
- - [`getWorkflowMetadata()`](/docs/api-reference/workflow/get-workflow-metadata) -- read the parent run ID for deterministic hook tokens
312
- - [`"use workflow"`](/docs/foundations/workflows-and-steps) -- marks the orchestrator function
313
- - [`"use step"`](/docs/foundations/workflows-and-steps) -- marks functions with full Node.js access
316
+ - [`start()`](/docs/api-reference/workflow-api/start): Spawns a new workflow run and returns its run ID.
317
+ - [`defineHook()`](/docs/api-reference/workflow/define-hook): Defines a typed hook for parent-child completion handshakes.
318
+ - [`resumeHook()`](/docs/api-reference/workflow-api/resume-hook): Resumes a waiting parent from a step called by the child wrapper.
319
+ - [`getWorkflowMetadata()`](/docs/api-reference/workflow/get-workflow-metadata): Returns the parent run ID for deterministic hook tokens.
320
+ - [`"use workflow"`](/docs/foundations/workflows-and-steps): Marks the orchestrator function.
321
+ - [`"use step"`](/docs/foundations/workflows-and-steps): Marks functions with full Node.js access.