Overview
The ResiliencePipelineBuilder class is used to create instances of ResiliencePipeline by combining multiple resilience strategies. Strategies are executed in the order they were added to the builder.
Classes
ResiliencePipelineBuilder
Builder for creating non-generic ResiliencePipeline instances.
public sealed class ResiliencePipelineBuilder : ResiliencePipelineBuilderBase
ResiliencePipelineBuilder<TResult>
Builder for creating generic ResiliencePipeline<TResult> instances that handle specific result types.
public sealed class ResiliencePipelineBuilder<TResult> : ResiliencePipelineBuilderBase
The type of result the pipeline will handle.
Properties
Name
public string? Name { get; set; }
The name of the builder. This property is included in telemetry produced by individual resilience strategies.Default value: null
InstanceName
public string? InstanceName { get; set; }
The instance name of the builder. Used to differentiate between multiple builder instances with the same Name in telemetry.Default value: null
TimeProvider
public TimeProvider? TimeProvider { get; set; }
A TimeProvider that is used by strategies that work with time (e.g., retry delays, timeouts).Default value: null (uses TimeProvider.System)
ContextPool
public ResilienceContextPool? ContextPool { get; set; }
The ResilienceContextPool associated with the builder. A custom pool can be used to configure custom behavior for context creation.Default value: null (uses ResilienceContextPool.Shared)
TelemetryListener
public TelemetryListener? TelemetryListener { get; set; }
The TelemetryListener that is used by Polly to report resilience events. This property is used by the telemetry infrastructure and should not be used directly by user code.Default value: null
Methods
Build
// Non-generic builder
public ResiliencePipeline Build()
// Generic builder
public ResiliencePipeline<TResult> Build()
Builds the resilience pipeline with all configured strategies.
An instance of ResiliencePipeline or ResiliencePipeline<TResult>.
Thrown when the builder has invalid configuration.
The builder cannot be reused after calling Build(). Attempting to add more strategies will throw an InvalidOperationException.
Extension Methods
AddPipeline
public static TBuilder AddPipeline<TBuilder>(
this TBuilder builder,
ResiliencePipeline pipeline)
where TBuilder : ResiliencePipelineBuilderBase
public static ResiliencePipelineBuilder<TResult> AddPipeline<TResult>(
this ResiliencePipelineBuilder<TResult> builder,
ResiliencePipeline<TResult> pipeline)
Adds an already created pipeline instance to the builder.
pipeline
ResiliencePipeline
required
The pipeline instance to add.
The same builder instance for chaining.
Thrown when pipeline is null.
Throws
InvalidOperationException
Thrown when the builder was already used to create a pipeline.
AddStrategy
// For proactive strategies
public static TBuilder AddStrategy<TBuilder>(
this TBuilder builder,
Func<StrategyBuilderContext, ResilienceStrategy> factory,
ResilienceStrategyOptions options)
where TBuilder : ResiliencePipelineBuilderBase
// For reactive strategies (non-generic builder)
public static ResiliencePipelineBuilder AddStrategy(
this ResiliencePipelineBuilder builder,
Func<StrategyBuilderContext, ResilienceStrategy<object>> factory,
ResilienceStrategyOptions options)
// For reactive strategies (generic builder)
public static ResiliencePipelineBuilder<TResult> AddStrategy<TResult>(
this ResiliencePipelineBuilder<TResult> builder,
Func<StrategyBuilderContext, ResilienceStrategy<TResult>> factory,
ResilienceStrategyOptions options)
Adds a resilience strategy to the builder.
factory
Func<StrategyBuilderContext, ResilienceStrategy>
required
The factory that creates a resilience strategy.
options
ResilienceStrategyOptions
required
The options associated with the strategy.
The same builder instance for chaining.
Thrown when builder, factory, or options is null.
Throws
InvalidOperationException
Thrown when the builder was already used to create a pipeline.
Thrown when options is invalid.
AddStrategy (without options)
// For proactive strategies
public static TBuilder AddStrategy<TBuilder>(
this TBuilder builder,
Func<StrategyBuilderContext, ResilienceStrategy> factory)
where TBuilder : ResiliencePipelineBuilderBase
// For reactive strategies (non-generic builder)
public static ResiliencePipelineBuilder AddStrategy(
this ResiliencePipelineBuilder builder,
Func<StrategyBuilderContext, ResilienceStrategy<object>> factory)
// For reactive strategies (generic builder)
public static ResiliencePipelineBuilder<TResult> AddStrategy<TResult>(
this ResiliencePipelineBuilder<TResult> builder,
Func<StrategyBuilderContext, ResilienceStrategy<TResult>> factory)
Adds a resilience strategy to the builder without explicit options.
factory
Func<StrategyBuilderContext, ResilienceStrategy>
required
The factory that creates a resilience strategy.
The same builder instance for chaining.
Example Usage
Basic Pipeline
using Polly;
var pipeline = new ResiliencePipelineBuilder()
.AddRetry(new RetryStrategyOptions
{
MaxRetryAttempts = 3,
Delay = TimeSpan.FromSeconds(1)
})
.AddTimeout(TimeSpan.FromSeconds(10))
.Build();
await pipeline.ExecuteAsync(async ct =>
{
await MakeHttpRequestAsync(ct);
});
Named Pipeline with Telemetry
var pipeline = new ResiliencePipelineBuilder()
{
Name = "my-api-client",
InstanceName = "production"
}
.AddRetry(new RetryStrategyOptions())
.AddCircuitBreaker(new CircuitBreakerStrategyOptions())
.Build();
Generic Pipeline for HTTP Responses
var pipeline = new ResiliencePipelineBuilder<HttpResponseMessage>()
.AddRetry(new RetryStrategyOptions<HttpResponseMessage>
{
ShouldHandle = new PredicateBuilder<HttpResponseMessage>()
.Handle<HttpRequestException>()
.HandleResult(r => !r.IsSuccessStatusCode),
MaxRetryAttempts = 3,
BackoffType = DelayBackoffType.Exponential
})
.AddTimeout(TimeSpan.FromSeconds(30))
.Build();
var response = await pipeline.ExecuteAsync(async ct =>
{
return await httpClient.GetAsync(apiUrl, ct);
});
Composing Multiple Pipelines
// Create a base pipeline for common strategies
var basePipeline = new ResiliencePipelineBuilder()
.AddRetry(new RetryStrategyOptions())
.Build();
// Create a specialized pipeline that includes the base
var specializedPipeline = new ResiliencePipelineBuilder()
.AddPipeline(basePipeline)
.AddCircuitBreaker(new CircuitBreakerStrategyOptions())
.AddTimeout(TimeSpan.FromSeconds(5))
.Build();
Custom Strategy
var pipeline = new ResiliencePipelineBuilder()
.AddStrategy(context => new CustomResilienceStrategy(),
new ResilienceStrategyOptions
{
Name = "custom-strategy"
})
.Build();
Using Custom TimeProvider for Testing
using Microsoft.Extensions.Time.Testing;
var fakeTimeProvider = new FakeTimeProvider();
var pipeline = new ResiliencePipelineBuilder
{
TimeProvider = fakeTimeProvider
}
.AddRetry(new RetryStrategyOptions
{
Delay = TimeSpan.FromSeconds(5)
})
.Build();
// In tests, you can control time
fakeTimeProvider.Advance(TimeSpan.FromSeconds(5));
Strategy Execution Order
Strategies are executed in the order they are added to the builder. The first strategy added wraps all subsequent strategies.
var pipeline = new ResiliencePipelineBuilder()
.AddRetry(new RetryStrategyOptions()) // Executes first (outermost)
.AddCircuitBreaker(new CircuitBreakerStrategyOptions()) // Executes second
.AddTimeout(TimeSpan.FromSeconds(10)) // Executes third (innermost)
.Build();
In this example:
- Retry wraps everything - if the circuit breaker or timeout fails, retry can attempt again
- Circuit breaker wraps timeout - protects against repeated timeout failures
- Timeout wraps the actual operation - ensures individual attempts don’t take too long
The order of strategies matters significantly. Generally, you want retry as the outermost layer, followed by circuit breaker, then timeout or rate limiter for the innermost layers.