Building a Resilient .NET API with Circuit Breaker

I'm a highly motivated and experienced developer expertise in leveraging the power of .NET Core Technology. Currently collaborating with an Australian company based in Nusa Dua, Bali, Indonesia, to deliver innovative application development services that push the boundaries of what technology can achieve, and also contribute to the ever-evolving landscape of the global IT industry
Modern backend systems rarely work in isolation. Most APIs depend on external services such as payment providers, weather services, authentication servers, or other microservices.
But what happens when one of those dependencies fails?
Without proper protection, your service can quickly become unstable due to cascading failures.
One of the most common resilience patterns used in distributed systems is Circuit Breaker.
In this article we will explore:
What Circuit Breaker is
Why we need it
Its benefits and trade-offs
When to use it
A practical example in .NET
Real architecture diagrams
What is Circuit Breaker?
Circuit Breaker is a resilience pattern used to prevent an application from repeatedly trying to execute an operation that is likely to fail.
It acts similarly to an electrical circuit breaker in your house.
When too many failures occur, the circuit breaker opens and stops calls to the failing service temporarily.
Instead of waiting for slow failures or timeouts, the application fails fast and protects itself from overload.
Circuit Breaker typically has three states:
Closed
Open
Half-Open
Circuit Breaker State Machine
CLOSED
Normal state.
Requests flow to the external service.
OPEN
Requests are blocked immediately to prevent further failures.
HALF-OPEN
A limited number of requests are allowed to test if the service has recovered.
Why Do We Need Circuit Breaker?
In distributed systems, services depend on other services.
If one service becomes slow or unavailable, repeated retries can cause cascading failures.
Example scenario:
Service A → Service B → Database
If Service B fails, Service A may continuously retry the request.
Consequences:
Thread pool exhaustion
Increased latency
Resource overload
System-wide instability
Circuit Breaker prevents this situation by stopping calls early.
Benefits of Using Circuit Breaker
Using Circuit Breaker provides several advantages.
1. Fail Fast
Instead of waiting for timeouts, requests fail immediately.
2. Protect System Resources
Avoids unnecessary calls to failing services.
3. Prevent Cascading Failures
Protects the entire system from dependency failures.
4. Improve System Stability
Keeps your application responsive even when external services fail.
The Downsides of Circuit Breaker
Although powerful, Circuit Breaker is not always the perfect solution.
1. Increased Complexity
It introduces additional logic and configuration into your application.
2. Temporary Blocking
If configured incorrectly, healthy services might be blocked.
3. Harder Debugging
Failures may originate from the circuit breaker instead of the service itself.
When Should We Use Circuit Breaker?
Circuit Breaker is particularly useful when:
Your service depends on external APIs
Your system uses microservices architecture
Some dependencies may become slow or unstable
Network calls are frequent and costly
Examples:
Payment gateways
Weather APIs
Third-party authentication providers
Internal microservices communication
Example Case in .NET
Let's implement Circuit Breaker in a .NET Web API.
In this example we call a weather service from Open-Meteo.
Architecture Overview
Registering a Typed HttpClient with Resilience
In .NET we can configure resilience policies using the built-in HTTP resilience tools.
builder.Services
.AddHttpClient<IWeatherApiClient, WeatherApiClient>(client =>
{
client.BaseAddress = new Uri("https://api.open-meteo.com/");
})
.AddResilienceHandler("weather-pipeline", pipeline =>
{
pipeline.AddRetry(new HttpRetryStrategyOptions
{
MaxRetryAttempts = 3,
Delay = TimeSpan.FromSeconds(2)
});
pipeline.AddCircuitBreaker(new HttpCircuitBreakerStrategyOptions
{
FailureRatio = 0.5,
MinimumThroughput = 4,
BreakDuration = TimeSpan.FromSeconds(15)
});
});
This configuration means:
Retry failed calls up to 3 times
If 50% of requests fail
After 4 requests
The circuit will open for 15 seconds
Example HTTP Client Implementation
public class WeatherApiClient : IWeatherApiClient
{
private readonly HttpClient _httpClient;
public WeatherApiClient(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<OpenMeteoResponse?> GetWeatherAsync()
{
var response = await _httpClient.GetAsync(
"v1/forecast?latitude=-8.65&longitude=115.22¤t_weather=true"
);
response.EnsureSuccessStatusCode();
return await response.Content.ReadFromJsonAsync<OpenMeteoResponse>();
}
}
What Happens When the External API Fails?
If the external service returns repeated failures:
404
404
404
404
The circuit breaker transitions to OPEN.
At this point, requests will fail immediately.
BrokenCircuitException
This prevents unnecessary calls to the failing service.
Request Flow Visualization
Pros and Cons of Circuit Breaker
| Pros | Cons |
|---|---|
| Prevent cascading failures | Adds complexity |
| Fail fast responses | Requires proper tuning |
| Protects system resources | Misconfiguration can block healthy services |
| Improves system resilience | Harder debugging |
Conclusion
Circuit Breaker is a critical resilience pattern for modern distributed systems.
By preventing repeated calls to failing services, it helps maintain system stability and protects valuable resources.
When combined with other resilience strategies like:
Retry
Timeout
Rate limiting
Caching
it becomes a powerful tool for building robust backend systems.
If your application depends on external APIs or microservices, implementing Circuit Breaker is a strong step toward production-grade reliability.





