Skip to main content

Overview

Circuit breakers prevent cascade failures by tracking provider health and automatically stopping traffic to failing providers. Lasso implements per-provider, per-transport circuit breakers with automatic recovery and exponential backoff.

State Machine

Circuit breakers operate in three states:

State Descriptions

:closed (Healthy)
  • Provider is operating normally
  • All requests are allowed
  • Failures increment counter but don’t block traffic
  • Transitions to :open after failure_threshold consecutive failures
:open (Failing)
  • Provider has exceeded failure threshold
  • All requests are rejected immediately
  • No traffic sent to provider
  • Transitions to :half_open after recovery_timeout elapsed
:half_open (Recovering)
  • Provider is testing recovery
  • Limited concurrent requests allowed (half_open_max_inflight)
  • Success increments recovery counter
  • Any failure immediately reopens circuit
  • Transitions to :closed after success_threshold consecutive successes

Circuit Breaker Keying

Circuit breakers are keyed by {instance_id, transport} where:
Key Properties:
  • Same provider instance shared across profiles
  • Independent circuit breakers for HTTP and WebSocket
  • Deduplication prevents redundant circuit state
Example:

Configuration

Circuit breaker behavior is configured via application config:

Configuration Parameters

failure_threshold (default: 5)
  • Consecutive failures required to open circuit
  • Lower values = more aggressive protection
  • Higher values = more tolerance for transient failures
success_threshold (default: 2)
  • Consecutive successes required to close from half-open
  • Lower values = faster recovery
  • Higher values = more conservative recovery
recovery_timeout (default: 60,000ms)
  • Base timeout before attempting recovery
  • Applies to first open episode
  • Subsequent reopens use exponential backoff
max_recovery_timeout (default: 600,000ms)
  • Maximum timeout after exponential backoff
  • Prevents unbounded backoff
  • Caps at 10 minutes by default
half_open_max_inflight (default: 3)
  • Maximum concurrent requests in half-open state
  • Limits blast radius during recovery testing
  • Excess requests rejected with :half_open_busy
category_thresholds (optional)
  • Per-error-category failure thresholds
  • Overrides failure_threshold for specific error types
  • Example: Open faster on network errors (3) than server errors (5)

State Transitions

Closed → Open

Triggered when consecutive failures reach threshold:
Telemetry Event:

Open → Half-Open

Triggered by recovery timeout or traffic-triggered recovery: Proactive Recovery (timer-based):
Traffic-Triggered Recovery (admission check):
Telemetry Event:

Half-Open → Closed

Triggered when consecutive successes reach threshold:
Telemetry Event:

Half-Open → Open (Reopen)

Triggered by any failure in half-open state:
Telemetry Event:

Exponential Backoff

On consecutive reopens, recovery timeout increases exponentially:
Backoff Schedule: Jitter: ±5% random jitter prevents synchronized recovery storms:

Rate Limit Handling

Rate limit errors receive special treatment:

Retry-After Headers

If error includes retry_after_ms, use it instead of exponential backoff:

Fast Recovery

Rate limit circuits use success_threshold=1 for faster recovery:

No Breaker Penalty

Rate limit errors don’t count toward circuit breaker failures in shared mode:
This prevents one profile’s rate limit from affecting other profiles sharing the provider.

Health Probe Integration

Health probes signal recovery to circuit breakers:
Signal Recovery:
Behavior by State:
  • :open → Transitions to :half_open if recovery deadline passed
  • :half_open → Counts toward success threshold
  • :closed → No-op (doesn’t need recovery signals)

ETS State Management

Circuit breaker state is written to ETS on every transition:
State Shape:
Benefits:
  • Survives GenServer restarts
  • Fast reads for provider selection (no GenServer calls)
  • Shared across profiles for consistent state

PubSub Fan-Out

Circuit events are broadcast to all profiles using the instance:
Subscribers:
  • Dashboard LiveViews (real-time UI updates)
  • EventStream (metrics aggregation)
  • Telemetry handlers (logging, alerting)

Admission Control

Circuit breaker guards requests with admission control:

Admission Logic

:closed - Allow all requests:
:open - Check recovery deadline:
:half_open - Check inflight capacity:

Rejection Reasons

Error Classification

Circuit breaker penalties depend on error category:

Retriable Errors (Breaker Penalty)

  • :server_error - 5xx status, upstream failure
  • :network_error - Connection refused, timeout
  • :timeout - Request timeout (except in shared mode)

Non-Retriable Errors (No Penalty)

  • :invalid_params - User error, not provider fault
  • :user_error - Client mistake
  • :client_error - 4xx status

Special Categories

:rate_limit (Retriable, No Penalty in Shared Mode):
  • Temporary backpressure
  • Known recovery (retry-after headers)
  • Fast recovery (success_threshold=1)
:capability_violation (Retriable, No Penalty):
  • Permanent constraint, not transient failure
  • Provider doesn’t support method/params
  • Should failover to different provider

Telemetry Events

All circuit breaker events emit telemetry:

Event Schema

Example Telemetry Handler

Best Practices

Tuning Thresholds

Low Traffic (<10 req/s):
High Traffic (>100 req/s):

Category Thresholds

Half-Open Inflight

Next Steps

Provider Selection

Understand how circuit state affects selection

Routing Strategies

Learn about health-based tiering

Profiles

Configure circuit breaker thresholds

Architecture

Explore shared circuit breaker infrastructure