Redis is excellent at a specific kind of job: keeping hot, simple data close to the application with very low latency. Problems start when teams treat it as the default answer for anything that needs to be “fast.”
Speed is not an architecture. A cache, queue, counter, session store, or ephemeral coordination layer can be a good use of Redis. A second database-shaped system that nobody has clearly bounded is how you get surprise consistency problems, expensive memory bills, and one more thing paging the team at 2 a.m.
1. Your dataset is too large to justify keeping it in memory
Redis keeps its active dataset in memory. That is the point. RAM gives you fast access, but it also changes the economics of the system.
If the data you want to keep in Redis is 800 MB and it serves a hot path thousands of times per second, the trade-off may be easy. If it is 800 GB of rarely touched records, Redis is likely the wrong place to start. You will pay memory prices for data that a disk-backed database can store more economically, and you will still need to think about eviction, backups, failover, and restart behavior.
The important phrase is working set. Redis can be a good cache when the hot slice of data is small even if the full dataset is large. For example, caching the top 20,000 product availability records for a busy storefront can make sense. Mirroring the entire product catalog, every historical price, every vendor attribute, and every rarely used admin field into Redis usually does not.
Before adding Redis, ask what needs to be in memory at the same time. If you cannot answer that, you do not yet have a cache design. You have a hope with a monthly bill.
2. Your data is naturally relational
Some data wants tables. Customers have subscriptions. Subscriptions have invoices. Invoices have payments. Products belong to categories. Orders have line items. You can model parts of that in Redis with hashes, sets, sorted sets, and carefully named keys, but Redis will not give you the same relational machinery that PostgreSQL or MySQL gives you.
The cost often moves into application code. Instead of asking the database to enforce a foreign key, you remember to update several Redis keys in exactly the right order. Instead of a join, you fetch IDs from one structure, fetch objects from another, then stitch the response together yourself. Instead of a database constraint rejecting impossible state, you write defensive code in every path that mutates the data.
That can be fine for a narrow access pattern. A leaderboard does not need a relational schema. A rate-limit counter does not need a join. But core business data usually has more questions asked of it over time, not fewer. If the product team will eventually ask for reports, filters, audit trails, exports, and data corrections, a relational database is usually the calmer foundation.
Use Redis where its data structures match the shape of the problem. Do not force relational business state into Redis just to avoid learning why the existing SQL query is slow.
3. Redis would become your primary source of truth without a good reason
Redis is not “just memory that disappears on restart.” That is a common oversimplification. Redis supports persistence, including point-in-time RDB snapshots and append-only file logging. You can also combine both. Those options matter, and for some workloads they are enough.
The real question is not whether Redis can write to disk. It can. The question is whether its persistence model, operational behavior, and data model match the job you are giving it.
RDB snapshots are compact and useful for backups, but they represent the dataset at intervals. If a process dies between snapshots, you need to be comfortable with the possible loss window. AOF logs write operations and can be configured with different fsync policies. More durability generally costs more write latency or more disk pressure. Redis gives you knobs; it does not remove the trade-off.
This matters when Redis becomes the only copy of something the business cares about. A shopping cart that can be rebuilt or tolerated as ephemeral state is one thing. Ledger entries, subscription changes, medical records, or entitlement decisions are another. If losing a small window of writes is unacceptable, design that explicitly. If you need strict relational constraints, auditable history, and complex correction workflows, Redis should probably not be the system of record.
4. You need complex ad-hoc queries
Key-value access is wonderfully direct when you know the key. It is much less pleasant when the question starts with “find all records where…”
Imagine a support dashboard that needs customers who subscribed during a date range, are located in a certain region, purchased products from a particular category, have not renewed, and have an open ticket. In PostgreSQL, that is a query problem. It may still need indexes and tuning, but the database is built for this kind of work.
In Redis, you have to design the access paths ahead of time. You might maintain sets by region, sorted sets by subscription date, indexes by product category, and separate keys for renewal status. Then the application has to intersect, filter, fetch, and keep those indexes synchronized. That is not automatically wrong, but it is a lot of machinery if the real requirement is ordinary querying.
If the query patterns are fixed and high-volume, Redis can serve precomputed views well. If the organization needs flexible investigation, reporting, and product analytics, use a database or search engine that is meant to answer questions you did not fully predict last quarter.
5. Your values are large
Redis strings can store binary-safe values, and the default maximum for a single string value is large enough that people sometimes take the wrong lesson from it. The issue is not “can Redis store this file?” The better question is “why should this live in memory?”
Large JSON documents, images, PDFs, serialized blobs, and big HTML fragments make every part of the Redis design heavier. Memory usage rises. Network payloads grow. Persistence files get larger. Replication takes more work. Backups and restarts become slower. If you frequently read or write the entire blob, you may also lose the benefit of small, targeted operations.
For files and binary objects, object storage is usually the better default. For large documents that need queryable fields, a document database, relational JSON column, or search index may fit better depending on the access pattern. Redis can still hold a pointer, a small derived summary, a short-lived token, or a cached fragment. It does not need to hold the whole object.
6. You are adding Redis because “we might need caching”
This is the one that shows up in otherwise sensible systems.
The team has an application and PostgreSQL. Someone says the database might get slow later, so Redis goes into the architecture diagram:
Application
-> Redis
-> PostgreSQL
That diagram looks harmless. In production, it means another service to deploy, monitor, secure, back up, upgrade, and recover. It means cache invalidation rules. It means serialization formats. It means network calls. It means deciding what happens when Redis is down, stale, partially warmed, or using more memory than expected.
The simpler version is easy to underestimate:
Application
-> PostgreSQL
This is not an argument against caching. It is an argument against caching as decoration. The fastest cache is the cache you do not need. If the database is serving the workload comfortably, an extra hop through Redis may make the system more complicated before it makes it faster.
Add Redis when you know what it protects, what data it owns, how it expires, and how the application behaves without it.
7. Your database is already fast enough
A slow endpoint does not automatically imply “add Redis.” It might need an index. It might be doing N+1 queries. It might be fetching ten columns when it needs two. It might be missing a connection pool, sending avoidable requests from the browser, or waiting on a third-party API. It might be a CDN problem, not a database problem.
Start with measurement. Look at query plans. Check p95 and p99 latency, not only averages. Confirm which part of the request is slow. Add the obvious indexes. Remove unnecessary round trips. Cache at the browser or CDN layer when the content is public and cacheable. Fix waste in the application code.
Redis is most satisfying when it removes a measured bottleneck. It is much less satisfying when it hides an unknown one.
When Redis IS a Great Choice
The point of this guide is not to make Redis sound bad. Redis is popular because it solves real problems cleanly.
It is a strong choice for caching expensive query results when the data can expire or be rebuilt. It works well for session storage when the session model is simple and the durability expectations are explicit. Atomic counters and rate limiters map naturally to Redis operations. Sorted sets are a good fit for leaderboards, priority-style rankings, and time-ordered scoring. Short-lived coordination state can also fit, as long as the failure modes are understood.
Redis streams and list-based queues can work well when their delivery semantics match the job. For some teams, Redis is a pragmatic queue because it is already operated well and the workload is modest. For others, a dedicated message broker is a better match. The deciding factor is not whether Redis can do it. The deciding factor is whether Redis does the specific job with the guarantees you need.
Redis is at its best when the access pattern is known, the data structure is natural, the working set fits in memory, and the system remains understandable when Redis is unavailable.
Redis vs Alternatives
This table is directional. Architecture still depends on workload, scale, failure tolerance, team experience, and operational constraints.
| Requirement | Redis | PostgreSQL | MongoDB | Object Storage |
|---|---|---|---|---|
| Low-latency cache | Excellent | Possible | Possible | Poor fit |
| Relational querying | Poor fit | Excellent | Possible | Poor fit |
| Durable system of record | Possible with careful design | Excellent | Good | Good for objects |
| Very large datasets economically | Often expensive | Good | Good | Excellent |
| Arbitrary query flexibility | Limited unless modeled upfront | Excellent | Good | Poor fit |
| Large binary files | Possible, usually poor economics | Possible, not ideal | Possible, not ideal | Excellent |
| Counters and rate limiting | Excellent | Possible | Possible | Poor fit |
Should You Use Redis?
Use Redis because it matches a real access pattern, not because it makes an architecture diagram look more serious.
Redis is worth considering if
- You have a measurable latency or throughput problem Redis solves.
- Most Redis data can be reconstructed, or you have explicitly designed persistence around your durability requirements.
- Your access pattern maps naturally to Redis data structures.
- You understand the memory requirements and growth pattern.
- Your team can operate Redis reliably.
Think twice if
- Redis will mirror most of your SQL database.
- You cannot clearly explain why Redis is needed.
- You are adding it because the database might become slow.
- Most queries need joins or filtering over many attributes.
- Redis becomes another source of truth that must stay synchronized.
Quick Redis Decision Tool
Redis Decision Sanity Check
Answer five questions to see whether Redis looks like a fit for this particular workload.
Redis is probably the wrong first move
The answers do not show a strong Redis-shaped problem. Start by improving the primary database, query plans, caching headers, or application code before adding another service.
0/5 answered. This is a quick architectural sanity check, not a substitute for profiling and understanding your workload.