Leaders Logo

Building a Circuit Breaker Mechanism Using .NET

Introduction to the Circuit Breaker Pattern

The Circuit Breaker pattern is a technique used in software development to increase the resilience of applications, especially in distributed architectures (PUNITHAVATHY; PRIYA, 2024). This pattern acts like a switch that prevents calls to services from failing repeatedly, allowing the system to recover before attempting a new call. This is particularly useful in scenarios where latency and failures of external services can impact application performance. Essentially, the Circuit Breaker helps to prevent an entire system from failing due to issues in a single component.

Purpose

The Circuit Breaker is inspired by electrical systems, where a circuit can be interrupted to prevent overloads. In the context of software, it works similarly, allowing the system to "turn off" calls to a failing service (PUNITHAVATHY; PRIYA, 2024). This prevents failures in one service from affecting the entire system, allowing it to recover before resuming normal operations (FOWLER, 2014). Thus, we can consider that the Circuit Breaker is:

  • A mechanism that prevents repeated calls to unstable services, protecting the system from cascading failures.
  • Inspired by electrical circuit breakers, "opening" the circuit when it detects continuous failures.
  • Composed of three states: Closed (normal), Open (calls blocked), and Half-Open (test to resume operations) (POLLY, 2023).
  • Used to improve the stability and resilience of distributed applications (MICROSOFT, 2025).

Similarly, it is important to understand that the Circuit Breaker is not:

  • A simple retry mechanism: although it can be combined with retries, its main function is to interrupt calls to problematic services.
  • A substitute for fallback: although it can be used alongside fallback strategies, they serve distinct purposes.
  • A monitoring tool: although it provides information about failures, it does not replace observability systems.
  • A load balancer: its function is to interrupt calls to unstable services, not to distribute traffic among healthy services.

Why Use Circuit Breaker?

When an external service fails, subsequent calls to that service can cause unnecessary overload and latency, leading to a cascading effect that can compromise application stability (COSTA et al., 2022). The Circuit Breaker pattern helps to avoid this situation, protecting the application from cascading failures. It allows the application to react quickly to issues, freeing resources and enabling the system to recover more swiftly. Additionally, the Circuit Breaker can be configured to provide feedback to the user, such as friendly error messages, instead of silent failures or generic error messages.

In a world where reliance on external services is increasingly common, implementing a Circuit Breaker becomes a best practice (COSTA et al., 2022). It not only enhances the application’s resilience but also facilitates monitoring and maintenance of the system, allowing development teams to quickly identify issues that may arise due to external failures.

Implementing Circuit Breaker in .NET

To implement a Circuit Breaker mechanism in .NET, we can use the Polly library, which is a resilience library for .NET that simplifies the implementation of patterns such as retry, timeout, and circuit breaker. Polly provides a powerful and flexible API, allowing developers to configure resilience policies that meet the specific needs of their applications (PUNITHAVATHY; PRIYA, 2024).

Installing Polly

To start using Polly, we need to install the Polly package via NuGet (POLLY, 2023). This can be done through the NuGet console with the following command:

Install-Package Polly

Alternatively, you can install Polly using the Visual Studio package manager. Simply search for "Polly" in the NuGet packages section and click install. Once Polly is installed, you can start implementing your resilience policies in your application.

Configuring the Circuit Breaker

After installation, we can configure a Circuit Breaker. The following code demonstrates how to create a Circuit Breaker policy that opens the circuit after 3 consecutive failures and keeps it open for 30 seconds. This configuration is a starting point and can be adjusted according to the specific needs of your application.


using Polly;
using System;
using System.Net.Http;
using System.Threading.Tasks;

public class CircuitBreakerExample
{
    private static readonly HttpClient httpClient = new HttpClient();
    
    public async Task<string> FetchDataAsync(string url)
    {
        var circuitBreakerPolicy = Policy
            .Handle<HttpRequestException>()
            .CircuitBreaker(3, TimeSpan.FromSeconds(30));

        try
        {
            return await circuitBreakerPolicy.ExecuteAsync(async () => 
            {
                var response = await httpClient.GetAsync(url);
                response.EnsureSuccessStatusCode();
                return await response.Content.ReadAsStringAsync();
            });
        }
        catch (BrokenCircuitException)
        {
            return "Circuit is open. Please try again later.";
        }
    }
}

