Skip to main content

Command Palette

Search for a command to run...

Building a Resilient .NET API with Circuit Breaker

Updated
5 min read
Building a Resilient .NET API with Circuit Breaker
D

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&current_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.