Skip to content

Commit fe3f676

Browse files
committed
[Workflows] Document scheduled Workflow triggers
1 parent fa2d786 commit fe3f676

8 files changed

Lines changed: 159 additions & 49 deletions

File tree

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
---
2+
title: Schedule Workflow instances directly from your Workflow binding
3+
description: Add cron schedules to a Workflow binding in wrangler.jsonc to create Workflow instances automatically on a recurring interval.
4+
products:
5+
- workflows
6+
- workers
7+
date: 2026-05-13 12:00:00 UTC
8+
---
9+
10+
You can now attach cron schedules directly to a Workflow binding in `wrangler.jsonc`. Each scheduled run creates a new Workflow instance automatically, so you do not need to define a separate Worker with a `scheduled` handler just to trigger your Workflow on an interval.
11+
12+
For example, you can configure hourly, every-15-minute, or weekday schedules on the same Workflow:
13+
14+
```jsonc
15+
{
16+
"workflows": [
17+
{
18+
"name": "my-scheduled-workflow",
19+
"binding": "MY_WORKFLOW",
20+
"class_name": "MyScheduledWorkflow",
21+
"schedules": [
22+
{ "cron": "0 * * * *" },
23+
{ "cron": "*/15 * * * *" },
24+
{ "cron": "0 9 * * MON-FRI" },
25+
],
26+
},
27+
],
28+
}
29+
```
30+
31+
This makes it easier to build recurring jobs such as database backups, invoice generation, report aggregation, and cleanup tasks without wiring up a separate Cron Trigger entrypoint.
32+
33+
For more information, refer to [Trigger Workflows](/workflows/build/trigger-workflows/).

src/content/docs/learning-paths/workflows-course/series/workflows-3.mdx

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,18 @@ sidebar:
55
order: 3
66
tableOfContents: false
77
description: |
8-
Cloudflare Workflows provide a powerful way to manage asynchronous, durable processes. The ability to explicitly schedule tasks using cron triggers and pause execution with `step.sleep` allows developers to build sophisticated, time-aware applications.
8+
Cloudflare Workflows provide a powerful way to manage asynchronous, durable processes. The ability to explicitly schedule tasks using scheduled handlers and pause execution with `step.sleep` allows developers to build sophisticated, time-aware applications.
99
products:
1010
- workflows
1111
- workers
1212
---
1313

14-
import { Render, Tabs, TabItem, Card, YouTube } from "~/components";
14+
import { Render, Tabs, TabItem, Card, WranglerConfig, YouTube } from "~/components";
1515

1616
<Tabs>
1717
<TabItem label="Watch this episode">
1818

19-
Cloudflare Workflows provide a powerful way to manage asynchronous, durable processes. The ability to explicitly schedule tasks using cron triggers and pause execution with `step.sleep` allows developers to build sophisticated, time-aware applications.
19+
Cloudflare Workflows provide a powerful way to manage asynchronous, durable processes. The ability to explicitly schedule tasks using scheduled handlers and pause execution with `step.sleep` allows developers to build sophisticated, time-aware applications.
2020

2121
<Card>
2222
<YouTube id="L6gR4Yr3UW8" />
@@ -59,18 +59,32 @@ Cloudflare Workflows provide a powerful way to manage asynchronous, durable proc
5959

6060
### Wrangler Configuration
6161

62-
The Wrangler configuration file is used to configure your Worker and Workflows. This includes defining bindings to resources like KV namespaces and setting up triggers for workflows.
62+
The Wrangler configuration file is used to configure your Worker and Workflows. This includes defining bindings to resources like KV namespaces and setting up schedules for workflows.
6363

