Cloudflare Workflows retries can now calculate their own delay!
Hi, I'm Shii-chan! Today I want to share a nice update to Cloudflare Workflows that just landed.
Cloudflare ChangelogWhat was announced?
According to the Cloudflare Changelog, Workflows step retries now support dynamic delay functions. Workflows already lets you configure retry behavior for each step in detail, and this update changes how you decide the wait time before the next attempt.
The story so far
Previously, you configured retries with a fixed delay duration (seconds, minutes, or hours) plus a backoff strategy such as constant, linear, or exponential. You'd pick a base delay and a strategy, and Workflows would wait accordingly before retrying.
But real-world failures aren't all the same. A rate-limit error and a brief network hiccup really call for different wait times, and the old fixed-configuration approach made it hard to fine-tune that.
What changes
With the new option, you can pass a function to retries.delay instead of a fixed base delay and strategy. This function receives the failed attempt count (ctx.attempt) and the thrown error, so you can calculate the next delay based on what actually went wrong.
That means you can now write retry logic like waiting longer after a rate-limit error but retrying sooner after a short network failure, all within Workflows itself. It can also accommodate provider guidance, for example when a downstream API returns a Retry-After value in its error messaging.
Dive Deep
Here's the code example from the changelog:
await step.do(
"sync customer",
{
retries: {
limit: 5,
delay: ({ ctx, error }) => {
if (error.message.includes("rate limit")) {
return `${ctx.attempt * 30} seconds`;
}
return "10 seconds";
},
},
},
async () => {
await syncCustomer();
},
);
If the error message includes "rate limit", the delay grows with the attempt count (ctx.attempt); otherwise it just waits 10 seconds.
The delay function can return a duration string like "10 seconds", a plain number, or even a promise that resolves to a duration, so you could fetch some external information asynchronously before deciding how long to wait.
Wrap-up
- Workflows step retries can now accept a function for
retries.delay - The function receives the failed attempt count (
ctx.attempt) and the thrown error to calculate the next delay dynamically - You can set different wait times depending on the failure type, like rate limits versus network errors
- The return value can be a duration string, a number, or a promise
- This adds adaptive retry behavior without writing separate retry logic yourself
If you're calling external APIs from Workflows and wanted retries that adapt to the type of failure, this update is exactly for you.