Do you need Redis? PostgreSQL does queuing, locking, and pub/sub (2021)
PostgreSQL’s built‑in features for queuing, locking, and pub/sub are prompting some engineers to question whether they really need Redis for many common workloads. Contributors note that for modest throughput and single‑database architectures, using Postgres can simplify operations, reduce infrastructure, and still perform well enough, especially with features like advisory locks and SKIP LOCKED queues. Others counter that Redis (and its fork Valkey) remains better suited for low‑latency caching, high‑volume key‑value writes, and shared in‑memory data across multiple processes or hosts, arguing that treating Postgres as a universal tool can introduce bloat, vacuum issues, and operational complexity.
Scope of the Debate
- Article’s claim: PostgreSQL can handle queuing, locking, and pub/sub, reducing the need for Redis.
- Thread broadens this to: when is Redis actually warranted vs “just use Postgres” (or even in-process memory)?
Performance and In‑Memory vs Local DB
- Several argue Redis’ core value is ultra‑low latency, in‑memory data structures, especially when co‑located with the app.
- Others counter that:
- A plain in‑process hashmap is faster still if only one process needs the data.
- PostgreSQL on the same host with local/Unix sockets and shared buffers can be very fast; properly tuned, many workloads complete well under a millisecond.
- Some benchmark links are criticized as flawed (e.g., no prepared statements), making direct Redis vs Postgres performance claims unclear.
Redis Use Cases Highlighted
- Shared cache or session store for multiple web workers or hosts.
- IPC and “shared memory” for languages or architectures without good global state.
- Backing job systems (e.g., using lists, sorted sets, hashes as queues and indexes).
- Use of special data structures (HyperLogLog, Bloom/Cuckoo filters, sorted sets, token buckets).
- Persistence across app restarts without re‑implementing a small database.
PostgreSQL Capabilities and Limits
- Queues:
SELECT … FOR UPDATE SKIP LOCKEDworks well for modest throughput; at higher rates, table bloat and vacuum behavior become concerns. Partitioning queues by time is suggested. - Locks: Advisory locks are useful but have a global integer keyspace and shared namespace; some see this as awkward for application‑level locking.
- Pub/sub: Works, but message size is limited (~8 KB); workarounds (store payloads in tables) add complexity.
- Caching: Writes, updates, vacuuming, durability, and lack of automatic TTL make Postgres a weaker fit than Redis for high‑churn caches, though unlogged tables and tuning can mitigate this.
Operational Trade‑offs and Design Guidance
- Many emphasize simplicity: start with Postgres; add Redis (or similar) only when proven necessary.
- Others note Redis is easy to deploy and offloads low‑value, high‑churn data (sessions, cache) from the primary DB.
- Concerns raised about overloading Postgres with every responsibility, impact on migrations, locking, and UI latency.
- Consensus direction: Postgres can go very far (especially for moderate queues/locks), but Redis remains better for high‑performance caching and specialized in‑memory data structures.