64-
Open the Wrangler configuration file and find the `[triggers]` section.
65-
[See here](https://github.com/craigsdennis/punderful-workflows/blob/main/wrangler.toml#L68)
64+
The episode repository uses the older pattern of a top-level `[triggers]` section plus a `scheduled` handler in the main Worker to create a `LEADERBOARD_WORKFLOW` instance on a timer.
6665

67-
The `crons` array allows you to define scheduled triggers for your main Worker. The example shows a cron job configured to run every 30 minutes.
66+
[See here](https://github.com/craigsdennis/punderful-workflows/blob/main/wrangler.toml#L68)
6867

69-
Locate the `scheduled` handler in your main Worker code (`src/index.tsx`). This handler is executed when a cron trigger fires.
68+
In current Workflows projects, you can usually schedule the Workflow directly on its binding instead:
69+
70+
<WranglerConfig>
71+
72+
```jsonc
73+
{
74+
"workflows": [
75+
{
76+
"name": "leaderboard-workflow",
77+
"binding": "LEADERBOARD_WORKFLOW",
78+
"class_name": "LeaderboardWorkflow",
79+
"schedules": [{ "cron": "*/30 * * * *" }]
80+
}
81+
]
82+
}
83+
```
7084

71-
[See here](https://github.com/craigsdennis/punderful-workflows/blob/main/src/index.tsx#L315)
85+
</WranglerConfig>
7286

73-
This handler creates an instance of the `LEADERBOARD_WORKFLOW`, initiating the leaderboard update process on a schedule.
87+
Use a separate Cron Trigger and `scheduled` handler only when you need custom logic before deciding whether to create a Workflow instance. Use the latest Wrangler release when configuring Workflow schedules.
7488

7589
### Puntificator: Using AI to Develop More Puns Automatically
7690

src/content/docs/workers/configuration/cron-triggers.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Cron Triggers are ideal for running periodic jobs, such as for maintenance or ca
2323

2424
:::note
2525

26-
Cron Triggers can also be combined with [Workflows](/workflows/) to trigger multi-step, long-running tasks. You can [bind to a Workflow](/workflows/build/workers-api/) directly from your Cron Trigger to execute a Workflow on a schedule.
26+
Cron Triggers are also available directly in [Workflows](/workflows/) via `schedules` on the Workflow binding instead. Refer to [Trigger Workflows](/workflows/build/trigger-workflows/) for details, and use a Wrangler release that supports Workflow schedules.
2727

2828
:::
2929

src/content/docs/workers/wrangler/configuration.mdx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,6 +1194,11 @@ To bind Workflows to your Worker, assign an array of the below object to the `wo
11941194
- `script_name` <Type text="string" /> <MetaInfo text="optional" />
11951195
- The name of the Worker script where the Workflow class is defined. Only required if the Workflow is defined in a different Worker than the one the binding is configured on.
11961196

1197+
- `schedules` <Type text="{ cron: string }[]" /> <MetaInfo text="optional" />
1198+
- A list of cron schedules that create new instances of this Workflow automatically.
1199+
- Use this when you want to run a Workflow on a recurring interval without defining top-level `triggers.crons` and a separate `scheduled` handler.
1200+
- Use a Wrangler release that supports Workflow schedules. If your local schema does not recognize `schedules`, update Wrangler first.
1201+
11971202
Example:
11981203

11991204
<WranglerConfig>
@@ -1205,6 +1210,7 @@ Example:
12051210
"binding": "<BINDING_NAME>",
12061211
"name": "<WORKFLOW_NAME>",
12071212
"class_name": "<CLASS_NAME>",
1213+
"schedules": [{ "cron": "0 * * * *" }],
12081214
},
12091215
],
12101216
}

src/content/docs/workflows/build/trigger-workflows.mdx

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,19 @@ import { TypeScriptExample, WranglerConfig } from "~/components";
1515
You can trigger Workflows both programmatically and via the Workflows APIs, including:
1616

1717
1. With [Workers](/workers) via HTTP requests in a `fetch` handler, or bindings from a `queue` or `scheduled` handler
18-
2. Using the [Workflows REST API](/api/resources/workflows/methods/list/)
19-
3. Via the [wrangler CLI](/workers/wrangler/commands/workflows/#workflows) in your terminal
18+
2. On a recurring interval by defining `schedules` on a Workflow binding in your Wrangler configuration
19+
3. Using the [Workflows REST API](/api/resources/workflows/methods/list/)
20+
4. Via the [wrangler CLI](/workers/wrangler/commands/workflows/#workflows) in your terminal
2021

2122
## Workers API (Bindings)
2223

2324
You can interact with Workflows programmatically from any Worker script by creating a binding to a Workflow. A Worker can bind to multiple Workflows, including Workflows defined in other Workers projects (scripts) within your account.
2425

25-
You can interact with a Workflow:
26+
You can trigger a Workflow:
2627

2728
- Directly over HTTP via the [`fetch`](/workers/runtime-apis/handlers/fetch/) handler
2829
- From a [Queue consumer](/queues/configuration/javascript-apis/#consumer) inside a `queue` handler
30+
- On a recurring schedule by defining `schedules` on the Workflow binding in `wrangler.jsonc`
2931
- From a [Cron Trigger](/workers/configuration/cron-triggers/) inside a `scheduled` handler
3032
- Within a [Durable Object](/durable-objects/)
3133

@@ -64,6 +66,37 @@ To bind to a Workflow from your Workers code, you need to define a [binding](/wo
6466

6567
The `binding = "MY_WORKFLOW"` line defines the JavaScript variable that our Workflow methods are accessible on, including `create` (which triggers a new instance) or `get` (which returns the status of an existing instance).
6668

69+
### Schedule a Workflow directly
70+
71+
If you want to create Workflow instances on a recurring interval, add a `schedules` array to the Workflow binding in your Wrangler configuration:
72+
73+
<WranglerConfig>
74+
75+
```jsonc
76+
{
77+
"$schema": "./node_modules/wrangler/config-schema.json",
78+
"name": "workflows-tutorial",
79+
"main": "src/index.ts",
80+
"compatibility_date": "$today",
81+
"workflows": [
82+
{
83+
"name": "workflows-tutorial",
84+
"binding": "MY_WORKFLOW",
85+
"class_name": "MyWorkflow",
86+
"schedules": [{ "cron": "0 * * * *" }]
87+
}
88+
]
89+
}
90+
```
91+
92+
</WranglerConfig>
93+
94+
Each matching cron expression creates a new Workflow instance automatically. Use this when you want to run a Workflow on a schedule without defining top-level `triggers.crons` and a separate `scheduled` handler.
95+
96+
On [Workers Paid](/workers/platform/pricing/#workers), Workflow instances created by `schedules` can run for up to one hour per cron firing without consuming a Workflow concurrency slot. If the instance pauses or sleeps after that window, the instance yields and enters the normal concurrency queue upon resume. It resumes when a concurrency slot is available.
97+
98+
Use the latest Wrangler release when configuring Workflow schedules. If your local Wrangler schema does not recognize `schedules` yet, update Wrangler before deploying.
99+
67100
The following example shows how you can manage Workflows from within a Worker, including:
68101

69102
- Retrieving the status of an existing Workflow instance by its ID
@@ -148,7 +181,7 @@ let instance = await env.MY_WORKFLOW.get("abc-123");
148181
await instance.resume(); // Returns Promise<void>
149182
```
150183

151-
Calling `resume` on an instance that is not currently paused will have no effect.
184+
Calling `resume` on an instance that is already running will throw an error.
152185

153186
:::caution
154187
If you have reached the maximum concurrent instances for your Workflow, resuming an instance may not restart it immediately. The instance will be queued until a concurrency slot becomes available.

src/content/docs/workflows/examples/backup-d1.mdx

Lines changed: 21 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ description: Send invoice when shopping cart is checked out and paid for
1212
reviewed: 2024-12-30
1313
---
1414

15-
import { TabItem, Tabs, WranglerConfig } from "~/components";
15+
import { WranglerConfig } from "~/components";
1616

17-
In this example, we implement a Workflow periodically triggered by a [Cron Trigger](/workers/configuration/cron-triggers). That Workflow initiates a backup for a D1 database using the REST API, and then stores the SQL dump in an [R2](/r2) bucket.
17+
In this example, we implement a Workflow that runs on a schedule using the `schedules` field on the Workflow binding. That Workflow initiates a backup for a D1 database using the REST API, and then stores the SQL dump in an [R2](/r2) bucket.
1818

1919
When the Workflow is triggered, it fetches the REST API to initiate an export job for a specific database. Then it fetches the same endpoint to check if the backup job is ready and the SQL dump is available to download.
2020

@@ -40,18 +40,15 @@ type Env = {
4040
BACKUP_WORKFLOW: Workflow;
4141
D1_REST_API_TOKEN: string;
4242
BACKUP_BUCKET: R2Bucket;
43-
};
44-
45-
// Workflow parameters: we expect accountId and databaseId
46-
type Params = {
47-
accountId: string;
48-
databaseId: string;
43+
ACCOUNT_ID: string;
44+
DATABASE_ID: string;
4945
};
5046

5147
// Workflow logic
52-
export class backupWorkflow extends WorkflowEntrypoint<Env, Params> {
53-
async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
54-
const { accountId, databaseId } = event.payload;
48+
export class backupWorkflow extends WorkflowEntrypoint<Env> {
49+
async run(_event: WorkflowEvent<unknown>, step: WorkflowStep) {
50+
const accountId = this.env.ACCOUNT_ID;
51+
const databaseId = this.env.DATABASE_ID;
5552

5653
const url = `https://api.cloudflare.com/client/v4/accounts/${accountId}/d1/database/${databaseId}/export`;
5754
const method = "POST";
@@ -105,18 +102,6 @@ export default {
105102
async fetch(req: Request, env: Env): Promise<Response> {
106103
return new Response("Not found", { status: 404 });
107104
},
108-
async scheduled(
109-
controller: ScheduledController,
110-
env: Env,
111-
ctx: ExecutionContext,
112-
) {
113-
const params: Params = {
114-
accountId: "{accountId}",
115-
databaseId: "{databaseId}",
116-
};
117-
const instance = await env.BACKUP_WORKFLOW.create({ params });
118-
console.log(`Started workflow: ${instance.id}`);
119-
},
120105
};
121106
```
122107

@@ -130,6 +115,8 @@ Here is a minimal package.json:
130115
}
131116
```
132117

118+
Create `D1_REST_API_TOKEN` as a [secret](/workers/configuration/secrets/) with permission to export the target D1 database.
119+
133120
Here is a [Wrangler configuration file](/workers/wrangler/configuration/):
134121

135122
<WranglerConfig>
@@ -143,25 +130,29 @@ Here is a [Wrangler configuration file](/workers/wrangler/configuration/):
143130
"compatibility_flags": [
144131
"nodejs_compat"
145132
],
133+
"vars": {
134+
"ACCOUNT_ID": "account-id",
135+
"DATABASE_ID": "database-id"
136+
},
146137
"workflows": [
147138
{
148139
"name": "backup-workflow",
149140
"binding": "BACKUP_WORKFLOW",
150-
"class_name": "backupWorkflow"
141+
"class_name": "backupWorkflow",
142+
"schedules": [{ "cron": "0 0 * * *" }]
151143
}
152144
],
153145
"r2_buckets": [
154146
{
155147
"binding": "BACKUP_BUCKET",
156148
"bucket_name": "d1-backups"
157149
}
158-
],
159-
"triggers": {
160-
"crons": [
161-
"0 0 * * *"
162-
]
163-
}
150+
]
164151
}
165152
```
166153

167154
</WranglerConfig>
155+
156+
Each scheduled run creates a new Workflow instance automatically.
157+
158+
Use the latest Wrangler release when configuring Workflow schedules. If your local Wrangler schema does not recognize `schedules` yet, update Wrangler before deploying.

src/content/docs/workflows/get-started/guide.mdx

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,11 +168,38 @@ Follow the steps below to learn how to build a Workflow from scratch.
168168
}
169169
```
170170

171-
</WranglerConfig>
171+
</WranglerConfig>
172172

173-
The `class_name` must match your exported class, and `binding` is the variable name you use to access the Workflow in your code (like `env.MY_WORKFLOW`).
173+
The `class_name` must match your exported class, and `binding` is the variable name you use to access the Workflow in your code (like `env.MY_WORKFLOW`).
174174

175-
You can also access [bindings](/workers/runtime-apis/bindings/) (such as [KV](/kv/), [R2](/r2/), or [D1](/d1/)) via `this.env` within your Workflow. For more information on bindings within Workers, refer to [Bindings (env)](/workers/runtime-apis/bindings/).
175+
If you want the same Workflow to run automatically on a recurring interval, add `schedules` to the Workflow definition:
176+
177+
<WranglerConfig>
178+
179+
```jsonc
180+
{
181+
"$schema": "node_modules/wrangler/config-schema.json",
182+
"name": "my-workflow",
183+
"main": "src/index.ts",
184+
"compatibility_date": "$today",
185+
"workflows": [
186+
{
187+
"name": "my-workflow",
188+
"binding": "MY_WORKFLOW",
189+
"class_name": "MyWorkflow",
190+
"schedules": [{ "cron": "0 * * * *" }]
191+
}
192+
]
193+
}
194+
```
195+
196+
</WranglerConfig>
197+
198+
Each matching cron expression creates a new Workflow instance automatically, so you do not need top-level `triggers.crons` and a separate `scheduled` handler for Workflow-specific recurring runs.
199+
200+
Use the latest Wrangler release when configuring Workflow schedules. If your local Wrangler schema does not recognize `schedules` yet, update Wrangler before deploying.
201+
202+
You can also access [bindings](/workers/runtime-apis/bindings/) (such as [KV](/kv/), [R2](/r2/), or [D1](/d1/)) via `this.env` within your Workflow. For more information on bindings within Workers, refer to [Bindings (env)](/workers/runtime-apis/bindings/).
176203

177204
2. Now, generate types for your bindings:
178205

src/content/docs/workflows/reference/limits.mdx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ Workflows cannot be deployed to Workers for Platforms namespaces, as Workflows d
5151

5252
[^6]: Workflows will return a HTTP 429 rate limited error if you exceed the rate of new Workflow instance creation.
5353

54-
[^7]: Only instances with a `running` state count towards the concurrency limits. Instances in the `waiting` state are excluded from these limits.
54+
[^7]: Only instances with a `running` state count towards the concurrency limits. Instances in the `waiting` state are excluded from these limits. Workers Paid cron-triggered Workflow instances have a separate one-hour cron concurrency budget per firing.
5555

5656
[^8]: Each instance created or restarted counts towards this limit
5757

@@ -113,6 +113,12 @@ export class MyWorkflow extends WorkflowEntrypoint<Env> {
113113

114114
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.
115115

116+
### Cron-triggered instances on Workers Paid
117+
118+
On [Workers Paid](/workers/platform/pricing/#workers), Workflow instances created by `schedules` can run for up to one hour per cron firing without consuming a Workflow concurrency slot.
119+
120+
After that budget is used, the instance yields and enters the normal concurrency queue. It resumes when a concurrency slot is available. The instance does not fail, time out, or terminate because it used this cron concurrency budget.
121+
116122
### Increasing Workflow step limits
117123

118124
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/#workflow-step-limits) for more information.

0 commit comments

Comments
 (0)