.claude/skills/circuit-breaker-state-machine/SKILL.md
Use when protecting a service from repeatedly calling a failing dependency, when retry logic alone keeps hammering an already-down service, or when you need to fail fast after sustained failures and probe cautiously for recovery. Covers the three-state circuit breaker (Closed → Open → Half-Open), Polly v8 ResiliencePipeline configuration with FailureRatio and MinimumThroughput tuning, and correct retry + circuit breaker composition order. Domain: Resilience, Fault Tolerance. Level: Intermediate. Tags: circuit-breaker, resilience, polly, fault-tolerance, state-machine.
npx skillsauth add klod68/littlerae circuit-breaker-state-machineInstall 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.
When a downstream dependency fails, retry logic keeps hammering it — wasting resources, delaying responses, and preventing the dependency from recovering. The system needs to "fail fast" once it detects sustained failure, then cautiously probe for recovery.
┌──────────┐ failure threshold ┌──────────┐
│ CLOSED │ ──────────────────────► │ OPEN │
│ (normal) │ │ (reject) │
└──────────┘ └──────────┘
▲ │
│ success in half-open │ break duration expires
│ ▼
│ ┌───────────┐
└───────────────────────────── │ HALF-OPEN │
│ (probe) │
└───────────┘
| State | Behavior |
|-------|----------|
| Closed | Requests pass through. Failures are counted. When the failure ratio exceeds the threshold within a sampling window, transition to Open. |
| Open | Requests are immediately rejected with BrokenCircuitException. After the break duration, transition to Half-Open. |
| Half-Open | A limited number of probe requests are allowed through. If they succeed, transition to Closed. If they fail, transition back to Open. |
using Polly;
var pipeline = new ResiliencePipelineBuilder()
.AddCircuitBreaker(new CircuitBreakerStrategyOptions
{
FailureRatio = 0.5, // Open after 50% failures
SamplingDuration = TimeSpan.FromSeconds(30), // Within a 30-second window
MinimumThroughput = 10, // Need at least 10 calls to evaluate
BreakDuration = TimeSpan.FromSeconds(15), // Stay open for 15 seconds
ShouldHandle = new PredicateBuilder()
.Handle<HttpRequestException>()
.Handle<TimeoutException>(),
OnOpened = args =>
{
// Log at Warning — this is a meaningful state transition
logger.LogWarning("Circuit opened for {Duration} after {FailureRatio:P0} failure rate",
args.BreakDuration, args.Outcome.Exception?.Message);
return ValueTask.CompletedTask;
},
OnClosed = args =>
{
logger.LogInformation("Circuit closed — dependency recovered");
return ValueTask.CompletedTask;
},
OnHalfOpened = args =>
{
logger.LogInformation("Circuit half-opened — probing dependency");
return ValueTask.CompletedTask;
}
})
.Build();
Order matters: retry wraps circuit breaker — retries happen inside the circuit.
var pipeline = new ResiliencePipelineBuilder()
.AddRetry(new RetryStrategyOptions
{
MaxRetryAttempts = 3,
BackoffType = DelayBackoffType.Exponential,
Delay = TimeSpan.FromMilliseconds(500),
ShouldHandle = new PredicateBuilder()
.Handle<HttpRequestException>()
})
.AddCircuitBreaker(new CircuitBreakerStrategyOptions
{
FailureRatio = 0.5,
SamplingDuration = TimeSpan.FromSeconds(30),
MinimumThroughput = 10,
BreakDuration = TimeSpan.FromSeconds(15)
})
.Build();
builder.Services.AddHttpClient("MyApi")
.AddStandardResilienceHandler(); // Includes retry + circuit breaker + timeout
public sealed class CircuitBreakerOptions
{
public double FailureRatio { get; set; } = 0.5;
public TimeSpan SamplingDuration { get; set; } = TimeSpan.FromSeconds(30);
public int MinimumThroughput { get; set; } = 10;
public TimeSpan BreakDuration { get; set; } = TimeSpan.FromSeconds(15);
}
MinimumThroughput: Set high enough to avoid opening on a small sample. 2 failures out of 3 calls is not a pattern — it's noise.BrokenCircuitException: Callers must handle this explicitly — it means "don't even try." Map it to 503 Service Unavailable in API responses.Unhealthy / Degraded signal.tools
Use when cross-cutting concerns (logging, metrics, validation, authorization) are tangled into command handlers or service methods, when building database command pipelines with reorderable concerns, or when HTTP client pipelines or message handlers need composable, independently-replaceable processing stages. Covers ICommandInterceptor interface, InterceptorPipeline with reverse-chain construction, zero-cost Empty sentinel to skip overhead when no interceptors are registered, and ConfigureAwait(false) discipline for library code. Domain: Architecture, Cross-Cutting Concerns. Level: Intermediate. Tags: interceptor, pipeline, middleware, decorator, cross-cutting-concerns.
development
Use when writing integration tests for Razor Pages, MVC, or Minimal API applications to validate routing, middleware, page rendering, and HTTP behavior without a browser or live server, or when adding fast smoke tests to a CI pipeline. Covers WebApplicationFactory<Program> setup with public partial class Program, in-memory test server, AngleSharp HTML parsing, CSS selector assertions, redirect and status code testing, and a shared static fixture pattern for minimal per-test startup overhead. Domain: Testing, ASP.NET Core. Level: Intermediate. Tags: integration-testing, webapplicationfactory, razor-pages, anglesharp, http-testing.
development
Use when designing indexes for new tables, diagnosing slow queries that are not using indexes efficiently, reviewing index fragmentation and maintenance, or when the current indexing strategy results in key lookups, table scans, or missing index warnings. Covers clustered index key selection (narrow, unique, ever-increasing), non-clustered index design for query patterns, covering indexes with INCLUDE columns, filtered indexes for subset queries, composite index column ordering, DMV-based monitoring for missing and unused indexes, and rebuild vs reorganize maintenance thresholds. Domain: Database, Performance. Level: Intermediate. Tags: index, sql-server, covering-index, filtered-index, performance, dmv, maintenance.
development
Use when building a searchable in-memory catalog or registry for documentation sites, admin panels, or type/API browsers where you need keyword matching, fuzzy search, and ranked results without an external search engine or database. Covers RegistryService with weighted scoring across name, description, keywords, and method names; Levenshtein fuzzy matching; synonym expansion; category and subcategory filtering; and singleton DI registration for datasets of hundreds to low thousands of items. Domain: Search, Data Access Patterns. Level: Intermediate. Tags: search, registry, fuzzy-matching, in-memory, catalog, filtering.