{
  "schema_version": 2,
  "id": "develop/clients/redis-py/produsage",
  "title": "Production usage",
  "url": "https://redis.io/docs/latest/develop/clients/redis-py/produsage/",
  "summary": "Get your `redis-py` app ready for production",
  "tags": [
    "docs",
    "develop",
    "stack",
    "oss",
    "rs",
    "rc",
    "oss",
    "kubernetes",
    "clients"
  ],
  "last_updated": "2026-10-12T10:32:09+01:00",
  "page_type": "content",
  "content_hash": "5fae3a152d02c3172d0b9b44bf7bce7cf2df1b0506289bc4b2e9435ef33ae72d",
  "sections": [
    {
      "id": "overview",
      "title": "Overview",
      "role": "overview",
      "text": "This guide offers recommendations to get the best reliability and\nperformance in your production environment."
    },
    {
      "id": "checklist",
      "title": "Checklist",
      "role": "content",
      "text": "Each item in the checklist below links to the section\nfor a recommendation. Use the checklist icons to record your\nprogress in implementing the recommendations.\n\n[code example]"
    },
    {
      "id": "recommendations",
      "title": "Recommendations",
      "role": "content",
      "text": "The sections below offer recommendations for your production environment. Some\nof them may not apply to your particular use case."
    },
    {
      "id": "client-side-caching",
      "title": "Client-side caching",
      "role": "content",
      "text": "[Client-side caching](https://redis.io/docs/latest/develop/clients/client-side-caching)\ninvolves storing the results from read-only commands in a local cache. If the\nsame command is executed again later, the results can be obtained from the cache,\nwithout contacting the server. This improves command execution time on the client,\nwhile also reducing network traffic and server load. See\n[Connect using client-side caching](https://redis.io/docs/latest/develop/clients/redis-py/connect#connect-using-client-side-caching)\nfor more information and example code."
    },
    {
      "id": "retries",
      "title": "Retries",
      "role": "content",
      "text": "Redis connections and commands can often fail due to transient problems,\nsuch as temporary network outages or timeouts. When this happens,\nthe operation will generally succeed after a few attempts, despite\nfailing the first time.\n\n`redis-py` can retry commands automatically when\nerrors occur. From version 6.0.0 onwards, the default behavior is to\nattempt a failed command three times.\nThe timing between successive attempts is calculated using\n[exponential backoff](https://en.wikipedia.org/wiki/Exponential_backoff)\nwith some random \"jitter\" added to avoid two or more connections retrying\ncommands in sync with each other.\n\nYou can override the default behavior using an instance of the `Retry` class to\nspecify the number of times to retry after a failure along with your\nown choice of backoff strategy.\nPass the `Retry` object in the `retry` parameter when you connect.\nFor example, the connection in the code below uses an exponential backoff strategy\n(without jitter) that will make eight repeated attempts after a failure:\n\n[code example]\n\nA retry is triggered when a command throws any exception\nlisted in the `supported_errors` attribute of the `Retry` class.\nBy default, the list only includes `ConnectionError` and `TimeoutError`,\nbut you can set your own choice of exceptions when you create the\ninstance:\n\n[code example]\n\nYou can also add extra exceptions to the default list using the `retry_on_error`\nparameter when you connect:\n\n[code example]\n\nFor a connection to a Redis cluster, you can specify a `retry` instance,\nbut the list of exceptions is not configurable and is always set\nto `TimeoutError`, `ConnectionError`, and `ClusterDownError`."
    },
    {
      "id": "health-checks",
      "title": "Health checks",
      "role": "content",
      "text": "If your code doesn't access the Redis server continuously then it\nmight be useful to make a \"health check\" periodically (perhaps once\nevery few seconds) to verify that the connection is working.\nSet the `health_check_interval` parameter during\na connection (with either `Redis` or `ConnectionPool`) to specify\nan integer number of seconds. If the connection remains idle for\nlonger than this interval, it will automatically issue a\n[`PING`](https://redis.io/docs/latest/commands/ping) command and check the\nresponse before continuing with any client commands.\n\n[code example]\n\nHealth checks help to detect problems as soon as possible without\nwaiting for a user to report them. Note that health checks, like\nother commands, will be [retried](#retries) using the strategy\nthat you specified for the connection."
    },
    {
      "id": "exception-handling",
      "title": "Exception handling",
      "role": "errors",
      "text": "Redis handles many errors using return values from commands, but there\nare also situations where exceptions can be thrown. In production code,\nyou should handle exceptions wherever they can occur. \n\nImport the exceptions you need to check from the `redis.exceptions`\nmodule. The list below describes some of the most common exceptions.\n\n- `ConnectionError`: Thrown when a connection attempt fails\n  (for example, when connection parameters are invalid or the server\n  is unavailable) and sometimes when a [health check](#health-checks)\n  fails. There is also a subclass, `AuthenticationError`, specifically\n  for authentication failures.\n- `ResponseError`: Thrown when you attempt an operation that has no valid\n  response. Examples include executing a command on the wrong type of key\n  (as when you try an\n  ['LPUSH'](https://redis.io/docs/latest/develop/data-types/lists#automatic-creation-and-removal-of-keys)\n  command on a string key), creating an\n  [index](https://redis.io/docs/latest/develop/ai/search-and-query/indexing)\n  with a name that already exists, and using an invalid ID for a\n  [stream entry](https://redis.io/docs/latest/develop/data-types/streams#entry-ids).\n- `TimeoutError`: Thrown when a timeout persistently happens for a command,\n  despite any [retries](#retries).\n- `WatchError`: Thrown when a\n  [watched key](https://redis.io/docs/latest/develop/clients/redis-py/transpipe#watch-keys-for-changes) is\n  modified during a transaction."
    },
    {
      "id": "timeouts",
      "title": "Timeouts",
      "role": "content",
      "text": "After you issue a command or a connection attempt, the client will wait\nfor a response from the server. If the server doesn't respond within a\ncertain time limit, the client will throw a `TimeoutError`. By default,\nthe timeout happens after 10 seconds for both connections and commands, but you\ncan set your own timeouts using the `socket_connect_timeout` and `socket_timeout` parameters\nwhen you connect:\n\n[code example]\n\nTake care to set the timeouts to appropriate values for your use case.\nIf you use timeouts that are too short, then `redis-py` might retry\ncommands that would have succeeded if given more time. However, if the\ntimeouts are too long, your app might hang unnecessarily while waiting for a\nresponse that will never arrive."
    },
    {
      "id": "smart-client-handoffs",
      "title": "Smart client handoffs",
      "role": "content",
      "text": "*Smart client handoffs (SCH)* is a feature of Redis Cloud and\nRedis Software servers that lets them actively notify clients\nabout planned server maintenance shortly before it happens. This\nlets a client take action to avoid disruptions in service.\n\nSee [Smart client handoffs](https://redis.io/docs/latest/develop/clients/sch)\nfor more information about SCH and\n[Connect using Smart client handoffs](https://redis.io/docs/latest/develop/clients/redis-py/connect#connect-using-smart-client-handoffs-sch)\nfor example code."
    },
    {
      "id": "monitor-performance-and-errors",
      "title": "Monitor performance and errors",
      "role": "content",
      "text": "`redis-py` supports [OpenTelemetry](https://opentelemetry.io/). This lets\nyou trace command execution and monitor your server's performance.\nYou can use this information to detect problems before they are reported\nby users. See [Observability](https://redis.io/docs/latest/develop/clients/redis-py/observability)\nfor more information.\n\nTo find the keys that use the most CPU time and network bandwidth on the\nserver, use the [`HOTKEYS`](https://redis.io/docs/latest/commands/hotkeys) command."
    }
  ],
  "examples": [
    {
      "id": "checklist-ex0",
      "language": "checklist {id=\"pyprodlist\"}",
      "code": "- [ ] [Client-side caching](#client-side-caching)\n- [ ] [Retries](#retries)\n- [ ] [Health checks](#health-checks)\n- [ ] [Exception handling](#exception-handling)\n- [ ] [Timeouts](#timeouts)\n- [ ] [Smart client handoffs](#smart-client-handoffs)\n- [ ] [Monitor performance and errors](#monitor-performance-and-errors)",
      "section_id": "checklist"
    },
    {
      "id": "retries-ex0",
      "language": "py",
      "code": "from redis.backoff import ExponentialBackoff\nfrom redis.retry import Retry\n\n# Run 8 retries with exponential backoff strategy.\nretry = Retry(ExponentialBackoff(), 8)\n\nr = Redis(\n  retry=retry,\n    .\n    .\n)",
      "section_id": "retries"
    },
    {
      "id": "retries-ex1",
      "language": "py",
      "code": "# Only retry after a `TimeoutError`.\nretry = Retry(ExponentialBackoff(), 3, supported_errors=(TimeoutError,))",
      "section_id": "retries"
    },
    {
      "id": "retries-ex2",
      "language": "py",
      "code": "# Add `BusyLoadingError` to the default list of exceptions.\nfrom redis.exceptions import (\n   BusyLoadingError,\n)\n    .\n    .\n\nr = Redis(\n  retry=retry,\n  retry_on_error=[BusyLoadingError],\n    .\n    .\n)",
      "section_id": "retries"
    },
    {
      "id": "health-checks-ex0",
      "language": "py",
      "code": "# Issue a health check if the connection is idle for longer\n# than three seconds.\nr = Redis(\n  health_check_interval = 3,\n    .\n    .\n)",
      "section_id": "health-checks"
    },
    {
      "id": "timeouts-ex0",
      "language": "py",
      "code": "# Set a 15-second timeout for connections and a\n# 5-second timeout for commands.\nr = Redis(\n  socket_connect_timeout=15,\n  socket_timeout=5,\n    .\n    .\n)",
      "section_id": "timeouts"
    }
  ]
}
