Mehdi Lallouache
04/30/2026, 1:32 PMMarvin
04/30/2026, 1:32 PMMarvin
04/30/2026, 1:34 PMDaskTaskRunner.
The important bit is: retries are configured on the task, not on DaskTaskRunner.
Example:
python
from prefect import flow, task
from prefect_dask import DaskTaskRunner
@task(
retries=3,
retry_delay_seconds=10,
)
def bar():
...
@flow(task_runner=DaskTaskRunner())
def foo():
bar.submit()
Relevant retry parameters on @task
- `retries`: how many times to retry after failure
- `retry_delay_seconds`: delay before retrying
- can be a single number
- can also be a list of delays
- can also be generated dynamically in some cases
- `retry_jitter_factor`: adds jitter to retry delays
- `retry_condition_fn`: custom function to decide whether a failure should actually be retried
Example with more options:
python
from prefect import flow, task
from prefect_dask import DaskTaskRunner
def should_retry(task, task_run, state):
return True
@task(
retries=5,
retry_delay_seconds=[1, 5, 10, 30, 60],
retry_jitter_factor=0.5,
retry_condition_fn=should_retry,
)
def bar():
...
@flow(task_runner=DaskTaskRunner())
def foo():
futures = [bar.submit() for _ in range(10)]
Where to set them
- Set them on the task definition with @task(...)
- Optionally, Prefect also has defaults for task retries via settings, but the main place is still the task itself
What not to configure
- DaskTaskRunner itself does not have special retry parameters for Prefect task retries
- Dask is handling parallel execution; Prefect is handling task state/retry behavior
So in your case:
- foo uses DaskTaskRunner for parallelism
- bar can use retries exactly like any other Prefect task
- configure retries directly on bar
Docs / package:
- Prefect docs
- prefect-dask docs
If you want, I can also show:
1. a full example with submit() + retries + waiting on futures, or
2. how flow retries differ from task retries in this setup.Mehdi Lallouache
04/30/2026, 1:35 PMMarvin
04/30/2026, 1:35 PMMarvin
04/30/2026, 1:36 PMretry_jitter_factor adds randomness to your retry delay so that retries don’t all happen at the exact same moment.
Why that helps:
- if many parallel tasks fail together
- and all have retry_delay_seconds=10
- then without jitter they all retry again at t+10s
- that can create another spike against your API / DB / service
With jitter, Prefect spreads those retries out a bit.
Example:
python
@task(
retries=3,
retry_delay_seconds=10,
retry_jitter_factor=0.5,
)
def bar():
...
Here, the base retry delay is 10 seconds, and Prefect will apply some randomness around that delay so retries are staggered instead of synchronized.
This is especially useful with:
- DaskTaskRunner
- many concurrent tasks
- rate-limited APIs
- flaky downstream services
So conceptually:
- retry_delay_seconds = base delay
- retry_jitter_factor = how much randomness to add to that delay
If you want, I can also show a concrete example of the actual delay range Prefect uses for a given jitter factor.Mehdi Lallouache
04/30/2026, 1:37 PMMarvin
04/30/2026, 1:37 PMMarvin
04/30/2026, 1:38 PMretry_jitter_factor means the retry delay is randomized around the base delay, not just increased.
So for:
python
@task(
retries=3,
retry_delay_seconds=10,
retry_jitter_factor=0.5,
)
def bar():
...
the retry delay will be a random value in roughly this range:
- minimum: about 6.29s
- maximum: 15s
So it can be:
- shorter than 10 seconds
- longer than 10 seconds
It does not just add up to 50% extra delay. It jitterizes the delay within a bounded range.
Concrete example
With retry_delay_seconds=10 and retry_jitter_factor=0.5, one retry might happen after:
- 6.4s
- 8.6s
- 9.9s
- 11.2s
- 13.0s
- 14.8s
all valid possibilities.
Why this exists
If 100 Dask-backed tasks fail at once and all retry after exactly 10s, they stampede the downstream service again. Jitter spreads them out.
Rule of thumb
- retry_delay_seconds = target delay
- retry_jitter_factor = how widely Prefect can randomize around that target
If retry_jitter_factor is:
- 0 or unset: retry happens at exactly the base delay
- `0.5`: retry is randomized in a bounded window around the base delay
- larger values: wider spread
One subtle detail: Prefect uses a bounded distribution, so the spread is not perfectly symmetric, but the average delay stays close to the base value.
If you want, I can also show a tiny table for:
- jitter_factor=0.1
- 0.5
- 1.0
so you can see the approximate retry ranges side by side.