Redis is a database. The useful comparison is not really “Redis vs database,” but Redis vs the durable primary database that owns your application data—often PostgreSQL, MySQL, or another transactional store.
Redis is excellent when you need fast access to data structures such as strings, hashes, sets, sorted sets, streams, counters, or short-lived state. A relational database is usually better when you need durable records, rich querying, joins, constraints, multi-row transactions, and long-term history.
In many production systems, the right answer is not one or the other. It is Redis alongside the primary database, with each system doing the job it is best suited for.
The short version
| Requirement | Redis | Relational database |
|---|---|---|
| Very fast key-based access | Excellent fit | Good, but usually not the main reason to choose it |
| TTL / expiring data | Native and convenient | Possible, usually application/query driven |
| Counters, sets, sorted sets, queues/streams | Native data structures | Possible, often more cumbersome |
| Joins and ad-hoc relational queries | Poor fit | Core strength |
| Foreign keys and relational constraints | Not the model | Core strength |
| Large durable system of record | Possible for selected workloads, but requires deliberate persistence/HA design | Typical default |
| Complex multi-record business transactions | Limited compared with SQL databases | Core strength |
| Cache | Excellent fit | Usually the origin behind the cache |
| Cost-efficient storage for large historical datasets | RAM-heavy by default | Usually a better fit |
The key design question is: What happens if this data disappears, becomes stale, or cannot be queried relationally?
That answer usually tells you where the data belongs.
Redis is more than a cache
Calling Redis “just a cache” misses a large part of what it provides.
Redis is a data-structure server with native support for structures including:
- strings and counters;
- hashes;
- lists;
- sets and sorted sets;
- streams;
- geospatial data;
- JSON;
- time-series and probabilistic structures;
- vector-oriented data types in current Redis releases.
The official Redis data type documentation shows why many workloads map naturally to Redis operations instead of relational rows and joins.
Examples include:
session:{token} -> hash with TTL
rate_limit:{user}:{minute} -> counter with expiration
leaderboard:weekly -> sorted set
online_users -> set
notification_stream -> stream
These are not merely “cached SQL rows.” They are application data structures with operations that Redis can perform directly.
Where a relational database is stronger
A relational database is built around a different set of promises.
Suppose an order has:
- a customer;
- line items;
- payments;
- tax records;
- inventory effects;
- refunds;
- audit history.
You may need to query that data by customer, date, status, product, payment reference, or dozens of other combinations. You may also need constraints and transactions that keep several rows consistent together.
That is where a relational database shines.
For example:
SELECT o.id, o.created_at, SUM(oi.quantity * oi.unit_price) AS total
FROM orders o
JOIN order_items oi ON oi.order_id = o.id
WHERE o.customer_id = $1
AND o.created_at >= $2
GROUP BY o.id, o.created_at
ORDER BY o.created_at DESC;
Redis can store the same facts in some form, but reproducing arbitrary relational access patterns usually means manually maintaining indexes and denormalized structures in application code.
That complexity is rarely justified when SQL already solves the problem cleanly.
Durability is not a binary “Redis is memory, SQL is disk” question
A common oversimplification says Redis is volatile because it uses memory while relational databases are durable because they use disks.
The real difference is more nuanced.
Redis supports multiple persistence modes:
- RDB snapshots for point-in-time dataset snapshots;
- AOF (Append Only File) to log writes for replay;
- RDB + AOF together;
- no persistence for intentionally disposable workloads such as caches.
The Redis persistence documentation explicitly presents these as different durability/performance trade-offs.
A relational database such as PostgreSQL normally uses a write-ahead log so committed transactional changes can be recovered after a crash. PostgreSQL's WAL documentation treats durability as a fundamental database reliability concern.
So Redis can persist data. The question is whether its persistence, replication, backup, recovery, and data model meet the guarantees your workload requires.
Do not make “it has AOF enabled” the entire durability plan. You still need to think about:
- replication;
- failover behavior;
- backup copies;
- restore testing;
- acceptable recovery point;
- acceptable recovery time;
- what happens to acknowledged writes during failures.
Transactions are different too
Redis supports transactions with MULTI, EXEC, DISCARD, and optimistic locking via WATCH. Commands queued in a Redis transaction execute sequentially without another client's command being interleaved in the middle.
That is useful, but it is not the same programming model as a relational transaction spanning arbitrary rows and constraints.
Redis transactions are strongest when the data and operation already fit Redis' key-oriented model.
A relational transaction is usually the clearer choice for business invariants such as:
create order
+ reserve inventory
+ record payment state
+ update accounting row
= commit together or roll back
Trying to move such workflows into Redis only to avoid database latency often replaces a known transactional model with application-level consistency problems.
See the Redis transaction documentation for the exact guarantees Redis provides.
The most common production design: database of record + Redis
A very common architecture looks like this:
The primary database owns durable business records. Redis handles data that benefits from low-latency access or specialized in-memory operations.
Typical Redis responsibilities include:
- cache entries;
- sessions;
- rate-limit counters;
- short-lived verification state;
- idempotency keys;
- distributed coordination primitives where the semantics fit;
- leaderboards;
- real-time counters;
- queues or streams where Redis' delivery model matches the workload.
The important architectural rule is to know which copy is authoritative.
If Redis is merely a cache, the database is the source of truth and cache entries can be rebuilt.
If Redis owns the only copy of some state, then Redis is no longer “just infrastructure.” Its persistence, backup, HA, consistency, and recovery design become part of your data architecture.
Example: product lookup
A product page may need data stored durably in PostgreSQL or MySQL:
products
prices
inventory
categories
merchant ownership
change history
The application can cache the assembled read model in Redis:
product_view:18372 -> JSON or hash, TTL 5 minutes
A request then follows a cache-aside path:
- read
product_view:18372from Redis; - if present, return it;
- if missing, query the primary database;
- rebuild the cached representation;
- write it to Redis with an appropriate TTL.
Redis reduces repeated work. The database still owns the durable record.
This separation is usually easier to reason about than making Redis and SQL competing sources of truth.
Example: rate limiting
Rate limiting is almost the opposite.
A request counter such as:
rate_limit:user_42:2026-09-12T12:30
may live entirely in Redis because:
- it is short-lived;
- expiration is part of the model;
- atomic counters are useful;
- querying years of historical counter rows is not the goal;
- losing an old bucket is usually very different from losing an order or payment record.
That is a workload where Redis is often the more natural primary store for that specific piece of state.
Query flexibility is one of the biggest dividing lines
Redis performs best when the application knows how it will access data.
For example:
GET session:abc123
ZRANGE leaderboard 0 99 REV
HGETALL user:42:presence
A relational database is better when the questions evolve:
show customers who bought product X,
were refunded in the last 30 days,
and have more than three completed orders
With SQL, indexes and query planning can support many combinations over the same normalized data.
With Redis, you generally design keys and secondary structures around expected access patterns. That can be extremely fast, but it shifts more indexing responsibility into the data model and application.
Memory economics matter
Redis is designed around serving data from memory, so dataset size has a direct infrastructure cost.
That is a feature when low latency is the goal, but it can be a poor trade for:
- large archives;
- infrequently accessed historical records;
- long-lived audit data;
- datasets that grow far beyond the hot working set.
A common architecture keeps the durable, complete dataset in a primary database while Redis stores only the hot or temporary subset that benefits from in-memory access.
Do not cache everything just because Redis is available.
Failure behavior should drive the decision
Ask what the application should do if Redis is unavailable.
If Redis is a cache
The application may be able to fall back to the database—carefully, because a mass fallback can overload the origin.
If Redis stores sessions
Users may be logged out or temporarily unable to authenticate, depending on the session design and persistence strategy.
If Redis stores the only copy of critical business data
The outage becomes a database incident. Recovery guarantees now matter as much as they would for any other primary datastore.
This is why the label “Redis” tells you less than the role Redis plays in the system.
When Redis should usually complement the database
Use Redis alongside a primary database when you need:
- lower latency for hot reads;
- fewer repeated expensive queries;
- TTL-based ephemeral state;
- fast counters;
- sets, sorted sets, streams, or other Redis-native structures;
- session or rate-limit state;
- a disposable acceleration layer that can be rebuilt.
When the relational database should remain authoritative
Keep data primarily in PostgreSQL, MySQL, or another durable transactional database when you need:
- rich ad-hoc querying;
- relationships and joins;
- foreign-key or uniqueness constraints across durable business records;
- complex transactions;
- large historical datasets;
- auditability and long-term retention;
- a recovery model centered on committed business transactions.
Can Redis be the primary database?
Yes—for the right workload.
Redis can be a primary datastore when its data model is a natural fit and the chosen persistence, replication, backup, and failure semantics meet the application's requirements.
Good examples can include specialized real-time state, counters, leaderboards, streams, or other key/data-structure workloads where Redis itself is the intended system of record.
But “Redis is fast” is not enough reason to replace a relational database.
Before making Redis authoritative, answer:
- How much acknowledged data can be lost in the failure modes we accept?
- How is the dataset backed up and restored?
- How do we query it six months from now when product requirements change?
- How do we enforce business invariants?
- What happens when the dataset outgrows one node?
- What is the cost of keeping the required working set in memory?
If those answers are awkward, the relational database should probably remain the source of truth.
A simple decision rule
Do not ask “Should we use Redis or a database?”
Ask two better questions:
- Which system should own this data?
- Which system should make this access pattern fast?
Often the answers are different.
A relational database can own durable business truth while Redis makes the hottest paths fast. That division gives you Redis' strengths without forcing every part of the application into an in-memory key-value model.

Discussion (0)