Patterns
Circuit breaker (closed / open / half-open)
Protection against cascading failures of API dependencies
Circuit breaker isolates calls to a failing dependency (SuperPDP, BulkGate SMS, eIDAS-certified signature partner) to prevent an external outage from propagating timeouts to the entire app. Three states. CLOSED (nominal): calls pass normally, failures counted over a sliding window. Above the threshold (e.g. 50% failures over 20 calls), breaker goes OPEN: all calls fail immediately (fail fast) without touching the dependency, for a cooldown (e.g. 30s). After cooldown, HALF-OPEN state: N test calls pass through; if successful, back to CLOSED; otherwise OPEN with doubled cooldown. Implementations: `opossum` (Node.js), `resilience4j` (Java), custom Laravel middleware. Metrics exposed to Datadog/Sentry to alert on OPEN transitions.
Key facts
- 3 states: CLOSED (nominal), OPEN (fail-fast), HALF-OPEN (probing)
- Typical threshold: 50% failures over 20 calls → OPEN
- Initial cooldown 30s, doubled on each OPEN return (max 5 min)
- Critical metric: rate of OPEN transitions per minute
- Libs: opossum (JS), resilience4j (Java), custom Laravel middleware
Code example
import CircuitBreaker from 'opossum';
const superpdpCall = async (payload: unknown) =>
fetch('https://api.superpdp.fr/v1.beta/invoices', {
method: 'POST',
body: JSON.stringify(payload),
}).then(r => r.json());
const breaker = new CircuitBreaker(superpdpCall, {
timeout: 5000, // ms
errorThresholdPercentage: 50,
resetTimeout: 30_000, // 30s cooldown
rollingCountTimeout: 60_000,
rollingCountBuckets: 10,
});
breaker.on('open', () => metrics.incr('superpdp.breaker.open'));
breaker.on('halfOpen', () => metrics.incr('superpdp.breaker.halfopen'));
breaker.fallback(() => ({ status: 'queued_for_retry' }));