Skip to main content

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

StrategyPatternUse CaseLink
Exponential BackoffDelays grow exponentially (1s, 2s, 4s, 8s...)External APIs, distributed systemsLearn more
Linear BackoffDelays increase linearly (100ms, 300ms, 500ms...)Database operations, lock contentionLearn more
Fixed DelaySame delay each time (2s, 2s, 2s...)File system, simple scenarios, testingLearn more

Advanced Strategies

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 delay
  • EqualJitter() - Random between half and full delay
  • DecorrelatedJitter() - 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

Advanced

Best Practices

  1. Always add jitter - Prevents thundering herd in distributed systems
  2. Set reasonable caps - Don't wait longer than 1-5 minutes
  3. Start conservative - Begin with shorter delays, increase if needed
  4. Use fixed delays in tests - Ensures deterministic timing
  5. Monitor metrics - Track actual retry patterns in production
  6. Match strategy to domain - APIs ≠ Databases ≠ Files
  7. Document decisions - Explain why you chose specific settings

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