{
  "id": "prefetch-cache",
  "title": "Redis prefetch cache",
  "url": "https://redis.io/docs/latest/develop/use-cases/prefetch-cache/",
  "summary": "Pre-load reference data into Redis so every read is a cache hit.",
  "tags": [
    "docs",
    "develop",
    "stack",
    "oss",
    "rs",
    "rc"
  ],
  "last_updated": "2026-05-14T08:58:05-05:00",
  "children": [
    {
      "id": "redis-py",
      "summary": "Implement a Redis prefetch cache in Python with redis-py",
      "title": "Redis prefetch cache with redis-py",
      "url": "https://redis.io/docs/latest/develop/use-cases/prefetch-cache/redis-py/"
    },
    {
      "id": "nodejs",
      "summary": "Implement a Redis prefetch cache in Node.js with node-redis",
      "title": "Redis prefetch cache with node-redis",
      "url": "https://redis.io/docs/latest/develop/use-cases/prefetch-cache/nodejs/"
    },
    {
      "id": "go",
      "summary": "Implement a Redis prefetch cache in Go with go-redis",
      "title": "Redis prefetch cache with go-redis",
      "url": "https://redis.io/docs/latest/develop/use-cases/prefetch-cache/go/"
    },
    {
      "id": "java-jedis",
      "summary": "Implement a Redis prefetch cache in Java with Jedis",
      "title": "Redis prefetch cache with Jedis",
      "url": "https://redis.io/docs/latest/develop/use-cases/prefetch-cache/java-jedis/"
    },
    {
      "id": "java-lettuce",
      "summary": "Implement a Redis prefetch cache in Java with Lettuce",
      "title": "Redis prefetch cache with Lettuce",
      "url": "https://redis.io/docs/latest/develop/use-cases/prefetch-cache/java-lettuce/"
    },
    {
      "id": "dotnet",
      "summary": "Implement a Redis prefetch cache in C# with StackExchange.Redis",
      "title": "Redis prefetch cache with StackExchange.Redis",
      "url": "https://redis.io/docs/latest/develop/use-cases/prefetch-cache/dotnet/"
    },
    {
      "id": "php",
      "summary": "Implement a Redis prefetch cache in PHP with Predis",
      "title": "Redis prefetch cache with Predis",
      "url": "https://redis.io/docs/latest/develop/use-cases/prefetch-cache/php/"
    },
    {
      "id": "ruby",
      "summary": "Implement a Redis prefetch cache in Ruby with redis-rb",
      "title": "Redis prefetch cache with redis-rb",
      "url": "https://redis.io/docs/latest/develop/use-cases/prefetch-cache/ruby/"
    },
    {
      "id": "rust",
      "summary": "Implement a Redis prefetch cache in Rust with redis-rs",
      "title": "Redis prefetch cache with redis-rs",
      "url": "https://redis.io/docs/latest/develop/use-cases/prefetch-cache/rust/"
    }
  ],
  "page_type": "content",
  "content_hash": "03e6da9d94f9b5b393d400371008a014186a5b524b0f410815aef4db17e8f2e2",
  "sections": [
    {
      "id": "when-to-use-redis-prefetch-cache",
      "title": "When to use Redis prefetch cache",
      "role": "overview",
      "text": "Use a Redis prefetch cache when you need to pre-load reference or master data into cache before the first request arrives, so every read is a hit and no request ever falls through to the primary database."
    },
    {
      "id": "why-the-problem-is-hard",
      "title": "Why the problem is hard",
      "role": "content",
      "text": "Cache-aside guarantees cold-start misses: the first request for every key hits the primary, and between TTL expiry and the next read, every service re-fetches the same rows from a slow backend. At scale this creates latency spikes and sustained read pressure on the system of record — the load pattern is worst exactly when traffic is highest.\n\nPrefetch solves this by loading data proactively, but that brings its own constraints. The entire working set must fit in memory, and it must stay current as the source of truth changes. Building and maintaining the sync pipeline from the source database adds engineering cost and ongoing operational burden — once the cache is the only read path, any sync lag becomes a correctness problem rather than a freshness one.\n\nThis pattern is distinct from cache-aside, where the cache populates reactively on miss and the primary is always available as a fall-back. With prefetch, the application assumes the cache is authoritative on the read path; on a miss, it does not fall back to the primary (and a sustained miss rate is treated as an incident). It is also distinct from write-through caching, where every write to the application writes both the cache and the primary in lock-step — prefetch decouples the write path from the cache and lets a separate sync pipeline catch up."
    },
    {
      "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-   Achieve near-100% cache hit ratios for country codes, product categories, translations, configuration, and other reference tables.\n-   Keep P95 read latency under 1 ms for lookup-heavy request paths at peak traffic (that is to say 95% of requests have a latency of 1 ms or less).\n-   Sync source database changes into cache within seconds using a managed CDC pipeline (such as Redis Data Integration), or a small consumer in front of Debezium, Kafka, or a Redis stream.\n-   Offload all reference-data reads from the primary database, avoiding the cost of dedicated read replicas.\n-   Pre-warm the cache on deploy or restart so cold starts never reach the backend.\n-   Bound memory with a long safety-net TTL that expires entries if the sync pipeline ever stops, so a silent failure never serves stale data forever."
    },
    {
      "id": "how-redis-supports-the-solution",
      "title": "How Redis supports the solution",
      "role": "content",
      "text": "In practice, the application loads the full working set into Redis once at startup using a pipelined bulk write, then a separate sync worker keeps Redis current as the source of truth changes. Every reference-data read goes to Redis only — there is no fall-back path to the primary on the request critical path.\n\nRedis provides the following features that make it a good fit for prefetch caching:\n\n-   [Hashes](https://redis.io/docs/latest/develop/data-types/hashes)\n    ([`HSET`](https://redis.io/docs/latest/commands/hset),\n    [`HGETALL`](https://redis.io/docs/latest/commands/hgetall)) and native\n    [JSON](https://redis.io/docs/latest/develop/data-types/json) documents\n    ([`JSON.SET`](https://redis.io/docs/latest/commands/json.set),\n    [`JSON.GET`](https://redis.io/docs/latest/commands/json.get)) map directly to common\n    reference-data lookup patterns — id-keyed records with a fixed set of fields,\n    or richer nested documents accessed by JSONPath.\n-   [Pipelined](https://redis.io/docs/latest/develop/clients/pools-and-muxing)\n    [`HSET`](https://redis.io/docs/latest/commands/hset) or\n    [`MSET`](https://redis.io/docs/latest/commands/mset) batches make the initial bulk load\n    fast: a few thousand records load in a single round trip, so the application\n    starts serving from a fully-warm cache within seconds of boot.\n-   [`EXPIRE`](https://redis.io/docs/latest/commands/expire) sets a long safety-net TTL on\n    each entry so memory stays bounded even if the sync pipeline silently stops —\n    not as the freshness mechanism, but as a guardrail.\n-   [`SCAN`](https://redis.io/docs/latest/commands/scan) iterates the prefetched keyspace\n    without blocking the server, so the application can audit cache coverage,\n    list available IDs, or run a periodic reconciliation pass against the source.\n-   [Streams](https://redis.io/docs/latest/develop/data-types/streams)\n    ([`XADD`](https://redis.io/docs/latest/commands/xadd),\n    [`XREAD`](https://redis.io/docs/latest/commands/xread)) provide a durable, replayable\n    change feed when the sync worker needs to resume from a known offset after\n    a restart — the canonical pattern for CDC consumers feeding Redis.\n-   Sub-millisecond reads from memory, so reference-data lookups never appear on\n    a flame graph. If Redis is already in the stack for sessions, rate limiting,\n    or cache-aside, prefetch runs on the same instance at zero marginal cost."
    },
    {
      "id": "ecosystem",
      "title": "Ecosystem",
      "role": "content",
      "text": "The following libraries and frameworks support Redis-backed prefetch caching:\n\n-   **Java**:\n    [Spring Cache abstraction (`@Cacheable` with Redis cache store)](https://docs.spring.io/spring-data/redis/reference/redis/redis-cache.html),\n    populated by a startup `CommandLineRunner` for the bulk load.\n-   **Node.js**:\n    [Redis OM](https://github.com/redis/redis-om-node) for object-mapping\n    prefetched JSON documents.\n-   **Change-data-capture (CDC)** pipelines that stream source-database changes\n    into Redis without custom application code:\n    [Redis Data Integration (RDI)](https://redis.io/docs/latest/integrate/redis-data-integration)\n    for relational and NoSQL sources on Redis Enterprise / Redis Cloud;\n    [Debezium](https://debezium.io/) plus a lightweight Redis consumer for\n    open-source Redis.\n-   **API gateways**:\n    [Kong](https://docs.konghq.com/hub/) plugins to route reference-data reads to\n    Redis directly, bypassing the backend service entirely."
    },
    {
      "id": "code-examples-to-build-your-own-redis-prefetch-cache",
      "title": "Code examples to build your own Redis prefetch cache",
      "role": "example",
      "text": "The following guides show how to build a simple Redis-backed prefetch cache in front of a primary store of reference data. Each guide includes a runnable interactive demo that pre-loads records on startup, runs a background sync worker that applies primary-store changes to Redis within milliseconds, and lets you watch the cache stay current as records are added, updated, and deleted on the source.\n\n* [redis-py (Python)](https://redis.io/docs/latest/develop/use-cases/prefetch-cache/redis-py)\n* [node-redis (Node.js)](https://redis.io/docs/latest/develop/use-cases/prefetch-cache/nodejs)\n* [go-redis (Go)](https://redis.io/docs/latest/develop/use-cases/prefetch-cache/go)\n* [Jedis (Java)](https://redis.io/docs/latest/develop/use-cases/prefetch-cache/java-jedis)\n* [Lettuce (Java)](https://redis.io/docs/latest/develop/use-cases/prefetch-cache/java-lettuce)\n* [StackExchange.Redis (C#)](https://redis.io/docs/latest/develop/use-cases/prefetch-cache/dotnet)\n* [Predis (PHP)](https://redis.io/docs/latest/develop/use-cases/prefetch-cache/php)\n* [redis-rb (Ruby)](https://redis.io/docs/latest/develop/use-cases/prefetch-cache/ruby)\n* [redis-rs (Rust)](https://redis.io/docs/latest/develop/use-cases/prefetch-cache/rust)"
    }
  ],
  "examples": []
}
