Skip to main content
This quickstart guide will help you create your first resilience pipeline with Polly and execute code with automatic retry and timeout handling.

Prerequisites

  • .NET 6.0 or later
  • Basic understanding of C# and async/await

Step 1: Install Polly.Core

1

Add the package

Install the Polly.Core package using the .NET CLI:
dotnet add package Polly.Core
2

Verify installation

The package should now appear in your project file:
<PackageReference Include="Polly.Core" Version="8.*" />

Step 2: Create your first resilience pipeline

Create a resilience pipeline that combines retry and timeout strategies:
using Polly;

// Create an instance of builder that exposes various extensions for adding resilience strategies
ResiliencePipeline pipeline = new ResiliencePipelineBuilder()
    .AddRetry(new RetryStrategyOptions()) // Add retry using the default options
    .AddTimeout(TimeSpan.FromSeconds(10)) // Add 10 seconds timeout
    .Build(); // Builds the resilience pipeline

// Execute the pipeline asynchronously
await pipeline.ExecuteAsync(static async token => 
{ 
    // Your custom logic goes here
    var response = await httpClient.GetAsync("https://api.example.com/data", token);
    return response;
}, cancellationToken);
The pipeline executes strategies in the order they are added. In this example, timeout wraps retry, which wraps your callback.

Step 3: Configure advanced retry behavior

Customize the retry strategy with exponential backoff and jitter:
var pipeline = new ResiliencePipelineBuilder()
    .AddRetry(new RetryStrategyOptions
    {
        MaxRetryAttempts = 3,
        Delay = TimeSpan.FromSeconds(1),
        BackoffType = DelayBackoffType.Exponential,
        UseJitter = true,
        OnRetry = args =>
        {
            Console.WriteLine($"Retry attempt {args.AttemptNumber}");
            return ValueTask.CompletedTask;
        }
    })
    .AddTimeout(TimeSpan.FromSeconds(10))
    .Build();

Step 4: Use dependency injection (optional)

For ASP.NET Core and other DI-enabled applications, install Polly.Extensions:
dotnet add package Polly.Extensions
Then register your resilience pipeline:
using Microsoft.Extensions.DependencyInjection;
using Polly;

var services = new ServiceCollection();

// Define a resilience pipeline with the name "my-pipeline"
services.AddResiliencePipeline("my-pipeline", builder =>
{
    builder
        .AddRetry(new RetryStrategyOptions())
        .AddTimeout(TimeSpan.FromSeconds(10));
});

// Build the service provider
var serviceProvider = services.BuildServiceProvider();

// Retrieve a ResiliencePipelineProvider that dynamically creates and caches the resilience pipelines
var pipelineProvider = serviceProvider.GetRequiredService<ResiliencePipelineProvider<string>>();

// Retrieve your resilience pipeline using the name it was registered with
ResiliencePipeline pipeline = pipelineProvider.GetPipeline("my-pipeline");

// Alternatively, you can use keyed services to retrieve the resilience pipeline
pipeline = serviceProvider.GetRequiredKeyedService<ResiliencePipeline>("my-pipeline");

// Execute the pipeline
await pipeline.ExecuteAsync(static async token =>
{
    // Your custom logic goes here
});

Complete example: HTTP client with resilience

Here’s a complete example showing how to use Polly with HttpClient in an ASP.NET Core application:
using Microsoft.Extensions.DependencyInjection;
using Polly;

var builder = WebApplication.CreateBuilder(args);

// Register HttpClient with Polly resilience pipeline
builder.Services.AddHttpClient("ResilientClient")
    .AddResilienceHandler("my-pipeline", builder =>
    {
        builder
            .AddRetry(new RetryStrategyOptions
            {
                MaxRetryAttempts = 3,
                Delay = TimeSpan.FromSeconds(1),
                BackoffType = DelayBackoffType.Exponential,
                UseJitter = true
            })
            .AddCircuitBreaker(new CircuitBreakerStrategyOptions
            {
                FailureRatio = 0.5,
                MinimumThroughput = 10,
                SamplingDuration = TimeSpan.FromSeconds(30),
                BreakDuration = TimeSpan.FromSeconds(30)
            })
            .AddTimeout(TimeSpan.FromSeconds(10));
    });

var app = builder.Build();

// Use the HttpClient in a controller or service
app.MapGet("/fetch-data", async (IHttpClientFactory factory) =>
{
    var client = factory.CreateClient("ResilientClient");
    var response = await client.GetAsync("https://api.example.com/data");
    var content = await response.Content.ReadAsStringAsync();
    return Results.Ok(content);
});

app.Run();

What’s next?

Core Concepts

Learn about resilience pipelines and strategies in depth

Resilience Strategies

Explore all available resilience strategies

Dependency Injection

Advanced DI patterns and configuration

Telemetry

Monitor your resilience pipelines

Common patterns

Generic pipelines for typed results

Use ResiliencePipeline<TResult> when you need to handle results:
var pipeline = new ResiliencePipelineBuilder<HttpResponseMessage>()
    .AddRetry(new RetryStrategyOptions<HttpResponseMessage>
    {
        ShouldHandle = new PredicateBuilder<HttpResponseMessage>()
            .Handle<HttpRequestException>()
            .HandleResult(r => !r.IsSuccessStatusCode)
    })
    .Build();

HttpResponseMessage response = await pipeline.ExecuteAsync(
    async token => await httpClient.GetAsync("https://api.example.com", token),
    cancellationToken);

Multiple independent pipelines

Create different pipelines for different scenarios:
// Fast-failing pipeline for user-facing operations
var userPipeline = new ResiliencePipelineBuilder()
    .AddRetry(new RetryStrategyOptions { MaxRetryAttempts = 2 })
    .AddTimeout(TimeSpan.FromSeconds(3))
    .Build();

// Resilient pipeline for background operations
var backgroundPipeline = new ResiliencePipelineBuilder()
    .AddRetry(new RetryStrategyOptions { MaxRetryAttempts = 5 })
    .AddTimeout(TimeSpan.FromSeconds(30))
    .Build();
Pipeline instances are lightweight and can be reused across multiple executions. Create them once and store them for the lifetime of your application.

Build docs developers (and LLMs) love