How to Use Microsoft.Extensions.Polly for Resilient HTTP Requests in .NET

In modern applications, network failures and transient faults are common. Microsoft.Extensions.Polly helps handle these failures gracefully by offering policies such as retries, timeouts, circuit breakers, and more. This blog will help you set up Polly in a .NET application to make your HTTP requests more resilient.

But before we proceed, I want to give you a quick explanation of what “resilient” means and why we’re discussing it now.

In software, resilence refers to the ability of a system to handle unexpected issues and continue functioning with minimal disruption. A resilient application can recover from temporary problems or even significant failures without crashing or causing a poor user experience.

Why Resilience Matters

In real-word appllications, you may encounter issues like:

  • Network Failures: Temporary internet outages or server downtimes.
  • Service Overloads: When a service you depend on becomes overloaded and responds slowly or fails temporarily.
  • Transient Errors: Short-lived issues that could resolve on their own with a simple retry, line timeouts or server overloads.

Without resilience, these issues could make your application unreliable, frustrating users and causing downtime.

How Resilience Works in Practice

To build resilience, developers use strategies like:

  • Retries: Automatically trying an operation again if it fails the first time, giving it a chance to succeed if the issue was temporary.
  • Circuit Breakers: Detecting repeated failures and stopping requests for a short time, allowing systems to recover before more requests come in.
  • Timeouts: Setting a limit on how long the application waits for a response, so it doesn’t get “stuck” waiting indefinitely.
  • Fallbacks: Providing an alternative response or functionality if the original request fails, so the application can continue to work in a limited way.

Now that we understand what resilience is and its importance, let’s see Microsoft.Extensions.Polly in action, which will help your application achieve resilience.

Step 1: Set Up Your Project

1. Create a new .NET project (if you don’t have one):

Bash
dotnet new console -o PollyDemo
cd PollyDemo

2. Add the required packages:

Bash
dotnet add package Microsoft.Extensions.Http
dotnet add package Microsoft.Extensions.Http.Polly

Step 2: Configuring Polly Policies

With Microsoft.Extensions.Polly, you can define policies for retries, timeouts, and circuit breakers.

1. Add Polly policies in a service configuration.

Go to your Program.cs file and configure the HttpClient with Polly policies in the IServiceCollection:

C#
using System;
using System.Net.Http;
using Microsoft.Extensions.DependencyInjection;
using Polly;
using Polly.Extensions.Http;

var serviceProvider = new ServiceCollection()
    .AddHttpClient("PollyDemoClient", client =>
    {
        client.BaseAddress = new Uri("https://jsonplaceholder.typicode.com/");
    })
    .AddPolicyHandler(GetRetryPolicy())
    .AddPolicyHandler(GetCircuitBreakerPolicy())
    .BuildServiceProvider();

var httpClient = serviceProvider.GetRequiredService<IHttpClientFactory>().CreateClient("PollyDemoClient");

2. Define the Retry Policy.

Here, we’ll retry failed requests up to 3 times, with an exponential back-off delay:

C#
static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
    return HttpPolicyExtensions
        .HandleTransientHttpError()  // Handles 5xx and 408 errors
        .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
}

3. Define the Circuit Breaker Policy.

The circuit breaker policy will “break” the circuit after 2 consecutive failures and stay open for 30 seconds:

C#
static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
{
    return HttpPolicyExtensions
        .HandleTransientHttpError()
        .CircuitBreakerAsync(2, TimeSpan.FromSeconds(30));
}

Step 3: Using HttpClient with Polly Policies

Now that we have configured HttpClient with Polly policies, let’s make a request:

1. Write the code to make a request:

C#
static async Task MakeRequest(HttpClient httpClient)
{
    try
    {
        var response = await httpClient.GetAsync("posts/1");
        if (response.IsSuccessStatusCode)
        {
            var content = await response.Content.ReadAsStringAsync();
            Console.WriteLine("Response received successfully:");
            Console.WriteLine(content);
        }
        else
        {
            Console.WriteLine($"Request failed with status code {response.StatusCode}");
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Request failed with exception: {ex.Message}");
    }
}

2. Execute the request:

Call the MakeRequest method to see Polly in action.

C#
await MakeRequest(httpClient);

Run the application to observe retry and circuit breaker behavior when network errors occur.

With Polly integrated into your HTTP client, you now have an extra layer of resilience in your .NET application. By using policies like retries and circuit breakers, you can handle transient failures gracefully, ensuring a smoother experience for users.

This setup can be customized further by chaining other policies, like timeouts and fallbacks, according to your needs.

Assi Arai
Assi Arai
Articles: 24