Skip to content

Disabled retries still retry: redis-py's default Retry(10) applies when the kit hands it nothing #25

Description

@AlexeyShalaev

Measured on 0.1.3 with redis-py 8.1.0, Redis 7 in a container that I paused so that connections neither succeed nor fail. One GET per client, with socket_timeout=0.5 and socket_connect_timeout=0.5 in the pool settings and the retry group left at its defaults, then with retry.enabled=False, max_attempts=0 spelled out:

bare redis-py, defaults                                    retry handed to redis-py: Retry retries=10 backoff=ExponentialWithJitterBackoff
bare redis-py, timeouts 0.5 + Retry(NoBackoff(), 0)        retry handed to redis-py: Retry retries=0  backoff=NoBackoff
kit, timeouts 0.5, retry settings default                  retry handed to redis-py: Retry retries=10 backoff=ExponentialWithJitterBackoff
kit, timeouts 0.5, retry.enabled=False explicitly          retry handed to redis-py: Retry retries=10 backoff=ExponentialWithJitterBackoff
--- Redis paused: one GET per client ---
bare redis-py, defaults                                    -> still waiting        20.00 s  (gave up watching)
bare redis-py, timeouts 0.5 + Retry(NoBackoff(), 0)        -> TimeoutError          0.50 s
kit, timeouts 0.5, retry settings default                  -> TimeoutError          9.93 s
kit, timeouts 0.5, retry.enabled=False explicitly          -> TimeoutError         17.90 s

Rule 5 on the agents page says that with no Retry handed to it redis-py does not retry at all. That was true once; redis-py now ships a default Retry(ExponentialWithJitterBackoff, retries=10) when retry is not given, and the kit hands nothing when retry.enabled is false, so a client configured to fail in half a second fails in ten to eighteen, jitter deciding which. For the use this post is about, a cache or an idempotency store that should fail open fast when Redis is gone, that is the difference between a request that degrades and a request that times out at the load balancer.

What I think it needs: when retries are disabled the factory should pass Retry(NoBackoff(), 0) explicitly, so "disabled" means what it says whatever redis-py's default is; when they are enabled, the kit's Retry is already explicit. Rule 5 and the retry section of the configuration guide follow. It may be worth a second look at whether the kit's own backoff should carry jitter now that redis-py's does, but that is a separate question from the default.

Scripts: retry_probe.py in https://github.com/bedrock-python/bedrock-python.github.io/tree/docs/production-python-series/docs/blog/lab/2026-09-07-when-should-redis-fail-open.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions