Retry Delays
Retry delays determine how long to wait between retry attempts. Choosing the right strategy is crucial for balancing quick recovery with preventing service overload.
Quick Start: Common Retry Patterns
Web API Calls (Most Common)
// Recommended for external API calls
context.UseExponentialBackoffDelay(
baseDelay: TimeSpan.FromSeconds(1),
multiplier: 2.0,
maxDelay: TimeSpan.FromMinutes(1));
Why this pattern:
- Exponential backoff gives services time to recover
- Prevents thundering herd problems
- Balanced for typical API rate limits
Database Operations
// Recommended for database retry scenarios
context.UseLinearBackoffDelay(
baseDelay: TimeSpan.FromMilliseconds(100),
increment: TimeSpan.FromMilliseconds(200), // Required - adds 200ms per retry
maxDelay: TimeSpan.FromSeconds(5));
Why this pattern:
- Linear growth is predictable for database connection pools
- Shorter delays work well for transient lock contention
- Conservative max delay prevents long-running transactions
File Processing
// Recommended for file system operations
context.UseFixedDelay(TimeSpan.FromSeconds(2));
Why this pattern:
- File system recovery is typically immediate
- Fixed delay provides predictable behavior
- Simple and effective for I/O operations
Decision Flow for Choosing Retry Strategy
Basic Implementation
Basic Pipeline with Retry Delays
using NPipeline;
using NPipeline.Pipeline;
public sealed class RetryQuickstartPipeline : IPipelineDefinition
{
public void Define(PipelineBuilder builder, PipelineContext context)
{
// Configure retry delay strategy based on operation type
context.UseExponentialBackoffDelay(
baseDelay: TimeSpan.FromSeconds(1),
multiplier: 2.0,
maxDelay: TimeSpan.FromMinutes(1));
var source = builder.AddSource<ApiSource, ApiResponse>("api-source");
var transform = builder.AddTransform<DataTransform, ApiResponse, ProcessedData>("transform");
var sink = builder.AddSink<DataSink, ProcessedData>("sink");
builder.Connect(source, transform);
builder.Connect(transform, sink);
// Configure retry options
builder.WithRetryOptions(new PipelineRetryOptions(
MaxItemRetries: 3,
MaxNodeRestartAttempts: 2,
MaxSequentialNodeAttempts: 5
));
}
}
Per-Node Retry Configuration
public void Define(PipelineBuilder builder, PipelineContext context)
{
var source = builder.AddSource<DataSource, string>("source");
// Fast retries for in-memory operations
context.UseFixedDelay(TimeSpan.FromMilliseconds(50));
var memoryTransform = builder.AddTransform<MemoryTransform, string, string>("memory-ops");
// Slower retries for external API calls
context.UseExponentialBackoffDelay(
baseDelay: TimeSpan.FromSeconds(1),
multiplier: 2.0,
maxDelay: TimeSpan.FromMinutes(1));
var apiTransform = builder.AddTransform<ApiTransform, string, string>("api-ops");
// Default retries for other operations
var sink = builder.AddSink<DataSink, string>("sink");
builder.Connect(source, memoryTransform);
builder.Connect(memoryTransform, apiTransform);
builder.Connect(apiTransform, sink);
}
Available Strategies
Basic Strategies
| Strategy | Pattern | Use Case | Link |
|---|---|---|---|
| Exponential Backoff | Delays grow exponentially (1s, 2s, 4s, 8s...) | External APIs, distributed systems | Learn more |
| Linear Backoff | Delays increase linearly (100ms, 300ms, 500ms...) | Database operations, lock contention | Learn more |
| Fixed Delay | Same delay each time (2s, 2s, 2s...) | File system, simple scenarios, testing | Learn more |
Advanced Strategies
- Decorrelated Jitter - Adaptive backoff for high concurrency
- Custom Strategies - Fibonacci, polynomial, time-of-day aware
- Fallback Strategies - Cascade through multiple strategies
- Circuit Breaker Pattern - Combine with circuit breaker
Key Concepts
Jitter
Add randomization to prevent synchronized retries:
context.UseExponentialBackoffDelay(
baseDelay: TimeSpan.FromSeconds(1),
multiplier: 2.0,
maxDelay: TimeSpan.FromMinutes(1),
jitterStrategy: JitterStrategies.FullJitter()); // Add jitter
Why: Without jitter, multiple clients retry at the same time, overwhelming the service ("thundering herd").
Jitter Options:
NoJitter()- Exact delays (use for testing only)FullJitter()- Random 0 to calculated delayEqualJitter()- Random between half and full delayDecorrelatedJitter()- Adapts to system load
Retry Cap (maxDelay)
Always set a maximum delay to prevent indefinitely long waits:
context.UseExponentialBackoffDelay(
baseDelay: TimeSpan.FromSeconds(1),
multiplier: 2.0,
maxDelay: TimeSpan.FromMinutes(1)); // Don't wait longer than 1 minute
Topics
Guides
- Exponential Backoff - For external APIs and services
- Linear Backoff - For database operations
- Fixed Delay - For file operations and testing
Advanced
- Advanced Patterns - Custom and adaptive strategies
- Testing Retries - Test retry behavior deterministically
- Monitoring Metrics - Observe retry behavior in production
Best Practices
- Always add jitter - Prevents thundering herd in distributed systems
- Set reasonable caps - Don't wait longer than 1-5 minutes
- Start conservative - Begin with shorter delays, increase if needed
- Use fixed delays in tests - Ensures deterministic timing
- Monitor metrics - Track actual retry patterns in production
- Match strategy to domain - APIs ≠ Databases ≠ Files
- Document decisions - Explain why you chose specific settings
Related Documentation
- Retry Configuration - Basic retry options (MaxItemRetries, MaxNodeRestartAttempts)
- Resilience Overview - Understanding resilience concepts
- Error Handling - How error handling integrates with retries
- Circuit Breakers - Combine with circuit breaker patterns
- Troubleshooting - Common retry issues and solutions
- Architecture - Deep dive into implementation
Next Steps
- Choose a strategy based on your use case (API? Database? Files?)
- Read the dedicated guide for your chosen strategy
- Test retry behavior with Testing Retries