ProxyWhirl Docs
Concepts

Circuit Breakers

How ProxyWhirl detects, isolates, and recovers from proxy failures with a three-state breaker.

Circuit Breakers

ProxyWhirl uses the circuit breaker pattern to detect, isolate, and recover from proxy failures automatically. For configuration and code examples, see Retry & Failover.

The Problem

Without intelligent failure handling, a rotator would:

  • Repeatedly retry known-bad proxies
  • Cascade failures when one slow proxy blocks the pool
  • Never detect when a temporarily failed proxy recovers

Simple per-request retry does not prevent the same bad proxy from being selected on the next request.

Three-State Machine

Each proxy has its own breaker:

CLOSED ──(failures ≥ threshold)──► OPEN
  ▲                                    │
  │                                    ▼
  └──(test succeeds)── HALF_OPEN ◄──(timeout elapsed)

                          └──(test fails)──► OPEN
StateBehavior
CLOSEDNormal operation; failures tracked in a rolling window (default 60s)
OPENProxy excluded; should_attempt_request() returns false (fail-fast)
HALF_OPENOne test request allowed; success closes, failure reopens

Default thresholds: 5 failures in 60s → OPEN for 30s, then HALF_OPEN probe.

Why Not Just Blacklist?

ApproachDetects failureAuto recoveryNo manual work
Manual blacklistNoNoNo
Simple retryPer-requestNoYes
Circuit breakerYesYesYes

Breakers probe recovery automatically after the OPEN timeout.

Rolling Window

Failures live in a timestamp deque. Only failures inside window_duration count toward failure_threshold. Old failures expire — transient bursts do not permanently exclude a proxy.

Half-Open Gating

When the timeout expires, multiple threads might test the same proxy. A _half_open_pending flag ensures only one test request proceeds; others fail fast and try a different proxy.

State Persistence

Optional SQLite persistence (persist_state=True) prevents retry storms on restart. Without it, all breakers start CLOSED after a crash and may flood previously failed proxies. Persistence is asynchronous and non-blocking.

Tuning

ParameterDefaultIncrease when…Decrease when…
failure_threshold5Using unreliable free proxiesUsing premium proxies
window_duration60sTransient failures are commonFailures are persistent
timeout_duration30sSlow recovery (residential)Fast recovery (datacenter)

Use sync CircuitBreaker in threaded code and AsyncCircuitBreaker in asyncio apps — never mix sync locks into async hot paths.

See Also

On this page