How do retries and exponential backoff work in ML pipelines?
Retries let an ML pipeline run a failed task again when the failure may be temporary. Exponential backoff increases the wait between attempts so a busy or unavailable service has time to recover.
This is useful for intermittent storage timeouts, temporarily unavailable workers, and throttled API calls. It is not a way to fix invalid data, missing permissions, or broken code.
A beginner-friendly example
A food-delivery company runs a nightly pipeline that downloads new orders from object storage before training a delivery-time model.
At 2:00 AM, the download task encounters a temporary storage-service timeout. Immediately repeating the request many times could worsen the outage, so the team configures 3 retries after the first attempt, with a 10-second initial wait and a backoff multiplier of 2.
Using the illustrative formula
delay before retry n = min(10 × 2^(n−1), 60) seconds
the scheduled attempts are:
- Initial attempt: Starts at 0 seconds; suppose it fails immediately.
- Retry 1: Wait 10 seconds; starts at 10 seconds.
- Retry 2: Wait 20 more seconds; starts at 30 seconds.
- Retry 3: Wait 40 more seconds; starts at 70 seconds.
Thus 3 retries means up to 4 total attempts, not 3 total attempts. If each attempt also takes time before failing, actual start times are later. The delays total 70 seconds in this simplified scenario, excluding execution and scheduler waiting time.
A retry policy can also set a maximum delay; with this example's 60-second cap, any later exponential wait would be limited to 60 seconds.
Why not retry instantly or forever?
Immediate repeated failures create a retry storm: many tasks can overwhelm the same object store, feature service, or model registry as it recovers.
A bounded policy reduces that pressure:
- Initial retry delay: For example, 10 seconds.
- Multiplier: Usually 2 for conventional exponential backoff.
- Maximum retries: Stop after a fixed number of additional attempts.
- Maximum delay: Prevents waits from growing without bound.
- Jitter: Add a small random variation so hundreds of workers do not retry in lockstep.
The formula above is an illustration, not a promise of exact timing in every orchestrator. Scheduler load, jitter, and framework-specific backoff algorithms can alter retry times.
Which ML errors should be retried?
Usually reasonable to retry, within limits:
- A network connection reset while fetching an immutable dataset.
- HTTP 429 or throttling from a model registry, subject to a provided
Retry-Afterresponse. - A short-lived service outage or an interrupted worker.
Usually fail fast:
- Missing required dataset columns or an incompatible schema.
- A malformed model configuration.
- Invalid access credentials or permission denial.
- A deterministic code error reproduced on every attempt.
A task should report the actual failure category instead of blindly retrying every exception. Rate-limit responses and service documentation may prescribe waits different from a generic exponential formula.
What does Airflow configuration look like?
The following Airflow task decorator uses the standard retry controls:
PYTHONfrom datetime import timedelta from airflow.sdk import dag, task @dag(schedule=None, catchup=False) def delivery_ml(): @task( retries=3, retry_delay=timedelta(seconds=10), retry_exponential_backoff=True, max_retry_delay=timedelta(minutes=1), ) def fetch_training_data(): # Download and validate an immutable dataset snapshot. ... fetch_training_data() delivery_ml()
This is a minimal illustrative DAG; an actual ML task must implement the download logic and distinguish retryable from permanent errors. Airflow supports retry policies for more selective per-exception handling in current releases.
Important: Airflow's exact exponential-backoff timing can differ from the simple 10/20/40-second teaching example. Do not assume its scheduler implements that formula verbatim.
Why does retry safety matter in ML?
Consider a training task that writes model-latest.pkl and registers a model. It successfully registers the model but crashes before reporting completion. If the orchestrator retries the whole task, it may create two registry entries or overwrite an artifact unexpectedly.
A retry is safe only when repeating the work has a controlled outcome. Helpful approaches include:
- Use stable run identifiers: Associate outputs with the workflow run and task attempt or a deterministic artifact identity.
- Prefer immutable inputs and versioned outputs: Avoid silently replacing datasets and model versions.
- Make registration idempotent: Repeatedly registering the same logical result should not create duplicates.
- Commit outputs deliberately: Write temporary artifacts first, validate them, and publish/promote only after success.
- Test partial failure: Simulate a crash after the external write but before task completion, then verify retry behavior.
The next question examines how to decide whether a pipeline step is retry-safe in more detail.
What happens after all retries fail?
When attempts are exhausted, the task becomes failed and the orchestrator applies its configured downstream rules. Quality-critical actions—such as promoting a newly trained model—should not proceed as though a required input task succeeded.
Monitor attempt count, delay, final failure cause, and total task latency. A pipeline that eventually succeeds only after frequent retries may still be unhealthy.
Question 55 explained how dependencies govern the *order* of tasks. Retries govern repeated attempts of one task after a failure, while its dependency position generally remains unchanged.
In short: Use bounded retries with exponential backoff and jitter for temporary failures; fail fast for permanent errors; and design ML task side effects so retrying cannot corrupt artifacts or duplicate releases.
Sources & Research References
Learning Sequence
MLOps Curriculum
How do you decide whether an ML pipeline step is retry-safe?
Explore Related Questions
Deepen your understanding across related MLOps topics.