{
  "id": "cache-aside",
  "title": "Redis cache-aside",
  "url": "https://redis.io/docs/latest/develop/use-cases/cache-aside/",
  "summary": "Cache database reads in Redis with TTL-bounded staleness.",
  "tags": [
    "docs",
    "develop",
    "stack",
    "oss",
    "rs",
    "rc"
  ],
  "last_updated": "2026-05-12T09:07:59-04:00",
  "children": [
    {
      "id": "redis-py",
      "summary": "Implement a Redis cache-aside layer in Python with redis-py",
      "title": "Redis cache-aside with redis-py",
      "url": "https://redis.io/docs/latest/develop/use-cases/cache-aside/redis-py/"
    },
    {
      "id": "nodejs",
      "summary": "Implement a Redis cache-aside layer in Node.js with node-redis",
      "title": "Redis cache-aside with node-redis",
      "url": "https://redis.io/docs/latest/develop/use-cases/cache-aside/nodejs/"
    },
    {
      "id": "go",
      "summary": "Implement a Redis cache-aside layer in Go with go-redis",
      "title": "Redis cache-aside with Go",
      "url": "https://redis.io/docs/latest/develop/use-cases/cache-aside/go/"
    },
    {
      "id": "java-jedis",
      "summary": "Implement a Redis cache-aside layer in Java with Jedis",
      "title": "Redis cache-aside with Jedis",
      "url": "https://redis.io/docs/latest/develop/use-cases/cache-aside/java-jedis/"
    },
    {
      "id": "java-lettuce",
      "summary": "Implement a Redis cache-aside layer in Java with Lettuce",
      "title": "Redis cache-aside with Lettuce",
      "url": "https://redis.io/docs/latest/develop/use-cases/cache-aside/java-lettuce/"
    },
    {
      "id": "dotnet",
      "summary": "Implement a Redis cache-aside layer in C# with StackExchange.Redis",
      "title": "Redis cache-aside with StackExchange.Redis",
      "url": "https://redis.io/docs/latest/develop/use-cases/cache-aside/dotnet/"
    },
    {
      "id": "php",
      "summary": "Implement a Redis cache-aside layer in PHP with Predis",
      "title": "Redis cache-aside with Predis",
      "url": "https://redis.io/docs/latest/develop/use-cases/cache-aside/php/"
    },
    {
      "id": "ruby",
      "summary": "Implement a Redis cache-aside layer in Ruby with redis-rb",
      "title": "Redis cache-aside with redis-rb",
      "url": "https://redis.io/docs/latest/develop/use-cases/cache-aside/ruby/"
    },
    {
      "id": "rust",
      "summary": "Implement a Redis cache-aside layer in Rust with redis-rs",
      "title": "Redis cache-aside with redis-rs",
      "url": "https://redis.io/docs/latest/develop/use-cases/cache-aside/rust/"
    }
  ],
  "page_type": "content",
  "content_hash": "ffaf81ad93daec19c8fa430eb1f6ed14871a02fe492a4da52403e104ee71b636",
  "sections": [
    {
      "id": "when-to-use-redis-cache-aside",
      "title": "When to use Redis cache-aside",
      "role": "overview",
      "text": "Use Redis cache-aside when you need to serve repeated reads at sub-millisecond latency without overloading your primary database, caching only the data that is actually requested."
    },
    {
      "id": "why-the-problem-is-hard",
      "title": "Why the problem is hard",
      "role": "content",
      "text": "Read-heavy workloads (product catalogs, user profiles, API responses) hit the same records thousands of times between updates. Primary databases optimized for durability pay the full cost of a disk-based lookup on every request; as traffic grows, P95 latency degrades, connection pools exhaust, and brief spikes cascade into broader service degradation.\n\nAn in-process cache solves this for a single instance but breaks across multiple stateless services: each instance warms independently, duplicates memory, and cannot be invalidated consistently. When a popular cached key expires under high concurrency, dozens of processes simultaneously query the database for the same record — a cache stampede that amplifies the exact load spike caching was supposed to prevent.\n\nThis use case is distinct from write-through or write-behind caching, where the cache mirrors the full dataset on every write. It is also distinct from semantic caching, which matches LLM responses by embedding similarity rather than exact key lookup."
    },
    {
      "id": "what-you-can-expect-from-a-redis-solution",
      "title": "What you can expect from a Redis solution",
      "role": "content",
      "text": "You can:\n\n-   Keep P95 read latency under 5 ms for cached entities at peak traffic.\n-   Reduce primary database load proportionally to hit rate without provisioning read replicas.\n-   Cache only actively requested data, keeping memory bounded to the working set.\n-   Invalidate on write so stale data windows stay within a configured bound.\n-   Survive popular-key expiration under load without stampeding the database.\n-   Update individual fields in a cached entity without deserializing and rewriting the full object."
    },
    {
      "id": "how-redis-supports-the-solution",
      "title": "How Redis supports the solution",
      "role": "content",
      "text": "In practice, each cached entity is stored under a key like `cache:{entity}:{id}`, with a TTL that bounds how long stale data can be served. The application reads from Redis on every request, falls back to the primary on a miss, and writes the result back to Redis. On updates, the application writes the primary and invalidates the cache key.\n\nRedis provides the following features that make it a good fit for cache-aside:\n\n-   [`GET`](https://redis.io/docs/latest/commands/get) and\n    [`SET`](https://redis.io/docs/latest/commands/set) with per-key\n    [`EX`/`PX`](https://redis.io/docs/latest/commands/set) TTL so every entry has a bounded\n    staleness window, and [`DEL`](https://redis.io/docs/latest/commands/del) on write for explicit\n    invalidation — keeping stale data confined to a known, configurable bound.\n-   [Hashes](https://redis.io/docs/latest/develop/data-types/hashes)\n    ([`HSET`](https://redis.io/docs/latest/commands/hset),\n    [`HGET`](https://redis.io/docs/latest/commands/hget)) and native\n    [JSON](https://redis.io/docs/latest/develop/data-types/json) path access\n    ([`JSON.SET`](https://redis.io/docs/latest/commands/json.set),\n    [`JSON.GET`](https://redis.io/docs/latest/commands/json.get)) for structured and\n    partial-field caching, avoiding full-object re-serialization on every read or update — a real\n    gap in string-only stores like Memcached.\n-   [Lua scripting](https://redis.io/docs/latest/develop/programmability/eval-intro) with\n    [`EVAL`](https://redis.io/docs/latest/commands/eval) for atomic stampede mitigation: mutex locks\n    or probabilistic early refresh execute in a single atomic step with no external locking.\n-   [`TTL`](https://redis.io/docs/latest/commands/ttl) for monitoring remaining staleness on any cached\n    key without recomputing.\n-   Sub-millisecond reads from memory, so the cache check adds negligible overhead on the\n    request path. If Redis is already in the stack for sessions, rate limiting, or queues,\n    cache-aside runs on the same instance at zero marginal infrastructure cost.\n\n<!-- TODO: add item about INCREX command when Redis 8.8 is GA -->"
    },
    {
      "id": "ecosystem",
      "title": "Ecosystem",
      "role": "content",
      "text": "The following libraries and frameworks provide Redis-backed cache-aside integrations:\n\n-   **Java**:\n    [Spring Data Redis (`@Cacheable`/`@CacheEvict`)](https://docs.spring.io/spring-data/redis/reference/redis/redis-cache.html),\n    [Redis Smart Cache](https://github.com/redis/smart-cache)\n    (transparent JDBC-layer cache-aside)\n-   **Python**: [Flask-Caching](https://flask-caching.readthedocs.io/)\n    (Redis backend),\n    [Django cache framework](https://docs.djangoproject.com/en/stable/topics/cache/)\n    (with [redis-py](https://redis.readthedocs.io/))\n-   **Node.js**: [node-redis](https://github.com/redis/node-redis),\n    [ioredis](https://github.com/redis/ioredis) (wrap route handlers with a cache-aside helper)\n-   **API gateways**:\n    [Kong Redis response caching](https://docs.konghq.com/hub/kong-inc/proxy-cache-advanced/)\n    (configurable TTL per route)"
    },
    {
      "id": "code-examples-to-build-your-own-redis-cache-aside",
      "title": "Code examples to build your own Redis cache-aside",
      "role": "example",
      "text": "The following guides show how to build a simple Redis-backed cache-aside layer in front\nof a slow primary store. Each guide includes a runnable interactive demo for each of the\nfollowing client libraries:\n\n* [redis-py (Python)](https://redis.io/docs/latest/develop/use-cases/cache-aside/redis-py)\n* [node-redis (Node.js)](https://redis.io/docs/latest/develop/use-cases/cache-aside/nodejs)\n* [go-redis (Go)](https://redis.io/docs/latest/develop/use-cases/cache-aside/go)\n* [Jedis (Java)](https://redis.io/docs/latest/develop/use-cases/cache-aside/java-jedis)\n* [Lettuce (Java)](https://redis.io/docs/latest/develop/use-cases/cache-aside/java-lettuce)\n* [StackExchange.Redis (C#)](https://redis.io/docs/latest/develop/use-cases/cache-aside/dotnet)\n* [Predis (PHP)](https://redis.io/docs/latest/develop/use-cases/cache-aside/php)\n* [redis-rb (Ruby)](https://redis.io/docs/latest/develop/use-cases/cache-aside/ruby)\n* [redis-rs (Rust)](https://redis.io/docs/latest/develop/use-cases/cache-aside/rust)"
    }
  ],
  "examples": []
}
