Skip to content
|By Muhammad Wilayat Shah|0 views • 0 unique IPs

Redis Caching: When You Should and Shouldn't Use It

Redis can turn a 400 ms endpoint into a 5 ms one, or add stale data bugs that hide a missing index. Learn when Redis caching helps, when it hurts, and how to use cache-aside safely.

Redis cache layer sitting in front of a database
Redis cache layer sitting in front of a database

When an endpoint gets slow, adding Redis is often the first idea in the room. Sometimes it is exactly right and response times drop from 400 ms to 5 ms. Other times it adds a second source of truth, stale data bugs, and an extra piece of infrastructure to babysit, while the real problem was a missing index. Redis caching is a powerful tool, but only when you use it for the right reasons.

What Redis Caching Actually Gives You

Redis is an in-memory key-value store. Reads take well under a millisecond, it supports expirations (TTL) natively, and it offers useful data structures such as hashes, sorted sets, and counters. As a cache, it lets you skip expensive work, whether that is a heavy SQL query, a slow third-party API, or a costly computation, by storing the result and serving it again.

When You Should Use Redis Caching

  • Read-heavy data that changes rarely. Product catalogs, configuration, category trees, pricing tables, and public profiles are read thousands of times for every write.
  • Expensive aggregations. Dashboards, leaderboards, and report totals that take seconds to compute but can be a minute old.
  • Slow or rate-limited external APIs. Currency rates, geocoding, or LLM responses for identical prompts. Caching protects both latency and your quota.
  • Sessions and short-lived tokens. Fast lookups with automatic expiry are a natural fit.
  • Rate limiting and counters. Atomic INCR with a TTL is simpler and faster than doing the same in a relational database.
  • Protecting the database under spikes. A cache absorbs traffic bursts so your primary database stays healthy.

When You Shouldn't Use It

  • The query is slow because it is badly written. Run EXPLAIN ANALYZE first. An index or a rewritten query fixes the root cause; a cache only hides it until the next cache miss.
  • Data must always be fresh. Account balances, stock levels during checkout, and permissions are dangerous to serve stale.
  • Every request is unique. If keys are almost never reused, your hit rate will be near zero and you pay the overhead for nothing.
  • Your traffic is small. A well-indexed PostgreSQL or MySQL database handles a lot. Don't add infrastructure before you have a measured problem.
  • As your only copy of data. A cache can be evicted or flushed at any time. If losing it means losing data, it is not a cache.

The Cache-Aside Pattern

The most common and safest approach is cache-aside, also called lazy loading. The application checks Redis first, falls back to the database on a miss, and stores the result with a TTL.

Cache-aside diagram showing app, Redis and database read and write flow
Code
async function getProduct(id) {
  const key = `product:v1:${id}`;
  const cached = await redis.get(key);
  if (cached) return JSON.parse(cached);

  const product = await db.product.findUnique({ where: { id } });
  await redis.set(key, JSON.stringify(product), 'EX', 300);
  return product;
}

On writes, update the database first and then delete the key, instead of trying to update the cache in place. The next read will repopulate it with fresh data.

Common Redis Caching Mistakes

No TTL

Keys without expiry live forever, grow memory without limit, and keep serving data long after it is wrong. Give every cache key a TTL, even a long one.

Forgetting invalidation

Most cache bugs are invalidation bugs. List every write path that changes the data behind a key, and make sure each one deletes it. Versioned keys such as product:v2:42 let you invalidate everything after a schema or logic change.

Cache stampede

When a popular key expires, hundreds of requests can hit the database at once. Use a short lock so only one request rebuilds the value, add random jitter to TTLs, or refresh hot keys in the background before they expire.

Caching huge objects

Storing whole pages or multi-megabyte blobs eats memory and network bandwidth. Cache the smallest useful piece, and set a maxmemory policy such as allkeys-lru.

Not measuring

Track hit rate, latency, memory, and evictions. A cache with a 20 percent hit rate is mostly overhead and may need different keys or longer TTLs.

A Quick Decision Checklist

  1. Have you measured the slow path and fixed obvious query problems?
  2. Is the data read far more often than it is written?
  3. Can users tolerate it being seconds or minutes old?
  4. Will the same keys be requested repeatedly?
  5. Do you know every write path that must invalidate the key?
  6. Can the system still work, more slowly, if Redis is down?

If you answer yes to all six, Redis caching is likely a strong win. If not, fix the underlying issue first.

Conclusion

Redis caching shines for read-heavy, repeatable, slightly stale-tolerant data and for protecting slow dependencies. It hurts when it is used to hide bad queries, cache data that must be exact, or act as a database. Measure first, use cache-aside with TTLs, plan invalidation up front, and treat Redis as an accelerator, never as the source of truth.