Problem
pyresilience stores all stateful component state in process memory. This works correctly for single-instance deployments, but breaks in any horizontally scaled environment — Kubernetes, Docker Swarm, or multiple workers behind a load balancer.
Concrete failure modes:
Circuit Breaker — each replica maintains its own failure counter. With failure_threshold=5 and 5 replicas, the service absorbs up to 25 failures before any circuit opens. The protection is effectively divided by replica count.
Rate Limiter — with max_calls=100 and 5 replicas, the actual rate sent to the downstream is 500 calls/period. The external API sees no limiting at all.
Retry Budget — the budget exists specifically to prevent retry storms cluster-wide. Per-process budgets multiply by replica count, defeating the entire purpose.
It would be nice to introduce a StateBackend protocol that stateful components accept as an optional dependency. The default (in-memory) behavior is unchanged. Users running multi-node deployments inject a shared backend.
To keep zero-dependency constraint — the Redis backend could live in pyresilience.backends.redis as an optional contrib module, keeping the core package dependency-free.
Problem
pyresilience stores all stateful component state in process memory. This works correctly for single-instance deployments, but breaks in any horizontally scaled environment — Kubernetes, Docker Swarm, or multiple workers behind a load balancer.
Concrete failure modes:
Circuit Breaker — each replica maintains its own failure counter. With failure_threshold=5 and 5 replicas, the service absorbs up to 25 failures before any circuit opens. The protection is effectively divided by replica count.
Rate Limiter — with max_calls=100 and 5 replicas, the actual rate sent to the downstream is 500 calls/period. The external API sees no limiting at all.
Retry Budget — the budget exists specifically to prevent retry storms cluster-wide. Per-process budgets multiply by replica count, defeating the entire purpose.
It would be nice to introduce a StateBackend protocol that stateful components accept as an optional dependency. The default (in-memory) behavior is unchanged. Users running multi-node deployments inject a shared backend.
To keep zero-dependency constraint — the Redis backend could live in pyresilience.backends.redis as an optional contrib module, keeping the core package dependency-free.