ProxyWhirl Docs
Concepts

Rotation Strategies

Protocol-based strategy design, the registry pattern, and the nine built-in rotation algorithms.

Rotation Strategies

ProxyWhirl ships nine rotation strategies. This page explains the design; for configuration examples see Strategy Matrix and Python API.

Protocol, Not ABC

Strategies implement the RotationStrategy Protocol (structural subtyping):

@runtime_checkable
class RotationStrategy(Protocol):
    def select(self, pool: ProxyPool, context: SelectionContext | None) -> Proxy: ...
    def record_result(self, proxy: Proxy, success: bool, response_time_ms: float) -> None: ...

Any class with matching methods is valid — no inheritance required. Benefits: third-party plugins, easier mocking, static type checking via @runtime_checkable.

Registry Pattern

registry = StrategyRegistry()
registry.register_strategy("my-custom", MyCustomStrategy)
strategy_class = registry.get_strategy("my-custom")

Strategy names in TOML/CLI decouple from implementations and support runtime hot-swapping.

Built-In Strategies

Simple (stateless)

StrategyAlgorithmTimeUse case
Round-RobinSequential indexO(1)Even distribution
Randomrandom.choice()O(1)Anti-detection

Adaptive (stateful)

StrategyAlgorithmTimeUse case
WeightedSuccess-rate weightsO(1) cachedFavor reliable proxies
Least-UsedMin active requestsO(n)Load balancing
Performance-BasedInverse EMA latencyO(n)Lowest latency
Cost-AwareBudget-weighted (free 10× boost)O(n)Cost optimization

record_result() feeds adaptive strategies. Performance-based uses EMA with a cold-start exploration period.

Context-aware

StrategyInputUse case
Session PersistenceSession ID → sticky proxy (LRU + TTL)Stateful workflows
Geo-Targetedcountry_code / region in contextRegional routing

Composition

Composite chains strategies into a pipeline:

[Geo filter: US] → [Performance: fastest] → selected proxy

Avoids an N×M explosion of combined strategy classes. Composite pipelines target <5 µs selection overhead.

Why record_result() Everywhere?

Even stateless strategies implement record_result() so:

  1. Adaptive strategies receive feedback uniformly
  2. Callers do not branch on strategy type
  3. Simple strategies can become adaptive without API changes

Thread Safety

StrategyMechanism
Round-Robinthreading.Lock on index
Session PersistenceRLock in SessionManager
Random / WeightedGIL-protected random.choices
Performance-BasedLock on EMA updates

See Also

On this page