{
  "schema_version": 2,
  "id": "develop/clients/client-side-caching",
  "title": "Client-side caching introduction",
  "url": "https://redis.io/docs/latest/develop/clients/client-side-caching/",
  "summary": "Server-assisted, client-side caching in Redis",
  "aliases": [
    "/develop/connect/clients/client-side-caching",
    "/manual/client-side-caching/"
  ],
  "tags": [
    "docs",
    "develop",
    "stack",
    "oss",
    "rs",
    "rc",
    "oss",
    "kubernetes",
    "clients"
  ],
  "last_updated": "2026-09-29T16:29:37+01:00",
  "page_type": "content",
  "content_hash": "9786f8abfe238f6f97388a13ecc8a7c0f975078e208d404a9bda758c4e97bee1",
  "sections": [
    {
      "id": "overview",
      "title": "Overview",
      "role": "overview",
      "text": "*Client-side caching* reduces network traffic between\na Redis client and the server, which generally improves performance.\n\nBy default, an [application server](https://en.wikipedia.org/wiki/Application_server)\n(which sits between the user app and the database) contacts the\nRedis database server through the client library for every read request.\nThe diagram below shows the flow of communication from the user app,\nthrough the application server to the database and back again:\n\n![](https://redis.io/docs/latest/images/csc/CSCNoCache.drawio.svg)\n\nWhen you use client-side caching, the client library\nmaintains a local cache of data items as it retrieves them\nfrom the database. When the same items are needed again, the client\ncan satisfy the read requests from the cache instead of the database:\n\n![](https://redis.io/docs/latest/images/csc/CSCWithCache.drawio.svg)\n\nAccessing the cache is much faster than communicating with the database over the\nnetwork and it reduces network traffic. Client-side caching reduces\nthe load on the database server, so you may be able to run it using less hardware\nresources.\n\nAs with other forms of [caching](https://en.wikipedia.org/wiki/Cache_(computing)),\nclient-side caching works well in the very common use case where a small subset of the data\nis accessed much more frequently than the rest of the data (according\nto the [Pareto principle](https://en.wikipedia.org/wiki/Pareto_principle))."
    },
    {
      "id": "tracking",
      "title": "Updating the cache when the data changes",
      "role": "content",
      "text": "All caching systems must implement a scheme to update data in the cache\nwhen the corresponding data changes in the main database. Redis uses an\napproach called *tracking*.\n\nWhen client-side caching is enabled, the Redis server remembers or *tracks* the set of keys\nthat each client connection has previously read. This includes cases where the client\nreads data directly, as with the [`GET`](https://redis.io/docs/latest/commands/get)\ncommand, and also where the server calculates values from the stored data,\nas with [`STRLEN`](https://redis.io/docs/latest/commands/strlen). When any client\nwrites new data to a tracked key, the server sends an invalidation message\nto all clients that have accessed that key previously. This message warns\nthe clients that their cached copies of the data are no longer valid and the clients\nwill evict the stale data in response. Next time a client reads from\nthe same key, it will access the database directly and refresh its cache\nwith the updated data.\n\n> [!NOTE]\n> If any connection from a client gets disconnected (including\n> one from a connection pool), then the client will flush all keys from the\n> client-side cache. Caching then resumes for subsequent reads from the\n> connections that are still active.\n\nThe sequence diagram below shows how two clients might interact as they\naccess and update the same key:\n\n![](https://redis.io/docs/latest/images/csc/CSCSeqDiagram.drawio.svg)"
    },
    {
      "id": "which-client-libraries-support-client-side-caching",
      "title": "Which client libraries support client-side caching?",
      "role": "content",
      "text": "The following client libraries support CSC from the stated version onwards:\n\n| Client | Version |\n| :-- | :-- |\n| [`redis-py`](https://redis.io/docs/latest/develop/clients/redis-py/connect#connect-using-client-side-caching) | v5.1.0 |\n| [`Jedis`](https://redis.io/docs/latest/develop/clients/jedis/connect#connect-using-client-side-caching) | v5.2.0 |\n| [`node-redis`](https://redis.io/docs/latest/develop/clients/nodejs/connect#connect-using-client-side-caching) | v5.1.0 |\n| [`go-redis`](https://redis.io/docs/latest/develop/clients/go/connect#connect-using-client-side-caching) | v9.22.0 |\n\nNote that some other clients support the [`CLIENT TRACKING`](https://redis.io/docs/latest/commands/client-tracking) command to configure CSC on the server, but this does not mean they support the\nfeatures required for CSC themselves."
    },
    {
      "id": "which-commands-can-cache-data",
      "title": "Which commands can cache data?",
      "role": "content",
      "text": "All read-only commands (with the `@read`\n[ACL category](https://redis.io/docs/latest/operate/oss_and_stack/management/security/acl))\nwill use cached data, except for the following:\n\n-   Any commands for the\n    [probabilistic](https://redis.io/docs/latest/develop/data-types/probabilistic) and\n    [time series](https://redis.io/docs/latest/develop/data-types/timeseries) data types.\n    These types are designed to be updated frequently, which means that caching\n    has little or no benefit.\n-   Non-deterministic commands such as [`HRANDFIELD`](https://redis.io/docs/latest/commands/hrandfield),\n    [`HSCAN`](https://redis.io/docs/latest/commands/hscan),\n    and [`ZRANDMEMBER`](https://redis.io/docs/latest/commands/zrandmember). By design, these commands\n    give different results each time they are called.\n-   Redis Search commands (with the `FT.*` prefix), such as\n    [`FT.SEARCH`](https://redis.io/docs/latest/commands/ft.search).\n\nYou can use the [`MONITOR`](https://redis.io/docs/latest/commands/monitor) command to\ncheck the server's behavior when you are using client-side caching. Because `MONITOR` only\nreports activity from the server, you should find the first cacheable\naccess to a key causes a response from the server. However, subsequent\naccesses are satisfied by the cache, and so `MONITOR` should report no\nserver activity if client-side caching is working correctly."
    },
    {
      "id": "what-data-gets-cached-for-a-command",
      "title": "What data gets cached for a command?",
      "role": "content",
      "text": "Broadly speaking, the data from the specific response to a command invocation\ngets cached after it is used for the first time. Subsets of that data\nor values calculated from it are retrieved from the server as usual and\nthen cached separately. For example:\n\n-   The whole string retrieved by [`GET`](https://redis.io/docs/latest/commands/get)\n    is added to the cache. Parts of the same string retrieved by\n    [`SUBSTR`](https://redis.io/docs/latest/commands/substr) are calculated on the\n    server the first time and then cached separately from the original\n    string.\n-   Using [`GETBIT`](https://redis.io/docs/latest/commands/getbit) or\n    [`BITFIELD`](https://redis.io/docs/latest/commands/bitfield) on a string\n    caches the returned values separately from the original string.\n-   For composite data types accessed by keys\n    ([hash](https://redis.io/docs/latest/develop/data-types/hashes),\n    [JSON](https://redis.io/docs/latest/develop/data-types/json),\n    [set](https://redis.io/docs/latest/develop/data-types/sets), and\n    [sorted set](https://redis.io/docs/latest/develop/data-types/sorted-sets)),\n    the whole object is cached separately from the individual fields.\n    So the results of `JSON.GET mykey $` and `JSON.GET mykey $.myfield` create\n    separate entries in the cache.\n-   Ranges from [lists](https://redis.io/docs/latest/develop/data-types/lists),\n    [streams](https://redis.io/docs/latest/develop/data-types/streams),\n    and [sorted sets](https://redis.io/docs/latest/develop/data-types/sorted-sets)\n    are cached separately from the object they form a part of. Likewise,\n    subsets returned by [`SINTER`](https://redis.io/docs/latest/commands/sinter) and\n    [`SDIFF`](https://redis.io/docs/latest/commands/sdiff) create separate cache entries.\n-   For multi-key read commands such as [`MGET`](https://redis.io/docs/latest/commands/mget),\n    the ordering of the keys is significant. For example `MGET name:1 name:2` is\n    cached separately from `MGET name:2 name:1` because the server returns the\n    values in the order you specify.\n-   Boolean or numeric values calculated from data types (for example \n    [`SISMEMBER`](https://redis.io/docs/latest/commands/sismember)) and\n    [`LLEN`](https://redis.io/docs/latest/commands/llen) are cached separately from the\n    object they refer to."
    },
    {
      "id": "usage-recommendations",
      "title": "Usage recommendations",
      "role": "syntax",
      "text": "Like any caching system, client-side caching has some limitations:\n\n-   The cache has only a limited amount of memory available. When the limit\n    is reached, the client must *evict* potentially useful items from the\n    cache to make room for new ones.\n-   Cache misses, tracking, and invalidation messages always add a slight\n    performance penalty.\n\nBelow are some guidelines to help you use client-side caching efficiently, within these\nlimitations:\n\n-   **Use a separate connection for data that is not cache-friendly**:\n    Caching gives the most benefit\n    for keys that are read frequently and updated infrequently. However, you\n    may also have data, such as counters and scoreboards, that receives frequent\n    updates. In cases like this, the performance overhead of the invalidation\n    messages can be greater than the savings made by caching. Avoid this problem\n    by using a separate connection *without* client-side caching for any data that is\n    not cache-friendly.\n-   **Estimate how many items you can cache**: The client libraries let you\n    specify the maximum number of items you want to hold in the cache. You\n    can calculate an estimate for this number by dividing the \n    maximum desired size of the\n    cache in memory by the average size of the items you want to store\n    (use the [`MEMORY USAGE`](https://redis.io/docs/latest/commands/memory-usage)\n    command to get the memory footprint of a key). For example, if you had\n    10MB (or 10485760 bytes) available for the cache, and the average\n    size of an item was 80 bytes, you could fit approximately\n    10485760 / 80 = 131072 items in the cache. Monitor memory usage\n    on your server with a realistic test load to adjust your estimate\n    up or down.\n\n    ## Reference\n\n    The Redis server implements extra features for client-side caching that are not used by\n    the main Redis clients, but may be useful for custom clients and other\n    advanced applications. See\n    [Client-side caching reference](https://redis.io/docs/latest/develop/reference/client-side-caching)\n    for a full technical guide to all the options available for client-side caching."
    }
  ],
  "examples": []
}
