workflow 5.0.0-beta.5 → 5.0.0-beta.50
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.
- package/README.md +68 -23
- package/dist/api-workflow.d.ts +1 -1
- package/dist/api-workflow.d.ts.map +1 -1
- package/dist/api-workflow.js +1 -1
- package/dist/api.d.ts +3 -3
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +5 -7
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/internal/builtins.d.ts +20 -3
- package/dist/internal/builtins.d.ts.map +1 -1
- package/dist/internal/builtins.js +68 -4
- package/dist/internal/errors.d.ts +1 -1
- package/dist/internal/errors.d.ts.map +1 -1
- package/dist/internal/errors.js +2 -2
- package/dist/nest-builder.d.ts +2 -0
- package/dist/nest-builder.d.ts.map +1 -0
- package/dist/nest-builder.js +2 -0
- package/dist/nest-vercel-builder.d.ts +2 -0
- package/dist/nest-vercel-builder.d.ts.map +1 -0
- package/dist/nest-vercel-builder.js +2 -0
- package/dist/observability.d.ts +1 -1
- package/dist/observability.js +2 -2
- package/dist/runtime.d.ts +2 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +4 -1
- package/docs/ai/chat-session-modeling.mdx +29 -26
- package/docs/ai/defining-tools.mdx +6 -7
- package/docs/ai/human-in-the-loop.mdx +11 -11
- package/docs/ai/index.mdx +50 -45
- package/docs/ai/message-queueing.mdx +16 -16
- package/docs/ai/meta.json +1 -0
- package/docs/ai/resumable-streams.mdx +40 -28
- package/docs/ai/sleep-and-delays.mdx +10 -10
- package/docs/ai/streaming-updates-from-tools.mdx +6 -6
- package/docs/api-reference/index.mdx +24 -0
- package/docs/api-reference/meta.json +8 -0
- package/docs/api-reference/vitest/index.mdx +9 -15
- package/docs/api-reference/workflow/create-hook.mdx +89 -10
- package/docs/api-reference/workflow/create-webhook.mdx +16 -15
- package/docs/api-reference/workflow/define-hook.mdx +35 -33
- package/docs/api-reference/workflow/fatal-error.mdx +30 -8
- package/docs/api-reference/workflow/fetch.mdx +14 -10
- package/docs/api-reference/workflow/get-step-metadata.mdx +2 -2
- package/docs/api-reference/workflow/get-workflow-metadata.mdx +3 -3
- package/docs/api-reference/workflow/get-writable.mdx +7 -7
- package/docs/api-reference/workflow/index.mdx +4 -1
- package/docs/api-reference/workflow/retryable-error.mdx +1 -1
- package/docs/api-reference/workflow/set-attributes.mdx +61 -0
- package/docs/api-reference/workflow/sleep.mdx +4 -4
- package/docs/api-reference/workflow-ai/durable-agent.mdx +48 -86
- package/docs/api-reference/workflow-ai/index.mdx +3 -3
- package/docs/api-reference/workflow-ai/workflow-chat-transport.mdx +67 -24
- package/docs/api-reference/workflow-api/get-hook-by-token.mdx +26 -12
- package/docs/api-reference/workflow-api/get-run.mdx +43 -8
- package/docs/api-reference/workflow-api/index.mdx +6 -10
- package/docs/api-reference/workflow-api/resume-hook.mdx +73 -12
- package/docs/api-reference/workflow-api/resume-webhook.mdx +11 -9
- package/docs/api-reference/workflow-api/start.mdx +60 -13
- package/docs/api-reference/workflow-astro/index.mdx +18 -0
- package/docs/api-reference/workflow-astro/meta.json +4 -0
- package/docs/api-reference/workflow-astro/workflow.mdx +45 -0
- package/docs/api-reference/workflow-errors/entity-conflict-error.mdx +4 -4
- package/docs/api-reference/workflow-errors/hook-conflict-error.mdx +60 -0
- package/docs/api-reference/workflow-errors/hook-not-found-error.mdx +8 -8
- package/docs/api-reference/workflow-errors/index.mdx +88 -0
- package/docs/api-reference/workflow-errors/meta.json +6 -0
- package/docs/api-reference/workflow-errors/precondition-failed-error.mdx +68 -0
- package/docs/api-reference/workflow-errors/run-expired-error.mdx +2 -2
- package/docs/api-reference/workflow-errors/run-not-supported-error.mdx +58 -0
- package/docs/api-reference/workflow-errors/step-not-registered-error.mdx +5 -5
- package/docs/api-reference/workflow-errors/throttle-error.mdx +2 -2
- package/docs/api-reference/workflow-errors/too-early-error.mdx +2 -2
- package/docs/api-reference/workflow-errors/workflow-error.mdx +52 -0
- package/docs/api-reference/workflow-errors/workflow-not-registered-error.mdx +5 -6
- package/docs/api-reference/workflow-errors/workflow-run-cancelled-error.mdx +6 -6
- package/docs/api-reference/workflow-errors/workflow-run-failed-error.mdx +5 -5
- package/docs/api-reference/workflow-errors/workflow-run-not-completed-error.mdx +58 -0
- package/docs/api-reference/workflow-errors/workflow-run-not-found-error.mdx +4 -4
- package/docs/api-reference/workflow-errors/workflow-runtime-error.mdx +58 -0
- package/docs/api-reference/workflow-errors/workflow-world-error.mdx +8 -8
- package/docs/api-reference/workflow-globals.mdx +14 -10
- package/docs/api-reference/workflow-nest/configure-workflow-controller.mdx +33 -0
- package/docs/api-reference/workflow-nest/index.mdx +31 -0
- package/docs/api-reference/workflow-nest/meta.json +9 -0
- package/docs/api-reference/workflow-nest/nest-local-builder.mdx +64 -0
- package/docs/api-reference/workflow-nest/workflow-controller.mdx +40 -0
- package/docs/api-reference/workflow-nest/workflow-module.mdx +74 -0
- package/docs/api-reference/workflow-next/with-workflow.mdx +39 -17
- package/docs/api-reference/workflow-nitro/index.mdx +60 -0
- package/docs/api-reference/workflow-nuxt/index.mdx +48 -0
- package/docs/api-reference/workflow-observability/hydrate-data.mdx +35 -0
- package/docs/api-reference/workflow-observability/hydrate-resource-io.mdx +62 -0
- package/docs/api-reference/workflow-observability/index.mdx +62 -0
- package/docs/api-reference/workflow-observability/meta.json +11 -0
- package/docs/api-reference/workflow-observability/observability-revivers.mdx +50 -0
- package/docs/api-reference/workflow-observability/parse-class-name.mdx +41 -0
- package/docs/api-reference/workflow-observability/parse-step-name.mdx +40 -0
- package/docs/api-reference/workflow-observability/parse-workflow-name.mdx +55 -0
- package/docs/api-reference/workflow-runtime/create-world.mdx +39 -0
- package/docs/api-reference/workflow-runtime/get-world-handlers.mdx +44 -0
- package/docs/api-reference/{workflow-api → workflow-runtime}/get-world.mdx +11 -14
- package/docs/api-reference/workflow-runtime/health-check.mdx +50 -0
- package/docs/api-reference/workflow-runtime/index.mdx +41 -0
- package/docs/api-reference/workflow-runtime/meta.json +12 -0
- package/docs/api-reference/workflow-runtime/set-world.mdx +51 -0
- package/docs/api-reference/workflow-runtime/workflow-entrypoint.mdx +43 -0
- package/docs/api-reference/workflow-runtime/world/analytics.mdx +315 -0
- package/docs/api-reference/workflow-runtime/world/index.mdx +60 -0
- package/docs/api-reference/workflow-runtime/world/meta.json +4 -0
- package/docs/api-reference/workflow-runtime/world/queue.mdx +88 -0
- package/docs/api-reference/{workflow-api → workflow-runtime}/world/storage.mdx +98 -34
- package/docs/api-reference/{workflow-api → workflow-runtime}/world/streams.mdx +8 -8
- package/docs/api-reference/workflow-serde/index.mdx +1 -2
- package/docs/api-reference/workflow-serde/workflow-deserialize.mdx +3 -4
- package/docs/api-reference/workflow-serde/workflow-serialize.mdx +8 -8
- package/docs/api-reference/workflow-sveltekit/index.mdx +18 -0
- package/docs/api-reference/workflow-sveltekit/meta.json +4 -0
- package/docs/api-reference/workflow-sveltekit/workflow-plugin.mdx +42 -0
- package/docs/api-reference/workflow-vite/index.mdx +18 -0
- package/docs/api-reference/workflow-vite/meta.json +4 -0
- package/docs/api-reference/workflow-vite/workflow.mdx +48 -0
- package/docs/changelog/attributes-mvp.mdx +380 -0
- package/docs/changelog/batched-event-writes.mdx +79 -0
- package/docs/changelog/eager-processing.mdx +110 -436
- package/docs/changelog/index.mdx +4 -2
- package/docs/changelog/lazy-event-creation.md +127 -0
- package/docs/changelog/lazy-hook-resume.mdx +78 -0
- package/docs/changelog/meta.json +11 -1
- package/docs/changelog/resilient-resume.mdx +32 -0
- package/docs/changelog/resilient-start.mdx +33 -285
- package/docs/changelog/step-message-ownership.mdx +360 -0
- package/docs/changelog/turbo-mode.md +87 -0
- package/docs/comparisons/index.mdx +66 -0
- package/docs/comparisons/meta.json +11 -0
- package/docs/comparisons/workflow-sdk-vs-aws-agentcore.mdx +55 -0
- package/docs/comparisons/workflow-sdk-vs-aws-step-functions.mdx +111 -0
- package/docs/comparisons/workflow-sdk-vs-cloudflare-workflows.mdx +71 -0
- package/docs/comparisons/workflow-sdk-vs-inngest.mdx +102 -0
- package/docs/comparisons/workflow-sdk-vs-temporal.mdx +123 -0
- package/docs/comparisons/workflow-sdk-vs-trigger-dev.mdx +104 -0
- package/docs/configuration/build-and-diagnostics.mdx +70 -0
- package/docs/configuration/cli-and-web-ui.mdx +241 -0
- package/docs/configuration/framework-options.mdx +165 -0
- package/docs/configuration/index.mdx +32 -0
- package/docs/configuration/meta.json +12 -0
- package/docs/configuration/runtime-tuning.mdx +376 -0
- package/docs/configuration/worlds.mdx +313 -0
- package/docs/cookbook/advanced/child-workflows.mdx +211 -264
- package/docs/cookbook/advanced/meta.json +6 -1
- package/docs/cookbook/advanced/publishing-libraries.mdx +65 -56
- package/docs/cookbook/advanced/serializable-steps.mdx +28 -20
- package/docs/cookbook/advanced/upgrading-workflows.mdx +199 -0
- package/docs/cookbook/agent-patterns/agent-cancellation.mdx +27 -19
- package/docs/cookbook/agent-patterns/durable-agent.mdx +14 -142
- package/docs/cookbook/agent-patterns/human-in-the-loop.mdx +30 -22
- package/docs/cookbook/common-patterns/batching.mdx +18 -14
- package/docs/cookbook/common-patterns/idempotency.mdx +41 -53
- package/docs/cookbook/common-patterns/rate-limiting.mdx +8 -4
- package/docs/cookbook/common-patterns/saga.mdx +23 -19
- package/docs/cookbook/common-patterns/scheduling.mdx +34 -22
- package/docs/cookbook/common-patterns/sequential-and-parallel.mdx +29 -25
- package/docs/cookbook/common-patterns/timeouts.mdx +26 -21
- package/docs/cookbook/common-patterns/webhooks.mdx +10 -6
- package/docs/cookbook/common-patterns/workflow-composition.mdx +30 -27
- package/docs/cookbook/index.mdx +22 -21
- package/docs/cookbook/integrations/ai-sdk.mdx +85 -47
- package/docs/cookbook/integrations/chat-sdk.mdx +50 -33
- package/docs/cookbook/integrations/sandbox.mdx +62 -45
- package/docs/deploying.mdx +95 -0
- package/docs/errors/abort-signal-timeout-in-workflow.mdx +16 -12
- package/docs/errors/corrupted-event-log.mdx +29 -18
- package/docs/errors/deployment-mismatch.mdx +71 -0
- package/docs/errors/fetch-in-workflow.mdx +11 -7
- package/docs/errors/hook-conflict.mdx +69 -13
- package/docs/errors/index.mdx +2 -36
- package/docs/errors/node-js-module-in-workflow.mdx +9 -5
- package/docs/errors/replay-divergence.mdx +27 -0
- package/docs/errors/run-expired.mdx +85 -0
- package/docs/errors/runtime-decryption-failed.mdx +77 -0
- package/docs/errors/serialization-failed.mdx +44 -12
- package/docs/errors/start-invalid-workflow-function.mdx +9 -5
- package/docs/errors/step-executed-multiple-times.mdx +23 -0
- package/docs/errors/step-not-registered.mdx +6 -6
- package/docs/errors/timeout-in-workflow.mdx +12 -8
- package/docs/errors/webhook-invalid-respond-with-value.mdx +18 -18
- package/docs/errors/webhook-response-not-sent.mdx +20 -16
- package/docs/errors/workflow-not-registered.mdx +5 -5
- package/docs/foundations/cancellation.mdx +31 -32
- package/docs/foundations/errors-and-retries.mdx +42 -11
- package/docs/foundations/hooks.mdx +64 -35
- package/docs/foundations/idempotency.mdx +244 -12
- package/docs/foundations/index.mdx +1 -23
- package/docs/foundations/meta.json +2 -1
- package/docs/foundations/serialization.mdx +21 -22
- package/docs/foundations/starting-workflows.mdx +106 -30
- package/docs/foundations/streaming.mdx +107 -59
- package/docs/foundations/versioning.mdx +263 -0
- package/docs/foundations/workflows-and-steps.mdx +9 -9
- package/docs/getting-started/astro.mdx +22 -18
- package/docs/getting-started/express.mdx +15 -11
- package/docs/getting-started/fastify.mdx +15 -11
- package/docs/getting-started/hono.mdx +15 -11
- package/docs/getting-started/index.mdx +10 -3
- package/docs/getting-started/meta.json +3 -1
- package/docs/getting-started/nestjs.mdx +87 -20
- package/docs/getting-started/next.mdx +22 -16
- package/docs/getting-started/nitro.mdx +22 -18
- package/docs/getting-started/nuxt.mdx +15 -11
- package/docs/getting-started/python.mdx +135 -40
- package/docs/getting-started/react-router/index.mdx +33 -0
- package/docs/getting-started/react-router/meta.json +5 -0
- package/docs/getting-started/react-router/v7.mdx +237 -0
- package/docs/getting-started/react-router/v8.mdx +232 -0
- package/docs/getting-started/sveltekit.mdx +20 -16
- package/docs/getting-started/tanstack-start.mdx +17 -13
- package/docs/getting-started/vite.mdx +15 -11
- package/docs/how-it-works/cancellation.mdx +63 -63
- package/docs/how-it-works/code-transform.mdx +83 -67
- package/docs/how-it-works/encryption.mdx +30 -26
- package/docs/how-it-works/event-sourcing.mdx +98 -34
- package/docs/how-it-works/framework-integrations.mdx +96 -337
- package/docs/how-it-works/understanding-directives.mdx +22 -22
- package/docs/internal/index.mdx +6 -4
- package/docs/internal/meta.json +6 -1
- package/docs/internal/nitro-native-build.mdx +38 -0
- package/docs/internal/nitro-web-ui.mdx +24 -0
- package/docs/internal/serializable-abort-controller.mdx +7 -7
- package/docs/meta.json +3 -2
- package/docs/observability/attributes.mdx +134 -0
- package/docs/observability/index.mdx +32 -10
- package/docs/observability/meta.json +1 -1
- package/docs/observability/retention.mdx +93 -0
- package/docs/observability/tracing.mdx +124 -0
- package/docs/testing/index.mdx +36 -36
- package/docs/testing/server-based.mdx +10 -10
- package/docs/whats-new.mdx +186 -0
- package/package.json +17 -14
- package/docs/api-reference/workflow-api/world/index.mdx +0 -58
- package/docs/api-reference/workflow-api/world/meta.json +0 -4
- package/docs/api-reference/workflow-api/world/observability.mdx +0 -164
- package/docs/api-reference/workflow-api/world/queue.mdx +0 -86
- package/docs/deploying/building-a-world.mdx +0 -251
- package/docs/deploying/index.mdx +0 -95
- package/docs/deploying/meta.json +0 -4
- package/docs/deploying/world/local-world.mdx +0 -84
- package/docs/deploying/world/meta.json +0 -4
- package/docs/deploying/world/postgres-world.mdx +0 -224
- package/docs/deploying/world/vercel-world.mdx +0 -179
- package/docs/migration-guides/index.mdx +0 -34
- package/docs/migration-guides/meta.json +0 -9
- package/docs/migration-guides/migrating-from-aws-step-functions.mdx +0 -363
- package/docs/migration-guides/migrating-from-inngest.mdx +0 -314
- package/docs/migration-guides/migrating-from-temporal.mdx +0 -318
- package/docs/migration-guides/migrating-from-trigger-dev.mdx +0 -337
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Runtime tuning
|
|
3
|
+
description: Runtime environment variables for replay, inline execution, queue delivery, compression, tracing, and advanced limits.
|
|
4
|
+
type: reference
|
|
5
|
+
summary: Tune Workflow runtime behavior where workflows execute.
|
|
6
|
+
related:
|
|
7
|
+
- /docs/configuration/worlds
|
|
8
|
+
- /docs/how-it-works/event-sourcing
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
The runtime reads these variables where workflows execute. Set them on the deployment or dev server.
|
|
12
|
+
|
|
13
|
+
## Client polling
|
|
14
|
+
|
|
15
|
+
### `WORKFLOW_RETURN_VALUE_POLL_INTERVAL_MS`
|
|
16
|
+
|
|
17
|
+
- Default: `1000`
|
|
18
|
+
- Minimum: `1`
|
|
19
|
+
- Delay between status requests made by [`Run.returnValue`](/docs/api-reference/workflow-api/get-run) while a workflow run is not yet complete.
|
|
20
|
+
- Increase it to reduce polling traffic at the cost of noticing completion later.
|
|
21
|
+
- This variable is read by the process awaiting `Run.returnValue`, such as an E2E test runner, rather than by the workflow deployment.
|
|
22
|
+
- Applies whenever the World cannot hold a read open. When it can, the wait below replaces most of this polling and the interval only paces retries.
|
|
23
|
+
|
|
24
|
+
### `WORKFLOW_RETURN_VALUE_WAIT_MS`
|
|
25
|
+
|
|
26
|
+
- Default: `50000`
|
|
27
|
+
- Minimum: `1`
|
|
28
|
+
- How long a single wait for a terminal run status may block, when the World supports waiting (`world.runs.waitForTerminalStatus()`). `Run.returnValue` re-issues the wait until the run finishes, so this bounds one request rather than the total wait.
|
|
29
|
+
- `50000` is the largest value the Vercel World can actually request: it clamps the ask to its 60s per-request HTTP timeout minus 10s of headroom, so the budget always expires as a response carrying the run's current status rather than as a client-side timeout. Raising this alone has no effect; raise `WORKFLOW_REQUEST_TIMEOUT_MS` as well.
|
|
30
|
+
- Read by the process awaiting `Run.returnValue`, like the interval above.
|
|
31
|
+
|
|
32
|
+
### `WORKFLOW_RETURN_VALUE_MAX_LONG_POLLS`
|
|
33
|
+
|
|
34
|
+
- Default: `10`
|
|
35
|
+
- Minimum: `1`
|
|
36
|
+
- How many consecutive waits `Run.returnValue` issues before falling back to interval polling for the rest of the await.
|
|
37
|
+
- It never ends the await. A run that outlives the cap continues waiting on `WORKFLOW_RETURN_VALUE_POLL_INTERVAL_MS` instead.
|
|
38
|
+
- Runs longer than roughly `WORKFLOW_RETURN_VALUE_MAX_LONG_POLLS` x `WORKFLOW_RETURN_VALUE_WAIT_MS` therefore spend most of their life interval polling, which costs more requests than continuing to wait would. Raise it if you routinely await long runs.
|
|
39
|
+
- Read by the process awaiting `Run.returnValue`, like the interval above.
|
|
40
|
+
|
|
41
|
+
### `WORKFLOW_RETURN_VALUE_LONG_POLL`
|
|
42
|
+
|
|
43
|
+
- Default: enabled
|
|
44
|
+
- Set to `0` or `false` to stop `Run.returnValue` from waiting and restore fixed-interval polling on `WORKFLOW_RETURN_VALUE_POLL_INTERVAL_MS` exactly.
|
|
45
|
+
- The kill switch for the wait. Worlds that do not implement waiting are already on the interval path, so this changes nothing for them.
|
|
46
|
+
- Read by the process awaiting `Run.returnValue`, like the interval above.
|
|
47
|
+
|
|
48
|
+
## Replay and queue delivery
|
|
49
|
+
|
|
50
|
+
### `WORKFLOW_REPLAY_TIMEOUT_MS`
|
|
51
|
+
|
|
52
|
+
- Default: `240000`
|
|
53
|
+
- Clamp: `30000` to `780000`
|
|
54
|
+
- Charged time budget for replay and orchestration work in one handler invocation.
|
|
55
|
+
- Covers loading events, re-running the workflow function, resolving suspensions, and scheduling follow-up work.
|
|
56
|
+
- Does not include time spent inside inline `"use step"` bodies. Steps are bounded by the platform function duration instead.
|
|
57
|
+
|
|
58
|
+
For example, a workflow can run a 10-minute inline step even with `WORKFLOW_REPLAY_TIMEOUT_MS=300000`, because the replay budget is paused while the step body runs.
|
|
59
|
+
|
|
60
|
+
### `WORKFLOW_REPLAY_TIMEOUT_MAX_RETRIES`
|
|
61
|
+
|
|
62
|
+
- Default: `3`
|
|
63
|
+
- Queue deliveries that may hit the replay timeout before the run is failed with `REPLAY_TIMEOUT`.
|
|
64
|
+
|
|
65
|
+
### `WORKFLOW_MAX_QUEUE_DELIVERIES`
|
|
66
|
+
|
|
67
|
+
- Default: `48`
|
|
68
|
+
- Delivery attempts before a run or step is failed gracefully.
|
|
69
|
+
- Can only be lowered. Workflow calibrates the default to record failure before the queue expires the message.
|
|
70
|
+
|
|
71
|
+
### `WORKFLOW_MAX_EVENTS`
|
|
72
|
+
|
|
73
|
+
- Default: `25000`
|
|
74
|
+
- Positive-integer event limit reported by the Local World and enforced by the runtime as `MAX_EVENTS_EXCEEDED`.
|
|
75
|
+
- The Local and Postgres Worlds also use it as the maximum number of events returned when `events.list()` is called without a limit. If more events exist, the response includes `hasMore: true` and a continuation cursor.
|
|
76
|
+
- The Vercel World receives its event limit from the service; this environment variable does not override that service-owned value.
|
|
77
|
+
- Invalid or non-positive values fall back to the default.
|
|
78
|
+
|
|
79
|
+
### `WORKFLOW_REPLAY_DIVERGENCE_MAX_RETRIES`
|
|
80
|
+
|
|
81
|
+
- Default: `3`
|
|
82
|
+
- Recovery replays before replay divergence is recorded as corruption.
|
|
83
|
+
|
|
84
|
+
### `WORKFLOW_DEPLOYMENT_MISMATCH_MAX_RETRIES`
|
|
85
|
+
|
|
86
|
+
- Default: `3`
|
|
87
|
+
- Times a delivery that reached a deployment other than the one its run is pinned to is re-routed to that deployment before the run is failed with [`DEPLOYMENT_MISMATCH`](/docs/errors/deployment-mismatch).
|
|
88
|
+
- Re-routed deliveries back off exponentially (1s, 2s, 4s). Set to `0` to fail the run on the first misrouted delivery.
|
|
89
|
+
- Only applies to Worlds with atomic, immutable deployments (the Vercel World). A run whose pinned deployment cannot be reached at all fails immediately regardless of this value.
|
|
90
|
+
- Transient or unknown queue publishing failures use normal queue redelivery and do not consume this budget.
|
|
91
|
+
|
|
92
|
+
### `WORKFLOW_RESILIENT_STEP_DISPATCH`
|
|
93
|
+
|
|
94
|
+
- Default: disabled
|
|
95
|
+
- When a suspension hands newly created steps to the queue, the runtime publishes each step's execution message in parallel with its `step_created` event write instead of sequencing them, cutting a round trip per dispatched step. The message also carries the serialized step input (`stepInput`), so a transient `step_created` write failure (429 / 5xx / transport) still executes the step. The queue consumer idempotently re-ensures the event before running it, converging with the producer's write on the step's correlation ID. This mirrors resilient start (`runInput`) and the legacy lazy hook resume's `hookInput` (which current producers no longer send; see [durable hook resume](/docs/changelog/lazy-hook-resume)).
|
|
96
|
+
- It is off by default because the publish races the create's verdict, and a create can come back refused: as a duplicate this replay should stop pursuing, or as a [stale write](#stale-reads-and-why-nothing-has-to-be-rejected) on a World that refuses rather than reports. Either way the message carrying the payload is already out, so the consumer can materialize a step whose create was refused, and nothing orders the verdict before the consumer's redelivery re-ensure. The sequential path is the only one that gives the message a happens-after edge over it.
|
|
97
|
+
- Even when enabled, the runtime falls back to the sequential create-then-publish dispatch when the step input is too large to inline on the queue message, or when the run's queue transport cannot carry binary payloads (pre-CBOR spec versions).
|
|
98
|
+
- Producer-side recoveries are reported on the suspension span as `workflow.step.resilient_dispatch_recovered`; a consumer that materialized the event reports `workflow.step.resilient_dispatch_materialized`.
|
|
99
|
+
- Set `1` to enable it.
|
|
100
|
+
|
|
101
|
+
### Stale reads, and why nothing has to be rejected
|
|
102
|
+
|
|
103
|
+
- Not a variable: this is how a replay working from an out-of-date event log stays correct, and why no World needs a precondition guard to make it so.
|
|
104
|
+
- Three properties work together. A reader's log is always a **prefix** of the run's log, never a prefix with a hole in it. The World allocates positions at commit, so nothing lands behind a position a reader has already passed. Replay is **deterministic on a prefix**: the same prefix always yields the same decisions, so a shorter log does not mean a different run, only a run that has not caught up. Every write **reports what it missed**: a creation names the position it replayed from (`eventCount`), and the World returns the events occupying the positions it was pushed past. The replay merges those and continues, correcting itself on the write rather than on a read.
|
|
105
|
+
- So a stale replay costs a merge, not a rejection. None of the shipped Worlds refuses a write for being stale.
|
|
106
|
+
- A World *may* refuse instead, with 412 ([`PreconditionFailedError`](/docs/api-reference/workflow-errors/precondition-failed-error)). This is appropriate when it allocates positions somewhere other than the commit and cannot report a gap reliably. The runtime restarts the replay in the same invocation from a corrected event log and falls back to a re-invocation with a fresh replay after spending the restart budget. It never retries the rejected write as-is because a replay working from a corrected log derives different events.
|
|
107
|
+
- A World that does refuse should only ever do so on evidence, and accept the write in every other case. A rejection then always means the position was stale, while the absence of one proves nothing about currency.
|
|
108
|
+
- Two runtime behaviors follow from the properties above rather than from any fence. The per-step event-log delta optimization (consuming the delta returned by a step's terminal write instead of issuing an extra `events.list` per step) stays active while the run has an open hook. A `hook_received` event missed by the delta window is observed one iteration later, and the next write brings it back. While a hook is open, inline steps take the await-then-run path even when optimistic inline start is enabled. Several invocations race for one step's claim there, and awaiting it means the body runs only for the writer that won.
|
|
109
|
+
|
|
110
|
+
### `WORKFLOW_SLOT_GAP_CHECK`
|
|
111
|
+
|
|
112
|
+
- Default: enabled
|
|
113
|
+
- A replay checks that the [event log](/docs/how-it-works/event-sourcing#event-ids) it loaded is dense before it runs, and fails the run with [`CORRUPTED_EVENT_LOG`](/docs/errors/corrupted-event-log) when a position below the log's highest holds no event. A log missing only its first position, meaning a run whose `run_created` is still being written, is left alone.
|
|
114
|
+
- A position can be briefly empty while the write that occupies it is still committing, so the check re-reads the log a few times before it decides, and the replay continues from whichever log it settled on.
|
|
115
|
+
- The check trades one failure for another. Most holes stand for an event that never happened, and replaying past those is correct. A hole standing for an event that did happen looks identical, and replaying past that one produces a run whose result is silently wrong. Failing is the recoverable side of that trade.
|
|
116
|
+
- Set `0` to replay across holes instead.
|
|
117
|
+
|
|
118
|
+
### `WORKFLOW_SEALED_LOG`
|
|
119
|
+
|
|
120
|
+
- Default: enabled
|
|
121
|
+
- New runs are created at the sealed-log spec version, in which the World's backend assigns each event its position *before* the write commits rather than letting concurrent writers race for one. Concurrent writes then never contend for a position, which is what makes a wide fan-out cheap.
|
|
122
|
+
- The price of assigning positions in advance is that a writer which claims one and then dies leaves a position no writer will ever fill. The backend closes such a position by writing a `noop` event into it once it can prove the position was abandoned, so a reader still sees the dense log it needs. Replay steps over a `noop` without delivering it to the workflow or advancing the deterministic clock. Its timestamp belongs to whichever reader sealed it, not to the run.
|
|
123
|
+
- Set `0` to put a deployment back on the previous scheme, where each position is allocated by the write that occupies it. Use this as the kill switch if position assignment turns out to be at fault for event-log problems.
|
|
124
|
+
- Existing runs are unaffected either way. A run's spec version is stamped once, at creation, and read from the run for the rest of its life, so flipping this changes only what *new* runs get, and a run in flight keeps the scheme it started on. Every build reads sealed logs regardless of the setting.
|
|
125
|
+
- A run created at the sealed-log version can only be replayed by a reader that knows to skip `noop` events. That includes every runtime on this release train, but a runtime that pins its own accepted spec range separately, such as the Python runtime, has to catch up before it can read these runs. Switch this off in an environment where it has not.
|
|
126
|
+
- Only the Vercel World seals. The Local and Postgres Worlds allocate each position at the commit that occupies it, so they cannot leave a hole and never write a `noop`; the setting still moves the version they stamp, so the fleet stays on one spec.
|
|
127
|
+
|
|
128
|
+
### `WORKFLOW_PRECONDITION_MAX_INPROCESS_RESTARTS`
|
|
129
|
+
|
|
130
|
+
- Default: `3`
|
|
131
|
+
- How many times a single invocation restarts its replay in-process after an event creation is [rejected as stale](#stale-reads-and-why-nothing-has-to-be-rejected) before it falls back to a re-invocation. No shipped World rejects one, so this budget is reserved for a World that chooses to.
|
|
132
|
+
- A restart reloads the event log and rebuilds the workflow from scratch, so it costs a replay but no queue round trip. A World may attach the missing events to its rejection, in which case the first restart needs no event-log request at all.
|
|
133
|
+
|
|
134
|
+
### `WORKFLOW_PRECONDITION_MAX_REINVOCATIONS`
|
|
135
|
+
|
|
136
|
+
- Default: `5`
|
|
137
|
+
- How many re-invocations one run may spend on rejected event creations before it is failed with `RUNTIME_ERROR`.
|
|
138
|
+
- Counted on the run's queue messages rather than per invocation, because a re-invocation enqueues a fresh message and so restarts the ordinary delivery count. Without this budget a run whose event log keeps growing faster than it can be read would cycle indefinitely.
|
|
139
|
+
|
|
140
|
+
### `WORKFLOW_PRECONDITION_REINVOKE_DELAY_SECONDS`
|
|
141
|
+
|
|
142
|
+
- Default: `2`
|
|
143
|
+
- Delay before a re-invocation caused by a rejected event creation.
|
|
144
|
+
- Unlike an in-process restart, which re-reads immediately, a re-invocation only happens after the in-process budget fails to catch up. The delay gives the other writers time to quiesce.
|
|
145
|
+
|
|
146
|
+
### `WORKFLOW_LOG_ORDER_DRAWS`
|
|
147
|
+
|
|
148
|
+
- Default: enabled
|
|
149
|
+
- Experimental. Pins correlation-ID draw order to event-log order. A branch-deciding delivery (a step result, hook payload, or wait completion) resolves to the workflow only after every earlier-in-log delivery's continuation has fully quiesced, and never ahead of a lower-slot delivery that is committed to happening.
|
|
150
|
+
- Without it, a delivery that resolves while an earlier delivery's continuation is still a few microtask hops from its next step/hook/wait call can overtake it on the run's shared correlation-ID sequence. Draw order, and therefore correlation IDs, then depends on how much of the event log a replay had loaded. Two concurrent replays holding different-length prefixes can bind one ID to two different entities, failing the run with `CORRUPTED_EVENT_LOG`.
|
|
151
|
+
- Costs one event-loop turn (roughly 15 to 20 microseconds via `setImmediate`) per branch-deciding delivery during replay, and more when continuations genuinely overlap. Measurements on a 100-step sequential replay show about 2 ms added end to end.
|
|
152
|
+
- Only applies to the default Node.js VM engine. `WORKFLOW_VM=quickjs` has its own event feed and correlation-ID sequence and is unaffected by this setting.
|
|
153
|
+
- Correlation IDs of runs created before the setting changed are not affected on platforms where a run keeps replaying on the deployment it started on. Elsewhere, only change it while no runs are in flight.
|
|
154
|
+
- Set `0` to opt back into arrival-order delivery resolution. Only the literal value `0` opts out; `false` or `off` leave it enabled.
|
|
155
|
+
|
|
156
|
+
## Inline execution
|
|
157
|
+
|
|
158
|
+
### `WORKFLOW_V2_TIMEOUT_MS`
|
|
159
|
+
|
|
160
|
+
- Default: derived from the runtime deadline. The value is `600000` when the invocation has 25 minutes or more left, `300000` when it has 10 minutes or more, and `120000` otherwise.
|
|
161
|
+
- Wall-clock guard for the inline replay loop.
|
|
162
|
+
- Once elapsed, the handler requeues the workflow instead of continuing to run more inline work in the same invocation.
|
|
163
|
+
- The default comes from `World.getRuntimeDeadline()`, so raising a function's `maxDuration` widens the inline budget without configuration. Worlds that do not report a deadline get the flat `120000`. Setting this variable to a finite positive number overrides the tiering entirely.
|
|
164
|
+
|
|
165
|
+
### `WORKFLOW_MAX_INLINE_STEPS`
|
|
166
|
+
|
|
167
|
+
- Default: `3`
|
|
168
|
+
- Clamp: `1` to `16`
|
|
169
|
+
- Number of newly-created steps one invocation runs inline in parallel before queueing the rest.
|
|
170
|
+
|
|
171
|
+
### `WORKFLOW_TURBO`
|
|
172
|
+
|
|
173
|
+
- Default: enabled
|
|
174
|
+
- Fast path for a run's first delivery.
|
|
175
|
+
- Stops forcing optimistic inline step start once the run creates a hook or wait.
|
|
176
|
+
- Set `0` or `false` to disable.
|
|
177
|
+
|
|
178
|
+
### `WORKFLOW_OPTIMISTIC_INLINE_START`
|
|
179
|
+
|
|
180
|
+
- Default: disabled
|
|
181
|
+
- Starts inline step bodies before their `step_started` event is confirmed.
|
|
182
|
+
- Use only when step side effects are idempotent.
|
|
183
|
+
- Set `0` or `false` to force it off, including the first-delivery fast path used by `WORKFLOW_TURBO`.
|
|
184
|
+
|
|
185
|
+
### `WORKFLOW_RETAINED_VM`
|
|
186
|
+
|
|
187
|
+
- Default: enabled
|
|
188
|
+
- Node.js VM engine only. Keeps the suspended workflow VM alive across inline steps within one invocation, so each iteration of the inline loop appends only the newly written events instead of replaying the whole event log in a fresh VM. QuickJS manages its own retained inline loop independently of this setting.
|
|
189
|
+
- A step- or attribute-driven suspension can keep the VM retained even when hooks or waits are open or created at the same boundary. Hook- or wait-only suspensions park the invocation because nothing in the current delivery can advance them, with one exception: when the hook's own create is what the workflow is waiting on (a `hook.getConflict()` awaiter, or a create whose token is already claimed), the invocation resumes the retained VM over the committed `hook_created` or `hook_conflict` instead of re-invoking through the queue. Any replay divergence falls back to a full replay.
|
|
190
|
+
- Step inputs made of plain data (objects, arrays, primitives) and standard built-ins (`Map`, `Set`, `Date`, `RegExp`, typed arrays, `ArrayBuffer`, `URL`, `Headers`) keep the VM retained. Patching or polyfilling built-in prototypes doesn't change that because serialization never calls them. A boundary falls back to a full replay only when serializing its arguments runs code the workflow controls, such as a getter, a proxy, or a custom class serializer, or computes an `Error`'s stack trace.
|
|
191
|
+
- Set `0` or `false` to replay the Node.js workflow from scratch in a fresh VM on every iteration.
|
|
192
|
+
|
|
193
|
+
### `WORKFLOW_INLINE_OWNERSHIP`
|
|
194
|
+
|
|
195
|
+
- Default: enabled
|
|
196
|
+
- Records which queue message owns each inline step execution, so a wake (hook resume, elapsed wait) that replays the run mid-step schedules a delayed backstop instead of immediately redispatching and reexecuting the step. See [Inline step message ownership](/docs/changelog/step-message-ownership).
|
|
197
|
+
- Set `0` or `false` to revert to the previous unconditional immediate re-dispatch.
|
|
198
|
+
|
|
199
|
+
### `WORKFLOW_INLINE_OWNERSHIP_LEASE_SECONDS`
|
|
200
|
+
|
|
201
|
+
- Default: `860`
|
|
202
|
+
- Clamp: `1` to `900`
|
|
203
|
+
- How long after an inline step's latest `step_started` other invocations assume its owner may still be executing the body. Within the lease they defer the step's backstop message; past it they enqueue immediately.
|
|
204
|
+
- Raise this on self-hosted multi-instance deployments whose inline steps run longer than the default (the default is sized for Vercel's function duration ceiling).
|
|
205
|
+
|
|
206
|
+
## Workflow VM engine
|
|
207
|
+
|
|
208
|
+
### `WORKFLOW_VM`
|
|
209
|
+
|
|
210
|
+
- Default: `node`
|
|
211
|
+
- Values: `node` or `quickjs`
|
|
212
|
+
- Selects the sandboxed VM engine that executes workflow functions (`"use workflow"`). Step functions are unaffected and always run with full Node.js access.
|
|
213
|
+
- `node` (default) runs workflow code in a [`node:vm`](https://nodejs.org/api/vm.html) context.
|
|
214
|
+
- `quickjs` (experimental) runs workflow code in a [QuickJS](https://github.com/quickjs-ng/quickjs) VM compiled to WebAssembly (via [`quickjs-wasi`](https://github.com/vercel-labs/quickjs-wasi)). Both engines implement the same event-replay execution model (seeded PRNG, deterministic clock, and correlation-ID sequences are identical), but the **global surface is not identical**. Review the differences below before switching an existing deployment. The QuickJS engine is intended for platforms that do not implement `node:vm`, and is the foundation for future VM-memory snapshotting.
|
|
215
|
+
- Global-surface differences under `quickjs` apply to workflow functions only. Step functions always have full Node.js:
|
|
216
|
+
- `crypto.getRandomValues()` and `crypto.randomUUID()` are provided and deterministic (seeded like the node engine's). All `crypto.subtle.*` methods, including `digest`, throw with guidance to move to a step function. The node engine supports `digest`.
|
|
217
|
+
- `Intl` is not available (QuickJS has no ICU). The `Intl.*` constructors throw, and `toLocaleString`-family methods (including `localeCompare`) throw when called **with an explicit locale**. Calling them without arguments keeps the engine default. Perform locale-sensitive formatting in a step function.
|
|
218
|
+
- `WebAssembly` and `Atomics` are not available.
|
|
219
|
+
- `process` exposes only a frozen copy of `env`, matching the node engine.
|
|
220
|
+
- The engine choice is stamped into the run's `executionContext` when the run starts, so a run keeps executing on the engine it started on even if the deployment's `WORKFLOW_VM` changes. Runs without a stamped engine use the handler's `WORKFLOW_VM` value.
|
|
221
|
+
- Unknown values throw at startup.
|
|
222
|
+
|
|
223
|
+
### `WORKFLOW_QUICKJS_BASELINE_SNAPSHOT`
|
|
224
|
+
|
|
225
|
+
- Default: enabled
|
|
226
|
+
- Only read when `WORKFLOW_VM=quickjs`.
|
|
227
|
+
- Evaluates the workflow bundle once per function instance, snapshots the resulting VM, and restores that snapshot at the start of every invocation instead of re-evaluating the bundle. This is the dominant share of QuickJS VM startup: roughly 77 ms to 3 ms to first suspension for a 1.3 MB bundle.
|
|
228
|
+
- A bundle whose module scope consumes randomness, reads the clock, or replaces a serialization intrinsic cannot be snapshotted safely. The runtime detects these cases when preparing the snapshot and falls back to per-invocation evaluation.
|
|
229
|
+
- Set `0` or `false` to always evaluate the bundle per invocation.
|
|
230
|
+
|
|
231
|
+
## Compression and tracing
|
|
232
|
+
|
|
233
|
+
### `WORKFLOW_DISABLE_COMPRESSION`
|
|
234
|
+
|
|
235
|
+
- Default: compression enabled
|
|
236
|
+
- Set `1` to disable compression when writing payloads.
|
|
237
|
+
- Reads still decompress existing payloads.
|
|
238
|
+
|
|
239
|
+
### `WORKFLOW_COMPRESSION_CODEC`
|
|
240
|
+
|
|
241
|
+
- Default: automatic
|
|
242
|
+
- Forces the write-side codec to `zstd` or `gzip`.
|
|
243
|
+
- Invalid values are ignored. Automatic mode prefers `zstd` when the current Node.js runtime supports it, otherwise it falls back to `gzip`.
|
|
244
|
+
|
|
245
|
+
### `WORKFLOW_TRACE_MODE`
|
|
246
|
+
|
|
247
|
+
- Default: `linked`
|
|
248
|
+
- OpenTelemetry span topology for runs.
|
|
249
|
+
- Accepts `linked` or `continuous`.
|
|
250
|
+
|
|
251
|
+
### `DEBUG`
|
|
252
|
+
|
|
253
|
+
- Default: unset
|
|
254
|
+
- Debug log filter with wildcards and negation.
|
|
255
|
+
- Examples: `workflow:*`, `workflow:*,-workflow:telemetry:*`.
|
|
256
|
+
|
|
257
|
+
## Transport
|
|
258
|
+
|
|
259
|
+
### `WORKFLOW_H2_MULTIPLEX`
|
|
260
|
+
|
|
261
|
+
- Default: enabled
|
|
262
|
+
- On the Vercel World, lets concurrent event-log requests share one HTTP/2 connection instead of one connection per in-flight request.
|
|
263
|
+
- Set `0` to take the event-log requests off HTTP/2 entirely, back to one request per HTTP/1.1 connection. Use this as the kill switch if HTTP/2 turns out to be at fault for event delivery problems.
|
|
264
|
+
- Has no effect when `WORKFLOW_NODE_HTTP` is enabled, which takes the whole HTTP/2 path away.
|
|
265
|
+
|
|
266
|
+
### `WORKFLOW_NODE_HTTP`
|
|
267
|
+
|
|
268
|
+
- Default: disabled
|
|
269
|
+
- Makes the Vercel and Local Worlds issue their HTTP requests through Node's built-in `node:http` and `node:https` modules, instead of the HTTP client library those Worlds normally use.
|
|
270
|
+
- Set `1` to switch to Node's modules. Read the trade-offs below first: they cost throughput on every deployment, which is why this is opt-in.
|
|
271
|
+
- Use it when that library is not an option: a bundler that mangles it, a runtime that does not ship a working copy of it, or a transport-level fault you want to rule out. It is not reached by way of `fetch()` either, so a runtime whose `fetch()` is built on the same library is still covered.
|
|
272
|
+
|
|
273
|
+
Node's own modules do less than the client they replace, so enabling this drops the per-call-site tuning the Worlds configure:
|
|
274
|
+
|
|
275
|
+
- Event-log requests lose HTTP/2, so concurrent reads and writes no longer share one connection, and the enlarged HTTP/2 receive windows no longer apply. This is the largest difference, and it slows down replays that read a big event log. It does not apply to event writes on the [WebSocket events transport](/docs/configuration/worlds#workflow_events_transport), which is the default and takes neither transport.
|
|
276
|
+
- Requests lose their transport-level retry. Failures still surface to the layers above, which retry event writes and redeliver queue messages, so nothing is silently dropped, but a failure that a same-connection retry would have hidden now costs a full redelivery.
|
|
277
|
+
- Stream close loses its retry of retriable server errors. A transient failure at close can leave a stream marked closing until the run expires, where it would previously have resolved on the retry.
|
|
278
|
+
|
|
279
|
+
Connection pooling, keep-alive, and the request, header, and body deadlines are preserved. Node's agents configure pooling and keep-alive, and each request receives the deadlines from the Local World's two queue timeouts or the same defaults that the Vercel World's HTTP client currently applies. Queue sends are the partial exception: that client takes no transport override, so it cannot move to Node's modules. It does honor this variable, by dispatching through the runtime's own copy of the library rather than the copy the World bundles, which is the distinction that matters when the bundled copy is the thing that does not work.
|
|
280
|
+
|
|
281
|
+
A `dispatcher` passed to `createVercelWorld()` still wins over this variable. The variable chooses which transport the World builds when you have not supplied one.
|
|
282
|
+
|
|
283
|
+
### `WORKFLOW_VERCEL_QUEUE_TIMEOUT_MS`
|
|
284
|
+
|
|
285
|
+
- Default: `30000`
|
|
286
|
+
- Total deadline for one request the Vercel World's queue client makes, measured from the moment it is handed to the transport, so it also covers time the request spends waiting for a free connection.
|
|
287
|
+
- Clamped to `[5000, 120000]`.
|
|
288
|
+
- This is the only request path the World cannot bound with `WORKFLOW_REQUEST_TIMEOUT_MS`, because the queue client makes its own calls and accepts no override for them. Without a deadline here, a queue acknowledgement that never completes holds the invocation until the platform kills it, and a killed invocation never acknowledges, so the message is redelivered.
|
|
289
|
+
- Keep it below the queue's visibility-renewal interval (60 seconds) so a failed call has room to surface and be retried before the message lease lapses.
|
|
290
|
+
|
|
291
|
+
### `WORKFLOW_VERCEL_QUEUE_CONNECTIONS`
|
|
292
|
+
|
|
293
|
+
- Default: `64`
|
|
294
|
+
- Connections the Vercel World's queue client may open to the queue service.
|
|
295
|
+
- Clamped to `[1, 1024]`.
|
|
296
|
+
- Sized much higher than the World's other connection pools on purpose. The queue client makes roughly two small requests per invocation, so its concurrency tracks how many invocations a compute instance is serving at once rather than any per-request fan-out. Lower it only if you have a reason to cap sockets; too low turns invocation concurrency into the limit on how fast messages can be acknowledged.
|
|
297
|
+
|
|
298
|
+
## Queue namespace
|
|
299
|
+
|
|
300
|
+
### `WORKFLOW_QUEUE_NAMESPACE`
|
|
301
|
+
|
|
302
|
+
- Default: none
|
|
303
|
+
- Queue topic namespace shared by build output and Worlds.
|
|
304
|
+
- Must match `^[a-z][a-z0-9]*$`.
|
|
305
|
+
- Set it consistently at build and runtime.
|
|
306
|
+
|
|
307
|
+
## Streams and waits
|
|
308
|
+
|
|
309
|
+
These variables are primarily for tests, debugging, or unusual deployments.
|
|
310
|
+
|
|
311
|
+
### `WORKFLOW_STREAM_FLUSH_INTERVAL_MS`
|
|
312
|
+
|
|
313
|
+
- Default: `0` (dispatch the first chunk of an idle stream immediately)
|
|
314
|
+
- Group-commit window for the *leading* chunk of an idle stream. `0` sends it at once; a positive value holds it up to that many milliseconds to collect a group. This opt-in setting trades first-chunk latency for larger batches and can benefit slow-but-steady producers. Chunks arriving while a request is already in flight always coalesce into the next group regardless of this setting.
|
|
315
|
+
- Also available as `streamFlushIntervalMs` on Worlds that expose it (the env var, when set, takes precedence over the World option).
|
|
316
|
+
|
|
317
|
+
### `WORKFLOW_STREAM_MAX_INFLIGHT_CHUNKS`
|
|
318
|
+
|
|
319
|
+
- Default: `1000`
|
|
320
|
+
- Flow-control bound: how many stream chunks may be read-but-not-yet-durably-written while writes are coalesced. Once this many are outstanding, the producer pauses reading until a batch is written. Bounds in-memory buffering; distinct from the per-request batch caps below.
|
|
321
|
+
|
|
322
|
+
### `WORKFLOW_STREAM_MAX_CHUNKS_PER_BATCH`
|
|
323
|
+
|
|
324
|
+
- Default: `1000`
|
|
325
|
+
- Wire limit: maximum number of chunks sent in a single coalesced multi-write. Larger bursts are split across requests so one request can't exceed the server's per-multi-write chunk cap.
|
|
326
|
+
|
|
327
|
+
### `WORKFLOW_STREAM_MAX_BYTES_PER_BATCH`
|
|
328
|
+
|
|
329
|
+
- Default: `1048576` (1 MiB)
|
|
330
|
+
- Wire limit: maximum cumulative bytes in a single coalesced multi-write, so large chunks don't produce a request body that platform limits reject. A single chunk larger than this is still sent on its own.
|
|
331
|
+
|
|
332
|
+
### `WORKFLOW_STREAM_MAX_BUFFERED_BYTES`
|
|
333
|
+
|
|
334
|
+
- Default: `8388608` (8 MiB)
|
|
335
|
+
- Flow-control bound: maximum cumulative bytes accepted into the stream writer's group-commit buffer before `write()` applies backpressure. The byte-denominated counterpart of `WORKFLOW_STREAM_MAX_INFLIGHT_CHUNKS`; distinct from `WORKFLOW_STREAM_MAX_BYTES_PER_BATCH`, which only splits how much goes out in one request.
|
|
336
|
+
|
|
337
|
+
### `WORKFLOW_FRAMED_STREAM_MAX_RECONNECTS`
|
|
338
|
+
|
|
339
|
+
- Default: `50`
|
|
340
|
+
- Consecutive reconnect cap for framed stream readers.
|
|
341
|
+
|
|
342
|
+
### `WORKFLOW_FRAMED_STREAM_MAX_TOTAL_RECONNECTS`
|
|
343
|
+
|
|
344
|
+
- Default: `1000`
|
|
345
|
+
- Total reconnect cap per stream session.
|
|
346
|
+
|
|
347
|
+
### `WORKFLOW_WAIT_CONTINUATION_MAX_DELAY_SECONDS`
|
|
348
|
+
|
|
349
|
+
- Default: `82800` (23 hours)
|
|
350
|
+
- Longest single queue delay used for `sleep()` continuations.
|
|
351
|
+
- If a wait is longer than this, Workflow queues one continuation for the maximum delay, then queues another continuation after that message fires, repeating until the wait's target time is reached.
|
|
352
|
+
|
|
353
|
+
### `WORKFLOW_NEAR_ELAPSED_WAIT_THRESHOLD_SECONDS`
|
|
354
|
+
|
|
355
|
+
- Default: `2`
|
|
356
|
+
- Clock-skew tolerance for wait continuations that arrive near their target time.
|
|
357
|
+
|
|
358
|
+
### `WORKFLOW_DEFERRED_CHECK_DELAY_MS`
|
|
359
|
+
|
|
360
|
+
- Default: `100`
|
|
361
|
+
- Delay before the unconsumed-event check fires.
|
|
362
|
+
- Minimum: `10`.
|
|
363
|
+
|
|
364
|
+
### `WORKFLOW_LOCK_POLL_INTERVAL_MS`
|
|
365
|
+
|
|
366
|
+
- Default: `10`
|
|
367
|
+
- Poll interval for detecting stream lock release.
|
|
368
|
+
|
|
369
|
+
## Limits
|
|
370
|
+
|
|
371
|
+
### `WORKFLOW_MAX_EVENTS_OVERRIDE`
|
|
372
|
+
|
|
373
|
+
- Default: unset
|
|
374
|
+
- Lowers the per-run event ceiling supplied by the World. A run whose event log reaches the ceiling fails with `MAX_EVENTS_EXCEEDED`, which stops a runaway loop from growing its log without bound.
|
|
375
|
+
- Clamp-down only: it never raises the World's limit, and it applies even when the World supplies none. With no World limit and no override, nothing is enforced.
|
|
376
|
+
- The Local and Vercel Worlds both supply a limit; the Local World defaults to 25,000 and is configurable with [`WORKFLOW_MAX_EVENTS`](/docs/configuration/worlds#workflow_max_events).
|