What is Polly and why is it needed?
\n\nPolly is a powerful and flexible library for .NET (C#, F#, VB.NET) designed for handling transient faults and improving application resilience. It implements resilience patterns such as Retry, Circuit Breaker, Timeout, Bulkhead Isolation, and Cache.
\n\nIn the modern world of microservice architecture and cloud computing, applications constantly interact with external resources: databases, web services, APIs. These interactions can be unreliable — network errors, temporary service unavailability, request rate limits. Polly allows you to handle such situations elegantly, without writing cumbersome code with try-catch blocks.
\n\nMain usage scenarios:
\n- \n
- Retry: Automatically retry an operation on a transient error. \n
- Circuit Breaker: Stop making calls if the service consistently returns errors, to give it time to recover. \n
- Timeout: Limit the execution time of an operation. \n
- Bulkhead: Limit the number of concurrent operations so that one "bad" operation does not block the entire thread pool. \n
- Cache: Cache the results of successful operations. \n
- Fallback: Execute an alternative action in case of failure. \n
Installing Polly
\n\nPolly is distributed via NuGet — the package manager for .NET. It can be installed in several ways:
\n\nVia Package Manager Console (Visual Studio)
\nInstall-Package Polly\n\nVia .NET CLI
\ndotnet add package Polly\n\nVia PackageReference (in .csproj file)
\n<PackageReference Include="Polly" Version="8.2.0" />\n\nAfter installation, add the using directives to your code:
\nusing Polly;\nusing Polly.Retry;\nusing Polly.CircuitBreaker;\nusing Polly.Timeout;\nusing Polly.Bulkhead;\nusing Polly.Caching;\nusing Polly.Fallback;\nusing Polly.Wrap;\n\nQuick Start with Code Example
\n\nLet's look at a simple example: we have a method that calls an external API, and we want to retry the call 3 times if an exception occurs.
\n\nusing System;\nusing System.Net.Http;\nusing System.Threading.Tasks;\nusing Polly;\nusing Polly.Retry;\n\npublic class ApiClient\n{\n private readonly HttpClient _httpClient;\n private readonly AsyncRetryPolicy _retryPolicy;\n\n public ApiClient()\n {\n _httpClient = new HttpClient();\n \n // Create a retry policy\n _retryPolicy = Policy\n .Handle<HttpRequestException>() // Which exceptions to handle\n .Or<TimeoutException>() // Or timeout\n .WaitAndRetryAsync(\n 3, // Number of attempts\n retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), // Exponential backoff\n onRetry: (exception, timeSpan, retryCount, context) =>\n {\n Console.WriteLine($"Attempt {retryCount} failed. Retrying in {timeSpan.Seconds} sec. Error: {exception.Message}");\n }\n );\n }\n\n public async Task<string> GetDataAsync(string url)\n {\n // Execute the request using the policy\n return await _retryPolicy.ExecuteAsync(async () =>\n {\n var response = await _httpClient.GetAsync(url);\n response.EnsureSuccessStatusCode();\n return await response.Content.ReadAsStringAsync();\n });\n }\n}\n\n// Usage\npublic class Program\n{\n public stat