Skip to content

Retry & Backoff Policies

Workflow-Level Retries

Set default retry behavior for all steps in a workflow.

Step-Level Retries

Override retry configuration for individual steps.

Backoff Strategies

Choose from different retry delay patterns.

export default defineWorkflow('payment-processing', {
retries: {
limit: 3,
delay: '30 seconds',
backoff: 'exponential'
}
}, async (flow) => {
// Step uses workflow's retry policy
await flow.do('process payment', async () => {
return processPayment(flow.params);
});
});

Constant

Fixed delay between retries. Best for predictable operations.

backoff: 'constant' // delay: 30s, 30s, 30s

Linear

Delay increases linearly. Good for gradually increasing wait times.

backoff: 'linear' // delay: 30s, 60s, 90s

Exponential

Delay increases exponentially. Best for handling transient failures.

backoff: 'exponential' // delay: 30s, 60s, 120s

Transient Failures

Temporary issues like network timeouts or service unavailability. These should be retried.

Permanent Failures

Unrecoverable errors like invalid input or business rule violations. These should not be retried.

See the main Error Handling page for more on classifying errors.

export default defineWorkflow('payment-processing', async (flow) => {
await flow.do('process payment', {
retries: {
limit: 3,
delay: '30 seconds',
backoff: 'exponential'
}
}, async () => {
try {
return await processPayment(flow.params);
} catch (error) {
if (error.code === 'INVALID_CARD') {
// Permanent failure - don't retry
throw new NonRetryableError(error);
}
// Transient failure - will be retried
throw error;
}
});
});

IdentityFlow supports the circuit breaker pattern via step options to prevent repeated calls to failing services. See Step Options in API Reference for configuration details.

export default defineWorkflow('api-integration', async (flow) => {
await flow.do(
'external api call',
{
retries: { limit: 3, delay: '30 seconds', backoff: 'exponential' },
circuitBreaker: { failureThreshold: 5, resetTimeout: '1 minute' },
},
async () => {
return await externalApiCall(flow.params);
},
);
});

Choose Appropriate Limits

Set reasonable retry limits based on operation type and consider downstream service limits.

Configure Smart Delays

Start with shorter delays for quick recovery and use longer delays for resource-intensive operations.

Select the Right Strategy

Use constant backoff for predictable operations, linear for gradual scaling, and exponential for transient failures.

export default defineWorkflow(
'order-processing',
{
// Default retry policy for all steps
retries: { limit: 3, delay: '30 seconds', backoff: 'exponential' },
},
async (flow) => {
// Uses default retry policy
const order = await flow.do('validate order', async () => {
return validateOrder(flow.params);
});
// Custom retry policy for critical operation
const payment = await flow.do(
'process payment',
{ retries: { limit: 5, delay: '1 minute', backoff: 'exponential' } },
async () => {
return processPayment(order);
},
);
// Minimal retries for notification
await flow.do(
'send notification',
{ retries: { limit: 2, delay: '10 seconds', backoff: 'constant' } },
async () => {
return sendNotification(payment);
},
);
},
);