skills/resilience/polly-resilience/SKILL.md
Use when building Polly v8 resilience pipelines with retry, timeout, or fallback.
npx skillsauth add faysilalshareef/dotnet-ai-kit polly-resilienceInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Microsoft.Extensions.Http.Resilience for HTTP client resilience (Polly v8)AddStandardResilienceHandler() for sensible defaults// Applies retry + circuit breaker + total timeout out of the box
builder.Services.AddHttpClient("OrdersApi", client =>
{
client.BaseAddress = new Uri("https://api.orders.{Company}.com");
})
.AddStandardResilienceHandler();
builder.Services.AddHttpClient("PaymentGateway", client =>
{
client.BaseAddress = new Uri("https://payments.example.com");
})
.AddResilienceHandler("payment-pipeline", pipeline =>
{
// Retry with exponential backoff + jitter
pipeline.AddRetry(new HttpRetryStrategyOptions
{
MaxRetryAttempts = 3,
Delay = TimeSpan.FromMilliseconds(500),
BackoffType = DelayBackoffType.Exponential,
UseJitter = true,
ShouldHandle = new PredicateBuilder<HttpResponseMessage>()
.HandleResult(r =>
r.StatusCode == HttpStatusCode.TooManyRequests ||
r.StatusCode >= HttpStatusCode.InternalServerError)
});
// Circuit breaker
pipeline.AddCircuitBreaker(new HttpCircuitBreakerStrategyOptions
{
FailureRatio = 0.5,
SamplingDuration = TimeSpan.FromSeconds(30),
MinimumThroughput = 10,
BreakDuration = TimeSpan.FromSeconds(15)
});
// Timeout per attempt
pipeline.AddTimeout(TimeSpan.FromSeconds(5));
});
// For database, message queue, or other non-HTTP operations
builder.Services.AddResiliencePipeline("database-retry", pipeline =>
{
pipeline
.AddRetry(new RetryStrategyOptions
{
MaxRetryAttempts = 3,
Delay = TimeSpan.FromSeconds(1),
BackoffType = DelayBackoffType.Exponential,
ShouldHandle = new PredicateBuilder()
.Handle<SqlException>()
.Handle<TimeoutException>()
})
.AddTimeout(TimeSpan.FromSeconds(30));
});
// Consuming via DI
public sealed class DataService(
[FromKeyedServices("database-retry")] ResiliencePipeline pipeline,
IDbConnectionFactory connectionFactory)
{
public async Task<Order?> GetOrderAsync(
Guid id, CancellationToken ct)
{
return await pipeline.ExecuteAsync(async token =>
{
using var conn = connectionFactory.CreateConnection();
return await conn.QuerySingleOrDefaultAsync<Order>(
"SELECT * FROM Orders WHERE Id = @Id",
new { Id = id });
}, ct);
}
}
// Pipeline with typed result
builder.Services.AddResiliencePipeline<string, HttpResponseMessage>(
"external-api", pipeline =>
{
pipeline
.AddRetry(new RetryStrategyOptions<HttpResponseMessage>
{
MaxRetryAttempts = 2,
ShouldHandle = new PredicateBuilder<HttpResponseMessage>()
.HandleResult(r => !r.IsSuccessStatusCode)
})
.AddTimeout(TimeSpan.FromSeconds(10));
});
builder.Services.AddResiliencePipeline<string, OrderResponse?>(
"order-with-fallback", pipeline =>
{
pipeline
.AddFallback(new FallbackStrategyOptions<OrderResponse?>
{
FallbackAction = _ =>
Outcome.FromResultAsValueTask<OrderResponse?>(null),
ShouldHandle = new PredicateBuilder<OrderResponse?>()
.Handle<HttpRequestException>()
.Handle<TimeoutRejectedException>()
})
.AddRetry(new RetryStrategyOptions<OrderResponse?>
{
MaxRetryAttempts = 2
})
.AddTimeout(TimeSpan.FromSeconds(5));
});
// Send parallel requests to reduce tail latency
builder.Services.AddHttpClient("search-api")
.AddResilienceHandler("hedging", pipeline =>
{
pipeline.AddHedging(new HttpHedgingStrategyOptions
{
MaxHedgedAttempts = 2,
Delay = TimeSpan.FromMilliseconds(200)
});
});
Request → Fallback → Retry → Circuit Breaker → Timeout → HTTP Call
↓
Response
Strategies execute from outermost (first added) to innermost (last added).
Microsoft.Extensions.Http.Resilience packageAddStandardResilienceHandler callsAddResilienceHandler or AddResiliencePipeline callsPolly package (v7 — migration candidate)ResiliencePipeline injectionMicrosoft.Extensions.Http.Resilience| Strategy | Use When | |----------|----------| | Standard resilience handler | Default for all HTTP clients | | Custom retry | Specific error codes or delay requirements | | Circuit breaker | Downstream service prone to cascading failure | | Timeout | Preventing indefinite waits | | Fallback | Returning cached/default data when service is down | | Hedging | Latency-sensitive operations with redundant backends |
data-ai
Use when about to claim work is complete, fixed, passing, or ready — before committing, creating PRs, or moving to the next task. Requires running verification commands and confirming output before making any success claims.
development
Use when encountering any bug, test failure, build error, or unexpected behavior — before proposing fixes or making changes.
development
Use when checkpointing, wrapping up, or handing off an AI-assisted development session.
development
Use when following the Specification-Driven Development lifecycle from plan through ship.