# How the Circuit Breaker Pattern Is Implemented in the Minisearch Server Utilities

> Discover how the circuit breaker pattern is implemented in Minisearch server utilities. Learn about its three-state model to prevent cascading failures in async operations.

- Repository: [Victor Nogueira/minisearch](https://github.com/felladrin/minisearch)
- Tags: internals
- Published: 2026-03-01

---

**The Minisearch server provides a stand-alone, generic circuit breaker in [`server/utils/circuitBreaker.ts`](https://github.com/felladrin/minisearch/blob/main/server/utils/circuitBreaker.ts) that follows the classic three-state model (CLOSED, OPEN, HALF_OPEN) to prevent cascading failures in async operations.**

The `felladrin/minisearch` repository includes a robust server-side implementation of the **circuit breaker pattern** designed to protect external API calls and other flaky async operations. Located entirely within [`server/utils/circuitBreaker.ts`](https://github.com/felladrin/minisearch/blob/main/server/utils/circuitBreaker.ts), this utility offers a key-agnostic, fully typed TypeScript solution that tracks failure rates and automatically cuts off traffic to failing services. Understanding this implementation helps developers configure resilient LLM integrations and third-party API consumers within the Minisearch ecosystem.

## Core Architecture and State Management

The circuit breaker relies on a strongly typed state machine and configurable thresholds to determine when to block or allow traffic.

### Type Definitions and Configuration

At the top of [`server/utils/circuitBreaker.ts`](https://github.com/felladrin/minisearch/blob/main/server/utils/circuitBreaker.ts), the implementation defines a `CircuitState` union type ([line 1](https://github.com/felladrin/minisearch/blob/main/server/utils/circuitBreaker.ts#L1)) that restricts the breaker to three valid states: `"CLOSED"`, `"OPEN"`, and `"HALF_OPEN"`. The configuration interface `CircuitBreakerOptions` ([lines 3‑7](https://github.com/felladrin/minisearch/blob/main/server/utils/circuitBreaker.ts#L3-L7)) exposes three critical parameters:

- **failureThreshold**: Number of consecutive failures before opening the circuit.
- **resetTimeout**: Milliseconds to wait before attempting recovery (transitioning to HALF_OPEN).
- **successThreshold**: Successful calls required in HALF_OPEN state to close the circuit.

Default values are provided via `defaultOptions` ([lines 16‑20](https://github.com/felladrin/minisearch/blob/main/server/utils/circuitBreaker.ts#L16-L20)), setting the failure threshold to **5**, reset timeout to **30 seconds**, and success threshold to **3**.

### Per-Key Metrics Storage

The breaker maintains isolated metrics for each protected resource using a private `metrics` Map ([lines 22‑24](https://github.com/felladrin/minisearch/blob/main/server/utils/circuitBreaker.ts#L22-L24)). This `CircuitMetrics` object tracks:

- Current `state`
- Consecutive `failures` count
- Consecutive `successes` count
- `lastFailure` timestamp

This design allows a single `CircuitBreaker` instance to protect multiple distinct external services (e.g., different LLM models) simultaneously without cross-contamination.

## Execution Flow and State Transitions

The `execute` method serves as the public entry point for all protected operations, handling state checks, transitions, and metric recording.

### The execute Method

The `execute` method ([lines 30‑55](https://github.com/felladrin/minisearch/blob/main/server/utils/circuitBreaker.ts#L30-L55)) accepts a unique `key` identifier and an async function `fn`. It performs the following sequence:

1. Retrieves or creates metrics for the provided key.
2. Checks if the circuit is **OPEN** and whether the `resetTimeout` has elapsed; if so, transitions to **HALF_OPEN**.
3. If still **OPEN**, throws immediately with `"Circuit breaker is open for …"`.
4. Executes the supplied function and records success or failure accordingly.

### Recording Successes and Failures

Success handling occurs in `recordSuccess` ([lines 90‑99](https://github.com/felladrin/minisearch/blob/main/server/utils/circuitBreaker.ts#L90-L99)). When in **HALF_OPEN** mode, consecutive successes increment the counter; reaching `successThreshold` resets the state to **CLOSED** and clears counters. In **CLOSED** mode, any successful call resets the failure counter to zero.

Failure handling in `recordFailure` ([lines 101‑116](https://github.com/felladrin/minisearch/blob/main/server/utils/circuitBreaker.ts#L101-L116)) increments the failure count, stores the timestamp, resets successes to zero, and opens the circuit when the threshold is breached. Crucially, this method schedules a `setTimeout` that automatically transitions the state from **OPEN** to **HALF_OPEN** after the configured `resetTimeout` duration, enabling automatic recovery testing.

### Manual Reset and State Inspection

For monitoring and testing purposes, the `getState` accessor ([lines 58‑64](https://github.com/felladrin/minisearch/blob/main/server/utils/circuitBreaker.ts#L58-L64)) returns the current state for any key, while `resetMetrics` ([lines 119‑124](https://github.com/felladrin/minisearch/blob/main/server/utils/circuitBreaker.ts#L119-L124)) forcibly clears all counters and returns the circuit to **CLOSED**.

## Practical Usage Examples

### Basic Integration for API Protection

Wrap any flaky async operation, such as an LLM request, using the `execute` method:

```typescript
import { CircuitBreaker } from "./utils/circuitBreaker";

const cb = new CircuitBreaker({
  failureThreshold: 3,
  resetTimeout: 15000,
  successThreshold: 2,
});

async function protectedCall<T>(key: string, fn: () => Promise<T>): Promise<T> {
  return cb.execute(key, fn);
}

// Protect an OpenAI API call
await protectedCall("openai-gpt-4", async () => {
  const response = await fetchOpenAI(...);
  return response.json();
});

```

### Health Check Endpoints

Inspect circuit states for monitoring dashboards:

```typescript
import { CircuitBreaker } from "./utils/circuitBreaker";

const cb = new CircuitBreaker();
const state = cb.getState("openai-gpt-4"); // "CLOSED" | "OPEN" | "HALF_OPEN"
console.log(`OpenAI circuit state: ${state}`);

```

### Service-Specific Configuration

Create isolated breakers with different thresholds for various external services:

```typescript
const modelBreakerMap = new Map<string, CircuitBreaker>();

function getBreakerForModel(model: string): CircuitBreaker {
  if (!modelBreakerMap.has(model)) {
    const options = model === "gpt-4"
      ? { failureThreshold: 2, resetTimeout: 10000, successThreshold: 1 }
      : {}; // fall back to defaults
    modelBreakerMap.set(model, new CircuitBreaker(options));
  }
  return modelBreakerMap.get(model)!;
}

// Usage
await getBreakerForModel("gpt-4").execute("gpt-4", async () => {
  // …call model…
});

```

## Validation and Testing

The implementation is validated by [`server/utils/circuitBreaker.test.ts`](https://github.com/felladrin/minisearch/blob/main/server/utils/circuitBreaker.test.ts), which verifies state transitions, error propagation, and timeout behavior. Key test assertions confirm that:

- An **OPEN** circuit throws `"Circuit breaker is open for …"` immediately.
- After consecutive failures exceeding the threshold, the circuit transitions to **OPEN** or **HALF_OPEN** depending on timing.
- The `setTimeout` mechanism correctly schedules transitions from **OPEN** to **HALF_OPEN**.

These tests serve as living documentation for the expected behavior of the circuit breaker utility.

## Summary

- The **circuit breaker pattern** in Minisearch is implemented as a generic, reusable TypeScript class in [`server/utils/circuitBreaker.ts`](https://github.com/felladrin/minisearch/blob/main/server/utils/circuitBreaker.ts).
- It maintains **three distinct states** (CLOSED, OPEN, HALF_OPEN) with automatic transitions based on failure counts and timeouts.
- The implementation supports **multi-key isolation**, allowing one instance to protect multiple external services simultaneously.
- Configuration options include `failureThreshold`, `resetTimeout`, and `successThreshold`, with sensible defaults provided.
- State transitions are handled internally via `recordSuccess`, `recordFailure`, and scheduled timeouts, requiring no manual intervention for recovery.

## Frequently Asked Questions

### What is the default failure threshold for the Minisearch circuit breaker?

According to the source code in [`server/utils/circuitBreaker.ts`](https://github.com/felladrin/minisearch/blob/main/server/utils/circuitBreaker.ts) ([lines 16‑20](https://github.com/felladrin/minisearch/blob/main/server/utils/circuitBreaker.ts#L16-L20)), the default `failureThreshold` is **5 consecutive failures**. The default `resetTimeout` is **30000 milliseconds** (30 seconds), and the `successThreshold` defaults to **3** successful calls in HALF_OPEN state.

### How does the circuit breaker transition from OPEN to HALF_OPEN automatically?

When the failure threshold is reached, the `recordFailure` method ([lines 101‑116](https://github.com/felladrin/minisearch/blob/main/server/utils/circuitBreaker.ts#L101-L116)) schedules a `setTimeout` that executes after the configured `resetTimeout` duration. This timer flips the state from **OPEN** to **HALF_OPEN**, allowing a single test request to determine if the external service has recovered without requiring manual intervention.

### Can I use different circuit breaker configurations for different external services?

Yes. While a single `CircuitBreaker` instance can track multiple services via unique keys, you can also instantiate separate `CircuitBreaker` objects with distinct `CircuitBreakerOptions` for different services. The code examples demonstrate using a `Map<string, CircuitBreaker>` to associate specific threshold configurations with individual LLM models or API endpoints.

### Where can I find the unit tests for the circuit breaker implementation?

The complete test suite is located in [`server/utils/circuitBreaker.test.ts`](https://github.com/felladrin/minisearch/blob/main/server/utils/circuitBreaker.test.ts) alongside the implementation. These tests validate default options, custom configuration handling, state transition logic, and the automatic opening behavior after repeated failures, serving as authoritative documentation for the utility's behavior.