A circuit breaker protects a Node.js service from repeatedly waiting on a failing dependency. It tracks calls, opens after a configured failure condition, and temporarily rejects or falls back on new calls; after a wait, it permits a recovery probe. With Opossum, the key implementation details are to make failures visible to the breaker, coordinate timeouts with request cancellation, and choose thresholds for your workload rather than copying sample settings.
What a circuit breaker does
A breaker wraps calls to an asynchronous dependency such as an HTTP API or database. When calls are healthy, it lets them proceed. When failures cross a configured threshold, it stops sending calls for a period so callers do not keep spending time and resources on an unhealthy service. This contains the impact; it does not repair the dependency.
As an Amazon Associate I earn from qualifying purchases.
The pattern has three states:
- Closed: calls pass through, and the breaker records outcomes.
- Open: calls are rejected quickly or handled by a fallback instead of being sent to the dependency.
- Half-open: after the reset interval, a limited recovery attempt is allowed. Success closes the circuit; failure or timeout opens it again.
Microsoft describes the aim as preventing an application from repeatedly trying an operation likely to fail: Circuit Breaker pattern.
Implement a breaker with Opossum
Opossum wraps asynchronous functions in a Node.js circuit breaker. Its npm listing observed on October 5, 2026, reports version 10.0.0 and a Node.js engine requirement of >=22; check the listing and your deployment runtime when installing, since package metadata can change.
#1 Best Overall
This example protects a profile lookup using Fetch. It explicitly rejects unsuccessful HTTP responses so the breaker can count them as failures. The timeout and threshold values below mirror the package documentation’s illustrative example; they are not production recommendations.
const CircuitBreaker = require('opossum');
async function getProfile(userId, { signal } = {}) {
const response = await fetch(
`https://api.example.com/profiles/${encodeURIComponent(userId)}`,
{ signal }
);
// Fetch resolves for HTTP statuses such as 500; classify them explicitly.
if (!response.ok) {
throw new Error(`Profile API returned HTTP ${response.status}`);
}
return response.json();
}
const breaker = new CircuitBreaker(getProfile, {
timeout: 3000,
errorThresholdPercentage: 50,
resetTimeout: 30000
});
async function loadProfile(userId) {
try {
return await breaker.fire(userId);
} catch (error) {
// Map or propagate the failure according to this endpoint's contract.
throw new Error('Profile lookup is unavailable', { cause: error });
}
}
Opossum documents AbortController support for passing a signal to a protected function. The function must accept and use that signal, as the Fetch example does, for an aborted request. A breaker timeout by itself should not be assumed to cancel arbitrary underlying work: it may stop waiting while that work continues.
Rank #2
Choose settings for the dependency and workload
Opossum’s options express policy. The right values depend on normal latency, tolerated failure rate, request volume, and the cost of serving incomplete or stale data. Use observed behavior and an explicit latency budget to tune them.
| Option | What it controls | How to decide |
|---|---|---|
timeout |
How long the protected action may take before Opossum treats it as timed out. | Set it within the operation’s latency budget. Where possible, make the underlying request cancellable as well. See Opossum documentation. |
errorThresholdPercentage |
The failure percentage at which the circuit can open. | Choose a threshold that reflects the failure rate your application can tolerate; it is not a universal constant. |
volumeThreshold |
The minimum number of calls in the rolling window before the breaker is eligible to open. | Use it to avoid reacting to a very small sample, while accounting for how quickly your service needs to detect a failure. |
resetTimeout |
How long the circuit remains open before a recovery attempt can move it to half-open. | Balance giving the dependency time to recover against the delay before testing it again. |
capacity |
The maximum number of concurrent protected executions; excess calls are rejected. | Set a concurrency limit appropriate to the dependency and your own resource budget. This controls concurrent work at the protected boundary. |
Check the installed Opossum version’s documentation for option behavior and defaults. The settings above should be validated against real dependency latency and call volume, not adopted solely because they appear in an example.
Rank #3
Classify failures deliberately
A breaker only reacts to outcomes it can observe. With Fetch, an HTTP 500 response does not reject the promise: inspect response.ok or the status code and throw, return a classified result, or otherwise report the response according to your policy. Without that step, an unsuccessful HTTP response can be recorded as a successful call.
Decide which outcomes should count against the dependency. Network errors, timeouts, server errors, and client errors are not interchangeable. A 4xx response caused by invalid caller input may say nothing about dependency health, while a particular API may use specific statuses to signal temporary unavailability. Opossum cannot infer these application semantics; your protected function must classify them.
Rank #4
Use timeouts, retries, and breakers for different jobs
- Timeout: bounds how long one operation may take.
- Retry: makes another attempt, often with bounded retries and backoff, when an error may be transient.
- Circuit breaker: stops repeated attempts after failures or timeouts indicate that continuing to call is unlikely to help.
These patterns can coexist, but retries add load. Bound attempts, use backoff where appropriate, and consider how retry duration fits inside the caller’s latency budget. A breaker is not a substitute for a timeout, and it does not make an unsafe retry safe. See Microsoft’s circuit breaker guidance and AWS guidance on retry with backoff.
Add fallbacks and telemetry carefully
A fallback is useful only when the operation has a valid degraded result. For example, a stale or partial value may be acceptable for some read paths; inventing a plausible profile when correctness requires the current result is not. Opossum supports fallbacks and emits a fallback event. Treat fallback execution as visible degradation, not as proof that the request succeeded normally.
Opossum documents events including open, halfOpen, close, timeout, failure, and fallback. Connect relevant events to logs or metrics with the dependency identity and useful request context. This helps distinguish a failing dependency, a breaker that is open, and a fallback that is serving users.
Check platform support before adopting an implementation
Opossum is a concrete Node.js option, but implementation choice should account for supported Node.js versions, maintenance, timeout and cancellation behavior, failure classification, half-open controls, fallback and observability APIs, concurrency limits, licensing, and support requirements. Red Hat documents a supported Opossum-based add-on for Red Hat build of Node.js; that may matter to teams using that platform, but it is not a general requirement for Opossum users: Red Hat build of Node.js documentation.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.