In this example, we are using Polly's Circuit Breaker policy to define that if three consecutive failures occur when trying to access a URL, the circuit will open and remain so for 30 seconds. During this time, any attempt to access the service will result in a BrokenCircuitException, which can be handled to inform the user that the service is temporarily unavailable.

Testing the Circuit Breaker

To test the behavior of the Circuit Breaker, you can simulate calls to a failing service. Here’s an example of how you could write a simple test to check if the Circuit Breaker is functioning as expected:


public async Task TestCircuitBreaker()
{
    var circuitBreakerExample = new CircuitBreakerExample();
    
    for (int i = 0; i < 10; i++)
    {
        var result = await circuitBreakerExample.FetchDataAsync("http://example.com/fail");
        Console.WriteLine(result);
    }
}
    

In this test, we are calling a service that we know will fail. After three failures, the Circuit Breaker should open, and subsequent attempts to call the service should result in the message "Circuit is open. Please try again later." being printed to the console. This confirms that the Circuit Breaker is functioning as expected and is protecting the application from unnecessary overloads.

Monitoring the Circuit Breaker

Monitoring the state of the Circuit Breaker is crucial to understanding your application’s performance. Polly allows you to log Circuit Breaker state events, which can be extremely useful for debugging and maintenance. Here’s an example of how to do this:


var circuitBreakerPolicy = Policy
    .Handle<HttpRequestException>()
    .CircuitBreaker(
        handledEventsAllowedBeforeBreaking: 3,
        durationOfBreak: TimeSpan.FromSeconds(30),
        onBreak: (exception, breakDelay) =>
        {
            Console.WriteLine(
            $"[OPEN] Circuit opened due to: {exception.Message}. Waiting {breakDelay.TotalSeconds} seconds before retrying.");
        },
        onReset: () =>
        {
            Console.WriteLine(
            "[CLOSED] Circuit closed. Operations resumed successfully.");
        },
        onHalfOpen: () =>
        {
            Console.WriteLine(
            "[HALF-OPEN] Circuit is half-open. Testing service availability...");
        });
    

In this example, we are adding two event handlers: one for when the circuit is opened (onBreak) and another for when the circuit is reset (onReset). These events allow you to log information about the Circuit Breaker state, helping to identify failure patterns and adjust configurations as needed.

Conclusion

The Circuit Breaker pattern contributes to increasing the resilience of .NET applications. Using the Polly library, it is possible to implement this technique simply and efficiently. Monitoring the state of the Circuit Breaker and adjusting its settings are fundamental steps to ensure that your application continues to function reliably, even in the face of external failures. By integrating the Circuit Breaker into your development strategy, you will provide a more robust and secure foundation for your applications, improving user experience and system reliability in the long term.

References

  • PUNITHAVATHY, E.; PRIYA, N. Comparative Study of Static Resilience Patterns Over Dynamically Modified Resilience Patterns. 2024. reference.Description
  • PUNITHAVATHY, E.; PRIYA, N. Auto retry circuit breaker for enhanced performance in microservice applications. International Journal of Electrical & Computer Engineering (2088-8708), vol. 14, no. 2, 2024. reference.Description
  • COSTA, Thiago M. et al. Performance Evaluation of Two Resilience Patterns for Microservices: Retry and Circuit Breaker. In: Brazilian Symposium on Computer Networks and Distributed Systems (SBRC). SBC, 2022. p. 517-530. reference.Description
  • POLLY, GitHub. Polly: The .NET resilience and transient-fault-handling library. Available at: https://www.pollydocs.org . Accessed on: April 15, 2025. reference.Description
  • FOWLER, M. Circuit Breaker. 2014. Available at https://martinfowler.com/bliki/CircuitBreaker.html. Accessed on: April 15, 2025. reference.Description
  • MICROSOFT. Circuit Breaker pattern. Available at https://learn.microsoft.com/en-us/azure/architecture/patterns/circuit-breaker. Accessed on: April 15, 2025. reference.Description
About the author