Redis vs PostgreSQL¶
1. Decision¶
Choose Redis as an in-memory datastore for sub-millisecond ephemeral caching, high-velocity session management, rate limiting, and real-time leaderboards; choose PostgreSQL as a primary relational disk-backed system of record for structured domain entities, complex queries, and ACID transactional durability.
2. 30-Second Answer¶
Redis is an in-memory, single-threaded key-value/data-structure store optimized for microsecond read/write latencies (\(<1\text{ms}\)) and high throughput (\(>100\text{k QPS}\) single node). It supports specialized data structures (Strings, Hashes, Lists, Sets, Sorted Sets, HyperLogLogs, Streams, Bitmaps). PostgreSQL is a persistent, disk-backed relational database providing ACID transactions, MVCC, and complex querying. Redis is primarily used as a caching layer, buffer, or ephemeral state store, whereas PostgreSQL acts as the authoritative source of truth. Using Redis as a primary database carries data loss risks if persistence (RDB/AOF) is misconfigured or RAM limits are reached.
3. Decision Matrix¶
| Option | Best For | Avoid When | Latency | Scalability | Consistency | Operational Complexity |
|---|---|---|---|---|---|---|
| Redis | Caching, session store, rate limit counters, pub/sub, real-time leaderboards | Large datasets exceeding RAM cost limits, complex multi-entity joins, primary source of truth | Sub-millisecond (<1ms) in-memory | Vertical RAM; Horizontal via Redis Cluster (16384 hash slots) | Single-key immediate; Asynchronous primary-replica replication | Low (Standalone); Medium (Cluster/Sentinel) |
| PostgreSQL | Primary storage, complex queries, financial transactions, JSON + SQL relations | Sub-millisecond SLAs, raw write throughput exceeding disk I/O limits | Low (<5ms disk page hit) | Vertical Scale; Read Replicas; Sharding | Strict ACID (Serializable, Repeatable Read) | Medium |
4. Selection Rules¶
| Requirement | Best Choice | Rationale / Example |
|---|---|---|
| Sub-Millisecond Read Latency (<1ms) | Redis | Pure in-memory data access eliminates disk I/O overhead completely |
| Primary System of Record / Durability | PostgreSQL | Write-Ahead Log (WAL) guarantees strict crash-recovery ACID durability |
| Real-Time Ranked Leaderboard | Redis | Sorted Sets (ZADD, ZREVRANGE) execute score operations in \(O(\log N)\) |
| Complex Multi-Table SQL Joins | PostgreSQL | Optimized query planner for complex relational schemas and foreign keys |
| Distributed Atomic Rate Limiting Counter | Redis | INCR + EXPIRE in atomic Redis Lua script prevents concurrency races |
| Geospatial & Vector Hybrid Relational Queries | PostgreSQL | PostGIS and pgvector integrate spatial/vector search natively with SQL |
5. Tradeoffs¶
- In-Memory RAM Speed vs Disk-Backed Capacity Economics
- Gain (Redis): Microsecond performance for all read and write operations.
- Lose (Redis): Extremely expensive per gigabyte compared to NVMe SSD storage; total dataset size bounded by node RAM.
- Data Structure Operability vs SQL Declarative Expressiveness
- Gain (Redis): Rich native primitives (Sets, Sorted Sets, Bitmaps) matching application memory structures.
- Lose (Redis): No declarative query language; queries must be explicitly coded via data structure commands or Lua scripts.
- Single-Threaded Event Loop Execution vs Multi-Process MVCC Concurrency
- Gain (Redis): Zero lock contention; all single-key commands execute atomically without race conditions.
- Lose (Redis): Long-running \(O(N)\) operations (
KEYS *, hugeHGETALL) block the entire event loop, freezing all client traffic. - Persistence Options vs Native Transactional WAL
- Gain (Redis): Flexible persistence modes (RDB snapshots, AOF log, or pure cache mode).
- Lose (Redis): Async persistence risks losing seconds of data during power loss/crash unless using fsync always (which degrades performance).
- Cache Eviction Policies vs Durable Retention
- Gain (Redis): Automatic memory management via eviction policies (
volatile-lru,allkeys-lru). - Lose (Redis): Risk of unexpected data eviction if configured improperly.
6. Interview Counter Questions¶
- Why shouldn't you use Redis as your primary system-of-record database?
- How does Redis single-threaded architecture achieve 100,000+ QPS per instance?
- How do Redis persistence options (RDB vs AOF) compare, and what are their performance tradeoffs?
- How do you implement a distributed lock in Redis (Redlock algorithm vs single instance)?
- What happens when Redis reaches its
maxmemorylimit, and how do eviction policies work? - How does Redis Cluster partition keys using Hash Slots (16,384 slots)?
- How do you prevent cache stampedes (thundering herd) when a key in Redis expires?
- How does Redis Lua scripting guarantee atomicity, and what is its major performance pitfall?
- When would you use Redis Streams instead of PostgreSQL LISTEN/NOTIFY or Apache Kafka?
- How do you maintain data consistency between PostgreSQL primary database and Redis cache?
7. Gold Standard Answers¶
- RAM is volatile and expensive. Redis asynchronous persistence (RDB/AOF) trades durability for latency; hardware crashes can lose un-flushed writes. Redis lacks relational constraints, foreign keys, and complex transactional isolation required for core domain data.
- Redis uses an efficient non-blocking I/O multiplexing event loop (
epoll/kqueue) operating entirely in RAM. Because data lives in memory, processing commands takes nanoseconds, avoiding context switching and thread locking overhead. - RDB (Redis Database) takes compact point-in-time binary snapshots (fast restarts, but potential data loss between snapshot intervals). AOF (Append-Only File) logs every write command (higher durability, but larger file size and slower startup). Standard practice: use both.
- Single instance:
SET resource_key my_random_token NX PX 30000deleted via Lua script verifying token. Redlock uses 5 independent Redis nodes; lock acquired if majority (3/5) grant lock within drift timeout. Redlock is controversial due to clock drift assumptions. - Redis executes the configured
maxmemory-policy:noeviction(returns errors on writes),allkeys-lru/volatile-lru(evicts least recently used keys), orallkeys-lfu(evicts least frequently used keys). - Redis Cluster divides key space into 16,384 logical Hash Slots. Partition Key slot calculated via
CRC16(key) mod 16384. Shards own subsets of slots. Hash tags{user100}:profileforce related keys into the same slot for multi-key operations. - Use Probabilistic Early Expiration (XFetch algorithm), distributed locks (mutex around DB fetch), or background worker refresh jobs before TTL expiration to prevent simultaneous cache misses hitting Postgres.
- Lua scripts execute atomically within the single-threaded event loop, blocking all other incoming commands until execution finishes. Pitfall: slow or infinite loops in Lua scripts freeze the entire Redis server instance.
- Use Redis Streams for lightweight, low-latency log-based message queues with consumer groups when data retention fits in RAM. Use Kafka when message persistence, replayability across weeks, and terabyte scale are required.
- Use Cache-Aside pattern with invalidation: Write to Postgres DB first, then delete key from Redis. Alternatively, use Change Data Capture (Debezium CDC) reading Postgres WAL to asynchronously invalidate Redis keys.
8. Common Mistakes¶
- Running
KEYS *in a production Redis instance, blocking the single-threaded event loop and dropping all application traffic. - Using Redis as a primary database without configuring AOF persistence or secondary replica failover.
- Updating Redis cache before writing to PostgreSQL DB, creating permanent cache inconsistency when DB writes fail.
- Storing massive multi-megabyte payloads in a single Redis key, causing network memory bottlenecks.
- Forgetting to set a TTL on dynamic cache keys, leading to uncontrolled RAM growth and memory eviction crashes.
9. Keywords¶
Redis, PostgreSQL, In-Memory, Event Loop, Single-Threaded, Hash Slots, RDB, AOF, Redlock, Lua Scripting, maxmemory, Eviction Policy, LRU, LFU, Cache-Aside, Debezium CDC.
10. Cheat Sheet¶
- Core Difference: Redis = In-memory sub-millisecond state/cache; PostgreSQL = Disk-backed ACID relational system of record.
- Concurrency: Redis = Single-threaded I/O multiplexing event loop; PostgreSQL = Multi-process MVCC concurrency model.
- Latency: Redis < 1ms; PostgreSQL 2-10ms (page cache hits vs NVMe disk I/O).
- Data Primitives: Redis = Strings, Hashes, Lists, Sets, Sorted Sets (
ZADD), Streams, HyperLogLogs. - Cluster Sharding: Redis Cluster divides key space into 16,384 Hash Slots; use
{hashtag}for multi-key atomic ops. - Consistency Pattern: Write to Postgres first -> Invalidate Redis key second (Cache-Aside pattern).