Skip to content

Commit 6e97b1c

Browse files
mia303ask-bonk[bot]Naapperas
authored
[Workflows] Add delay function docs (#31850)
* [Workflows] Add delay function docs * Apply suggestions from code review Co-authored-by: ask-bonk[bot] <249159057+ask-bonk[bot]@users.noreply.github.com> Co-authored-by: Nuno Pereira <nunoafonso2002@gmail.com> * Rename 2026-07-02-dynamic-retry-delays.mdx to 2026-07-03-dynamic-retry-delays.mdx * [Workflows] Update publish date --------- Co-authored-by: ask-bonk[bot] <249159057+ask-bonk[bot]@users.noreply.github.com> Co-authored-by: Nuno Pereira <nunoafonso2002@gmail.com>
1 parent e9ea905 commit 6e97b1c

4 files changed

Lines changed: 94 additions & 2 deletions

File tree

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
title: Workflows now supports delay functions when retrying
3+
description: Workflows step retries now support delay functions, so you can change the next retry delay based on the failed attempt and error.
4+
products:
5+
- workflows
6+
date: 2026-07-09 12:00:00 UTC
7+
---
8+
9+
import { TypeScriptExample } from "~/components";
10+
11+
With [Workflows](/workflows/), you can configure built-in retry behavior for each step. Previously, you could configure step retries with fixed delay durations, such as seconds, minutes, or hours, and backoff strategies such as `constant`, `linear`, or `exponential`.
12+
13+
Step retries now support dynamic delay functions. Instead of choosing only a base delay and backoff strategy, pass a function to `retries.delay` and calculate the next delay from the failed attempt and thrown error.
14+
15+
This is useful when retries should depend on the failure. Your Workflow may need to wait longer after a rate-limit error, but retry sooner after a short network failure. The delay function can also accommodate provider guidance if, for example, a downstream API returns a `Retry-After` value in its error messaging.
16+
17+
<TypeScriptExample>
18+
19+
```ts
20+
await step.do(
21+
"sync customer",
22+
{
23+
retries: {
24+
limit: 5,
25+
delay: ({ ctx, error }) => {
26+
if (error.message.includes("rate limit")) {
27+
return `${ctx.attempt * 30} seconds`;
28+
}
29+
30+
return "10 seconds";
31+
},
32+
},
33+
},
34+
async () => {
35+
await syncCustomer();
36+
},
37+
);
38+
```
39+
40+
</TypeScriptExample>
41+
42+
Dynamic delay functions can return a duration string, a number, or a promise that resolves to a duration. Use them to add adaptive retry behavior without writing separate queue or scheduling logic. For more information, refer to [Sleeping and retrying](/workflows/build/sleeping-and-retrying/).

src/content/docs/workflows/build/sleeping-and-retrying.mdx

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ const defaultConfig: WorkflowStepConfig = {
7474
When providing your own `StepConfig`, you can configure:
7575

7676
- The total number of attempts to make for a step (limited to 10,000 retries per step)
77-
- The delay between attempts (accepts both `number` (ms) or a human-readable format)
77+
- The delay between attempts. Use a fixed duration as a `number` in milliseconds or a human-readable string, or use a function that returns the next delay.
7878
- What backoff algorithm to apply between each attempt: any of `constant`, `linear`, or `exponential`
7979
- When to timeout (in duration) before considering the step as failed (including during a retry attempt, as the timeout is set per attempt)
8080

@@ -97,6 +97,42 @@ let someState = await step.do(
9797
);
9898
```
9999

100+
### Set a dynamic retry delay
101+
102+
Use a delay function when the next retry delay should depend on the failed attempt or the thrown error. This gives you more control than a fixed delay with `constant`, `linear`, or `exponential` backoff. It is useful for rate limits, downstream provider recovery, and short network failures.
103+
104+
The delay function receives an object with:
105+
106+
- `ctx` - the current [`WorkflowStepContext`](/workflows/build/step-context/), including `ctx.attempt`.
107+
- `error` - the error that caused the retry.
108+
109+
Return a duration string, a number in milliseconds, or a promise that resolves to either value.
110+
111+
<TypeScriptExample>
112+
113+
```ts
114+
await step.do(
115+
"sync customer",
116+
{
117+
retries: {
118+
limit: 5,
119+
delay: ({ ctx, error }) => {
120+
if (error.message.includes("rate limit")) {
121+
return `${ctx.attempt * 30} seconds`;
122+
}
123+
124+
return "10 seconds";
125+
},
126+
},
127+
},
128+
async () => {
129+
await syncCustomer();
130+
},
131+
);
132+
```
133+
134+
</TypeScriptExample>
135+
100136
## Force a Workflow instance to fail
101137

102138
You can also force a Workflow instance to fail and _not_ retry by throwing a `NonRetryableError` from within the step.

src/content/docs/workflows/build/step-context.mdx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ type WorkflowStepContext = {
3232
| `attempt` | `number` | The current attempt number (1-indexed). `1` on the first try, `2` on the first retry, and so on. |
3333
| `config` | [`WorkflowStepConfig`](/workflows/build/workers-api/#workflowstepconfig) | The resolved retry and timeout configuration for this step, including any defaults applied by the runtime. |
3434

35+
If a step config's `retries.delay` is a function, the dynamic delay is not exposed on `ctx.config.retries.delay`. The delay function receives its own context object with the current step context and the error that caused the retry.
36+
3537
## Access the context
3638

3739
Pass a parameter to your `step.do` callback to receive the context object:
@@ -65,6 +67,8 @@ await step.do(
6567
);
6668
```
6769

70+
To configure delay functions, refer to [Set a dynamic retry delay](/workflows/build/sleeping-and-retrying/#set-a-dynamic-retry-delay).
71+
6872
## Examples
6973

7074
### Adjust behavior based on retry attempt

src/content/docs/workflows/build/workers-api.mdx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,17 +197,27 @@ Review the documentation on [events and parameters](/workflows/build/events-and-
197197
## WorkflowStepConfig
198198

199199
```ts
200+
export type WorkflowDynamicDelayContext = {
201+
ctx: WorkflowStepContext;
202+
error: Error;
203+
};
204+
205+
export type WorkflowDelayFunction = (
206+
input: WorkflowDynamicDelayContext,
207+
) => string | number | Promise<string | number>;
208+
200209
export type WorkflowStepConfig = {
201210
retries?: {
202211
limit: number;
203-
delay: string | number;
212+
delay: string | number | WorkflowDelayFunction;
204213
backoff?: WorkflowBackoff;
205214
};
206215
timeout?: string | number;
207216
};
208217
```
209218

210219
- A `WorkflowStepConfig` is an optional argument to the `do` method of a `WorkflowStep` and defines properties that allow you to configure the retry behaviour of that step.
220+
- Set `retries.delay` to a fixed duration, or pass a `WorkflowDelayFunction` to calculate the next retry delay from the current step context and thrown error.
211221

212222
Refer to the [documentation on sleeping and retrying](/workflows/build/sleeping-and-retrying/) to learn more about how Workflows are retried.
213223

0 commit comments

Comments
 (0)