Configuration
Options
CircuitBreakerPlugin accepts ICircuitBreakerPluginOptions:
| Option | Type | Default | Description |
|---|---|---|---|
failureThreshold | number | 5 | Failures within windowMs that trip CLOSED → OPEN. |
windowMs | number | 10000 | Rolling window (ms) over which failures are counted in CLOSED. |
openDurationMs | number | 30000 | Time (ms) the breaker stays OPEN before probes are allowed. |
halfOpenMaxCalls | number | 1 | Max probe calls permitted while HALF_OPEN. |
successThreshold | number | 1 | Successful probes required to close (must be ≤ halfOpenMaxCalls). |
probeTimeoutMs | number | openDurationMs | Time (ms) a permitted HALF_OPEN probe may stay unresolved before its slot is reclaimed (protects against crashed probes). |
keyPrefix | string | 'cb:' | Redis key prefix for circuit state. |
client | string | 'default' | Named Redis client to use. |
errorPolicy | 'fail-open' | 'fail-closed' | 'fail-closed' | Behaviour when the state store is unavailable. |
errorFactory | (key, snapshot) => Error | — | Custom error thrown when the breaker rejects a call. |
All numeric knobs are validated at bootstrap (integers ≥ 1; successThreshold <= halfOpenMaxCalls) — an invalid config throws InvalidCircuitBreakerConfigError instead of silently misbehaving.
Synchronous Setup
import { Module } from '@nestjs/common';
import { RedisModule } from '@nestjs-redisx/core';
import { CircuitBreakerPlugin } from '@nestjs-redisx/circuit-breaker';
@Module({
imports: [
RedisModule.forRoot({
clients: {
host: 'localhost',
port: 6379,
},
plugins: [
new CircuitBreakerPlugin({
failureThreshold: 5, // trip after 5 failures...
windowMs: 10000, // ...within a 10s rolling window
openDurationMs: 30000, // stay OPEN for 30s before probing
halfOpenMaxCalls: 1, // allow 1 probe while HALF_OPEN
successThreshold: 1, // 1 successful probe closes the breaker
probeTimeoutMs: 30000, // reclaim a probe slot if its outcome is never recorded
}),
],
}),
],
})
export class AppModule {}Asynchronous Setup
Load option values from ConfigService with CircuitBreakerPlugin.registerAsync, kept outside the connection useFactory (standard NestJS pattern):
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { RedisModule } from '@nestjs-redisx/core';
import { CircuitBreakerPlugin } from '@nestjs-redisx/circuit-breaker';
@Module({
imports: [
RedisModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
// Plugins live OUTSIDE useFactory (standard NestJS pattern). Their own
// options can still be loaded asynchronously via registerAsync.
plugins: [
CircuitBreakerPlugin.registerAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (config: ConfigService) => ({
failureThreshold: config.get<number>('CB_FAILURE_THRESHOLD', 5),
openDurationMs: config.get<number>('CB_OPEN_MS', 30000),
}),
}),
],
useFactory: (config: ConfigService) => ({
clients: {
type: 'single',
host: config.get<string>('REDIS_HOST', 'localhost'),
port: config.get<number>('REDIS_PORT', 6379),
},
}),
}),
],
})
export class AppModule {}Error Policy
errorPolicy decides what happens when the state store itself (Redis) is unavailable — it does not affect what happens when the breaker is simply OPEN (that always rejects unless you provide a fallback).
fail-closed(default): throwCircuitBreakerStoreError.fail-open: run the guarded call anyway, favouring availability.
import { Module } from '@nestjs/common';
import { RedisModule } from '@nestjs-redisx/core';
import { CircuitBreakerPlugin } from '@nestjs-redisx/circuit-breaker';
@Module({
imports: [
RedisModule.forRoot({
clients: { host: 'localhost', port: 6379 },
plugins: [
new CircuitBreakerPlugin({
// errorPolicy governs what happens when the STATE STORE (Redis) is
// unavailable — not when the breaker itself is OPEN.
//
// 'fail-open' -> run the guarded call anyway (favor availability)
// 'fail-closed' (default) -> throw CircuitBreakerStoreError
errorPolicy: 'fail-open',
}),
],
}),
],
})
export class AppModule {}Per-call Overrides
Every knob can be overridden per method (via the decorator) or per call (via execute), e.g. @WithCircuitBreaker({ key: 'x', failureThreshold: 10 }). See the decorator and service pages.