PollyOpenAI 1.0.0
dotnet add package PollyOpenAI --version 1.0.0
NuGet\Install-Package PollyOpenAI -Version 1.0.0
<PackageReference Include="PollyOpenAI" Version="1.0.0" />
<PackageVersion Include="PollyOpenAI" Version="1.0.0" />
<PackageReference Include="PollyOpenAI" />
paket add PollyOpenAI --version 1.0.0
#r "nuget: PollyOpenAI, 1.0.0"
#:package PollyOpenAI@1.0.0
#addin nuget:?package=PollyOpenAI&version=1.0.0
#tool nuget:?package=PollyOpenAI&version=1.0.0
PollyOpenAI
Polly v8 resilience for OpenAI and Azure OpenAI API calls.
Automatic retry with exponential back-off, Retry-After header support, circuit breaker, and per-request timeout — wired up in one line via IHttpClientBuilder.
Why PollyOpenAI?
OpenAI and Azure OpenAI APIs regularly return transient errors in production:
| Scenario | Without PollyOpenAI | With PollyOpenAI |
|---|---|---|
| 429 Rate limit | Request fails immediately | Retries after Retry-After delay |
| 500 / 503 outage | Request fails, user sees error | Retries with exponential back-off |
| Sustained outage | Every request waits for timeout | Circuit opens, fails fast immediately |
| Slow response | Request hangs for 100s+ | Times out per-attempt, retried quickly |
| Request body | Silently lost on retry | Buffered and re-sent on every attempt |
Installation
dotnet add package PollyOpenAI
Quick Start
// Program.cs
builder.Services.AddHttpClient("openai", client =>
{
client.BaseAddress = new Uri("https://api.openai.com/");
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}");
})
.AddPollyOpenAIResilience();
// Inject IHttpClientFactory and pass to the OpenAI SDK
var httpClient = httpClientFactory.CreateClient("openai");
var openAIClient = new OpenAIClient(new ApiKeyCredential(apiKey),
new OpenAIClientOptions { Transport = new HttpClientTransport(httpClient) });
Azure OpenAI
builder.Services.AddHttpClient("azure-openai", client =>
{
client.BaseAddress = new Uri("https://my-resource.openai.azure.com/");
})
.AddPollyOpenAIResilience(options =>
{
options.MaxRetries = 5;
options.BaseDelay = TimeSpan.FromSeconds(2);
options.MaxDelay = TimeSpan.FromSeconds(60);
});
Named client shortcut
// Registers IHttpClientFactory with a client named "PollyOpenAI"
builder.Services.AddPollyOpenAIHttpClient(
baseAddress: new Uri("https://api.openai.com/"),
configure: options => options.MaxRetries = 4);
// Resolve
var client = httpClientFactory.CreateClient("PollyOpenAI");
Configuration
.AddPollyOpenAIResilience(options =>
{
// Retry
options.MaxRetries = 3; // default: 3
options.BaseDelay = TimeSpan.FromSeconds(1); // default: 1 s
options.MaxDelay = TimeSpan.FromSeconds(30); // default: 30 s
options.RespectRetryAfterHeader = true; // default: true
// Circuit breaker
options.CircuitBreakerMinimumThroughput = 5; // default: 5
options.CircuitBreakerFailureRatio = 0.5; // default: 0.5 (50%)
options.CircuitBreakerSamplingDuration = TimeSpan.FromSeconds(30);
options.CircuitBreakerBreakDuration = TimeSpan.FromSeconds(30);
// Timeout (per request attempt)
options.RequestTimeout = TimeSpan.FromSeconds(100); // default: 100 s
// Customise which status codes trigger retry
options.TransientStatusCodes = new HashSet<HttpStatusCode>
{
HttpStatusCode.TooManyRequests, // 429
HttpStatusCode.InternalServerError, // 500
HttpStatusCode.BadGateway, // 502
HttpStatusCode.ServiceUnavailable, // 503
HttpStatusCode.GatewayTimeout, // 504
};
})
How it works
The pipeline order (outer → inner):
Request
└─► Retry (exponential back-off, honours Retry-After)
└─► Circuit Breaker (opens on sustained failures)
└─► Timeout (per-attempt)
└─► HttpClient → OpenAI API
Retry — on
OpenAITransientException(thrown for any status code inTransientStatusCodes), waits for theRetry-Afterdelta if present, otherwise uses exponential back-off with jitter. The request body is buffered before the first send so it can be re-transmitted on every attempt.Circuit Breaker — after enough failures within the sampling window the circuit opens, all subsequent calls fail-fast with
BrokenCircuitExceptionuntil the break duration elapses. Prevents hammering a degraded API.Timeout — enforces a per-attempt deadline; throws
TimeoutRejectedExceptionif the OpenAI API doesn't respond in time.
Exception types
| Exception | When thrown |
|---|---|
OpenAITransientException |
Transient HTTP status received (429, 5xx). Has .StatusCode, .RetryAfter, .Response. |
BrokenCircuitException |
Circuit is open; caught after retry is exhausted. |
TimeoutRejectedException |
Per-attempt timeout exceeded. |
Comparison
Raw HttpClient |
Microsoft.Extensions.Http.Resilience |
PollyOpenAI | |
|---|---|---|---|
| Retry on 429 | ❌ | ✅ (partial) | ✅ |
Respects Retry-After header |
❌ | ❌ | ✅ |
| Retry on 5xx | ❌ | ✅ | ✅ |
| Circuit breaker | ❌ | ✅ | ✅ |
| Per-request timeout | ❌ | ✅ | ✅ |
| Request body re-sent on retry | ❌ | ❌ | ✅ |
| OpenAI-specific status defaults | ❌ | ❌ | ✅ |
| Zero config | ✅ | ❌ | ✅ |
Related Packages
| Package | Downloads | Description |
|---|---|---|
| PollyChaos | Chaos engineering / fault injection for Polly v8 | |
| PollyMediatR | Polly v8 pipelines for MediatR request handlers | |
| PollyEFCore | Polly v8 resilience for EF Core queries and SaveChanges | |
| PollyHealthChecks | ASP.NET Core health checks for Polly v8 circuit breakers | |
| PollyBackoff | Custom back-off strategies for Polly v8 |
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Microsoft.Extensions.Http (>= 8.0.1)
- Microsoft.Extensions.Options (>= 8.0.2)
- Polly.Core (>= 8.7.0)
-
net9.0
- Microsoft.Extensions.Http (>= 8.0.1)
- Microsoft.Extensions.Options (>= 8.0.2)
- Polly.Core (>= 8.7.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 50 | 6/23/2026 |
Initial release. Retry on 429/5xx with Retry-After header support, circuit breaker, timeout, and DI extensions for IHttpClientBuilder.