Circuit Breaker with Opossum in NestJS
- Pavol Megela
- Nov 14, 2024
- 4 min read

In modern applications, we often rely on external services, APIs, or databases. When these dependencies fail our entire system suffer. This is where the Circuit Breaker pattern comes into a play.
A Circuit Breaker acts as a safeguard, stopping repeated calls to failing services and allowing them time to recover. This prevents cascading failures and improves system stability.
We look at the simple implementation of a Circuit Breaker in NestJS using Opossum library. We break down the key concepts and show how to integrate it into a real-world NestJS service.
Understanding circuit breakers
A Circuit Breaker is a simple concept. It monitors calls to an external service and if failures happen too often, it temporarily blocks further requests. This prevents your system from getting stuck waiting for a service that’s down, instead it saves the work for later and once the service is available again, it will execute it.
Circuit breakers have three states:
Closed - Everything is working fine. Requests flow normally
Open - Too many failures happened, so the circuit "breaks" blocking requests for a while
Half-Open – After a timeout it allows a few test requests. If they succeed, the circuit closes. If they fail, it stays open
Think of it like an automatic switch that stops sending requests to a broken service and tries again later. This protects your app from unnecessary slowdowns and crashes.
Next we take a look on how to set up a Circuit breaker in NestJS project with Opossum.
Installing and configuring Opossum
Let’s install Opossum a circuit breaker library for Node.js. You can read more about it here npmjs/opossum.
npm install opossum
Once installed we can use it to wrap an API call or any external dependency to prevent failures from affecting our app. Next, we’ll implement it inside a NestJS service.
Basic configurations
Opossum provides several configuration options to control how the circuit breaker behaves. Here are the most important ones
timeout - Maximum time (in milliseconds) a request can take before it's considered failed
errorThresholdPercentage - The failure percentage that triggers the circuit to open (50 means if 50% of requests fail -> the circuit opens)
resetTimeout - How long (in milliseconds) the circuit stays open before trying again in the half-open state
Now let's look at the coding part
import * as CircuitBreaker from 'opossum';
const options = {
timeout: 3 * 1000,
errorThresholdPercentage: 50,
resetTimeout: 5 * 1000,
};
const breaker = new CircuitBreaker(yourFunction, options);
Implementing a Circuit Breaker
To implement the circuit breaker, we need to do the following:
Create an instance of Opossum
Configure the circuit breaker
Wrap the API call inside the circuit breaker - This is the execution we want to monitor for failures
Set a fallback function - This defines what should happen if the external service is unavailable (logging the failure, triggering alternative flows, or saving the event for later processing)
Here’s how the coding part looks
@Injectable()
export class ExternalService {
private breaker: CircuitBreaker;
public constructor(private readonly httpService: HttpService) {
const options = {
timeout: 3 * 1000,
errorThresholdPercentage: 50,
resetTimeout: 5 * 1000,
};
this.breaker = new CircuitBreaker(this.fetchData.bind(this), options);
this.breaker.fallback(() => {
// Here you will:
// Log the failure
// Trigger alternative flow
// Save failed event for later processing
});
}
public async getData() {
return this.breaker.fire();
}
private async fetchData(): Promise<ExampleResponse> {
return this.httpService.get('https://api.example.com/data').toPromise();
}
}
How it works:
The circuit breaker wraps fetchData() and defines failure callback
getData() gets called instead of fetchData(). This ensures that all requests pass through the circuit breaker logic.
fetchData() is being called by getData() and it makes an API request
If failures exceed the threshold requests are blocked for a while
The fallback function is triggered when the circuit is open, ensuring that failures are logged or saved for later processing instead of just returning a static response.
This ensures that if the external service is unavailable, the application won't keep making failing requests. Instead, it waits before retrying, improving system resilience.
Circuit Breaker Events in Opossum
Opossum provides event listeners that allow us to track the circuit breaker’s state and respond accordingly. These events help with monitoring, logging, and triggering alternative actions when failures occur.
Here are the key events you can listen for
open - Circuit Breaker Opened
Triggered when the failure threshold is reached, and the circuit moves to the open state (blocking further requests).
this.breaker.on('open', () => {
console.warn('Circuit breaker opened! External service is failing.');
});
close - Circuit Breaker Closed
Triggered when the circuit recovers and moves back to the closed state (allowing requests again).
Use Case: If you’ve stored failed requests (for example in Outbox Table), this is the time to reprocess them.
this.breaker.on('close', () => {
console.log('Circuit breaker closed. Service is healthy again.');
// Trigger reprocessing of failed requests
});
halfOpen - Circuit Breaker Half-Open
After the circuit opens, a timeout starts as per options.resetTimeout. Once this period ends, opossum enters the halfOpen state. The next circuit activation will execute the action again. Success closes the circuit and triggers the close event; failure or timeout returns it to the open state.
this.breaker.on('halfOpen', () => {
console.log('Circuit breaker is half-open. Testing service availability...');
});
Best practices
When using a circuit breaker it’s important to follow best practices to ensure reliability. Here are key considerations:
Choose the right timeout
Set a reasonable timeout value based on your expected API response time
Too short -> Unnecessary failures
Too long -> Wasted time waiting for slow responses
Tune failure threshold and reset timeout There's no one-size-fits-all, you need to observe your system and learn how it works. See what settings works best for you.
errorThresholdPercentage should match the acceptable failure rate of your system
resetTimeout should allow enough time for recovery before retrying
Use fallbacks wisely
A fallback function should not just return a default response but also:
Log the failure
Save the request for later processing, store them in an Outbox Table or a queue for later retry
Notify monitoring systems
Avoid overuse
Not every API call needs a circuit breaker
Use it for critical external services, not every database or microservice call
Test failure scenarios
Simulate failures (timeouts, API downtime) to ensure the circuit breaker behaves as expected
Ensure fallbacks and logging work properly
That's all for now
Circuit breakers are essential for building resilient applications, preventing cascading failures, and handling unreliable external services. By integrating Opossum with NestJS, we can protect our APIs from slow or failing dependencies while ensuring system stability. Now go ahead and implement it in your project.
コメント