diff --git a/src/content/changelog/workflows/2026-03-03-step-limits-to-25k.mdx b/src/content/changelog/workflows/2026-03-03-step-limits-to-25k.mdx
new file mode 100644
index 00000000000..66636419651
--- /dev/null
+++ b/src/content/changelog/workflows/2026-03-03-step-limits-to-25k.mdx
@@ -0,0 +1,29 @@
+---
+title: Workflows step limit increased to 25,000 steps per instance
+description: Each Workflow instance supports 10,000 steps by default, configurable up to 25,000 steps
+products:
+ - workflows
+ - workers
+date: 2026-03-03 12:00:00 UTC
+---
+
+Each Workflow instance now supports 10,000 steps by default, configurable up to 25,000 steps in your `wrangler.jsonc` file:
+
+```json
+{
+ "workflows": [
+ {
+ "name": "my-workflow",
+ "binding": "MY_WORKFLOW",
+ "class_name": "MyWorkflow",
+ "limits": {
+ "steps": 25000
+ }
+ }
+ ]
+}
+```
+
+Previously, each instance was limited to 1,024 steps. Now, Workflows can support more complex, long-running executions without the additional complexity of recursive or child workflow calls.
+
+Note that the maximum persisted state limit per Workflow instance remains **100 MB** for Workers Free and **1 GB** for Workers Paid. Refer to [Workflows limits](/workflows/reference/limits/) for more information.
diff --git a/src/content/docs/agents/api-reference/run-workflows.mdx b/src/content/docs/agents/api-reference/run-workflows.mdx
index 11fb316eccd..669935e3936 100644
--- a/src/content/docs/agents/api-reference/run-workflows.mdx
+++ b/src/content/docs/agents/api-reference/run-workflows.mdx
@@ -825,12 +825,12 @@ await this.rejectWorkflow(instanceId, { reason: "Request denied" });
## Limitations
-| Constraint | Limit |
-| ------------------- | ------------------- |
-| Maximum steps | 1,024 per workflow |
-| State size | 10 MB per workflow |
-| Event wait time | 1 year maximum |
-| Step execution time | 30 minutes per step |
+| Constraint | Limit |
+| ------------------- | --------------------------------------------------------- |
+| Maximum steps | 10,000 per workflow (default) / configurable up to 25,000 |
+| State size | 10 MB per workflow |
+| Event wait time | 1 year maximum |
+| Step execution time | 30 minutes per step |
Workflows cannot open WebSocket connections directly. Use `broadcastToClients()` to communicate with connected clients through the Agent.
diff --git a/src/content/docs/workflows/build/workers-api.mdx b/src/content/docs/workflows/build/workers-api.mdx
index 1d81d7f2278..465399703d0 100644
--- a/src/content/docs/workflows/build/workers-api.mdx
+++ b/src/content/docs/workflows/build/workers-api.mdx
@@ -112,9 +112,13 @@ More information about the limits imposed on Workflow can be found in the [Workf
:::
-- step.waitForEvent(name: string, options: ): Promise<void>
- - `name` - the name of the step.
- - `options` - an object with properties for `type` (up to 100 characters [^1]), which determines which event type this `waitForEvent` call will match on when calling `instance.sendEvent`, and an optional `timeout` property, which defines how long the `waitForEvent` call will block for before throwing a timeout exception. The default timeout is 24 hours.
+- step.waitForEvent(name: string, options: ): Promise<void>-
+ `name` - the name of the step. - `options` - an object with properties for
+ `type` (up to 100 characters [^1]), which determines which event type this
+ `waitForEvent` call will match on when calling `instance.sendEvent`, and an
+ optional `timeout` property, which defines how long the `waitForEvent` call
+ will block for before throwing a timeout exception. The default timeout is 24
+ hours.
@@ -152,6 +156,28 @@ export type WorkflowStepConfig = {
Refer to the [documentation on sleeping and retrying](/workflows/build/sleeping-and-retrying/) to learn more about how Workflows are retried.
+## Workflow step limits
+
+Each workflow instance supports 10,000 steps by default. You can increase this up to 25,000 steps by configuring `steps` within the `limits` property of your Workflow definition in your Wrangler configuration:
+
+
+
+```toml
+[[workflows]]
+name = "my-workflow"
+binding = "MY_WORKFLOW"
+class_name = "MyWorkflow"
+
+[workflows.limits]
+steps = 25_000
+```
+
+
+
+Note that `step.sleep` does not count towards the maximum steps limit.
+
+Refer to [Workflow limits](/workflows/reference/limits/) for more information.
+
## NonRetryableError
{/* prettier-ignore */}
@@ -182,9 +208,9 @@ For example, to bind to a Workflow called `workflows-starter` and to make it ava
// binding name env.MY_WORKFLOW
"binding": "MY_WORKFLOW",
// this is class that extends the Workflow class in src/index.ts
- "class_name": "MyWorkflow"
- }
- ]
+ "class_name": "MyWorkflow",
+ },
+ ],
}
```
@@ -220,9 +246,9 @@ For example, if your Workflow is defined in a Worker script named `billing-worke
"class_name": "MyWorkflow",
// the script name where the Workflow is defined.
// required if the Workflow is defined in another script.
- "script_name": "billing-worker"
- }
- ]
+ "script_name": "billing-worker",
+ },
+ ],
}
```
@@ -455,8 +481,10 @@ Terminate a Workflow instance.
[Send an event](/workflows/build/events-and-parameters/) to a running Workflow instance.
-- sendEvent(): Promise<void>
- - `options` - the event `type` (up to 100 characters [^1]) and `payload` to send to the Workflow instance. The `type` must match the `type` in the corresponding `waitForEvent` call in your Workflow.
+- sendEvent(): Promise<void>- `options` - the event `type`
+ (up to 100 characters [^1]) and `payload` to send to the Workflow instance.
+ The `type` must match the `type` in the corresponding `waitForEvent` call in
+ your Workflow.
Return `void` on success; throws an exception if the Workflow is not running or is an errored state.
@@ -505,9 +533,9 @@ type InstanceStatus = {
| "waiting" // instance is hibernating and waiting for sleep or event to finish
| "waitingForPause" // instance is finishing the current work to pause
| "unknown";
- error?: {
- name: string,
- message: string
+ error?: {
+ name: string;
+ message: string;
};
output?: unknown;
};
diff --git a/src/content/docs/workflows/reference/limits.mdx b/src/content/docs/workflows/reference/limits.mdx
index aa44dbfb0b8..8657f3b7caa 100644
--- a/src/content/docs/workflows/reference/limits.mdx
+++ b/src/content/docs/workflows/reference/limits.mdx
@@ -27,7 +27,7 @@ Workflows cannot be deployed to Workers for Platforms namespaces, as Workflows d
| Maximum event [payload size](/workflows/build/events-and-parameters/) | 1MiB (2^20 bytes) | 1MiB (2^20 bytes) |
| Maximum state that can be persisted per Workflow instance | 100MB | 1GB |
| Maximum `step.sleep` duration | 365 days (1 year) | 365 days (1 year) |
-| Maximum steps per Workflow [^5] | 1024 | 1024 |
+| Maximum steps per Workflow [^5] | 10,000 (default) / configurable up to 25,000 | 10,000 (default) / configurable up to 25,000 |
| Maximum Workflow executions | 100,000 per day [shared with Workers daily limit](/workers/platform/limits/#worker-limits) | Unlimited |
| Concurrent Workflow instances (executions) per account [^7] | 100 | 10,000 |
| Maximum Workflow instance creation rate [^8] | 100 per second [^6] | 100 per second [^6] |
@@ -43,7 +43,7 @@ Workflows cannot be deployed to Workers for Platforms namespaces, as Workflows d
[^4]: Match pattern: _```^[a-zA-Z0-9_][a-zA-Z0-9-_]\*$```\_
-[^5]: `step.sleep` do not count towards the max. steps limit
+[^5]: `step.sleep` does not count towards the maximum steps limit
[^6]: Workflows will return a HTTP 429 rate limited error if you exceed the rate of new Workflow instance creation.
@@ -103,6 +103,10 @@ export class MyWorkflow extends WorkflowEntrypoint {
While a given Workflow instance is waiting for 30 days, it will transition to the `waiting` state, allowing other `queued` instances to run if concurrency limits are reached.
+### Increasing Workflow step limits
+
+Each Workflow instance supports 10,000 steps by default, but this can be increased up to 25,000 steps in your Wrangler configuration. Refer to [Workflow step limits](/workflows/build/workers-api/#workflowsteplimit) for more information.
+
### Increasing Workflow CPU limits
Workflows are Worker scripts, and share the same [per invocation CPU limits](/workers/platform/limits/#worker-limits) as any Workers do. Note that CPU time is active processing time: not time spent waiting on network requests, storage calls, or other general I/O, which don't count towards your CPU time or Workflows compute consumption.