You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/tasks/scheduled.mdx
+45Lines changed: 45 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -140,6 +140,50 @@ To use imperative schedules you need to do two things:
140
140
1. Define a task in your code using `schedules.task()`.
141
141
2. Attach 1+ schedules to the task either using the dashboard or the SDK.
142
142
143
+
## Spreading runs with windows
144
+
145
+
By default a schedule runs at its exact cron time. When many schedules share the same cron pattern, such as a daily `0 9 * * *`, they all fire at the same time and load your downstream systems as well as ours. A **window** spreads those runs out: each schedule is assigned a stable time within the window after its cron time, so the load is smoothed while each schedule keeps firing at a predictable, repeatable moment.
146
+
147
+
The assigned time is deterministic. A given schedule always lands at the same offset for a given interval, so runs don't jump around between occurrences. And you can always see exactly when the next run will start.
148
+
149
+
Set a `window` as either:
150
+
151
+
-**An absolute duration** in whole minutes or hours, up to 24 hours: `"30m"`, `"2h"`, `"24h"`. Absolute windows are capped at the next cron time, so a run is never delayed past its following occurrence.
152
+
-**A percentage** of the interval between runs: `"30%"`, `"100%"`. A `"50%"` window on an hourly schedule spreads runs across the first 30 minutes of each hour.
153
+
154
+
Set `"0m"` (or `"0%"`) for no spreading — the run fires at its exact cron time.
155
+
156
+
Declarative schedules set the window on the `cron` object:
157
+
158
+
```ts
159
+
exportconst dailyReport =schedules.task({
160
+
id: "daily-report",
161
+
cron: {
162
+
pattern: "0 0 * * *",
163
+
// spread this run across the 30 minutes after midnight
164
+
window: "30m",
165
+
},
166
+
run: async (payload) => {},
167
+
});
168
+
```
169
+
170
+
Imperative schedules set it when creating or updating a schedule, either in the dashboard form or through the SDK:
171
+
172
+
```ts
173
+
const createdSchedule =awaitschedules.create({
174
+
task: dailyReport.id,
175
+
cron: "0 0 * * *",
176
+
window: "30m",
177
+
deduplicationKey: "user_123456-daily-report",
178
+
});
179
+
```
180
+
181
+
<Note>
182
+
The payload `timestamp` and `upcoming` values are always the nominal cron times, not the assigned
183
+
times. When you retrieve a schedule, `nextRun` is the nominal cron time and `nextRunEffectiveAt`
184
+
is the assigned time the run will actually start.
185
+
</Note>
186
+
143
187
## Supported cron syntax
144
188
145
189
```
@@ -198,6 +242,7 @@ These are the options when creating a schedule:
198
242
| Task | The id of the task you want to attach to. |
199
243
| Cron pattern | The schedule in cron format. You can also describe it in natural language and press "Generate" to fill this in. |
200
244
| Timezone | The timezone the schedule will run in. Defaults to "UTC" |
245
+
| Window | An optional [window](#spreading-runs-with-windows) to spread runs after their cron time, e.g. `30m`, `2h`, or `50%`. |
201
246
| External id | An optional external id, usually you'd use a userId. |
202
247
| Deduplication key | An optional deduplication key. If you pass the same value, it will update rather than create. Scoped per project, not per environment. |
203
248
| Environments | The environments this schedule will run in. |
0 commit comments