Postgres as queue
Using PostgreSQL as a job queue divides opinion: some engineers praise the simplicity of reusing an existing, ACID-compliant database to manage tasks, avoid dual-write consistency issues, and reduce infrastructure and DevOps overhead. Others argue that databases are costly and complex to scale as queues grow, and that purpose-built systems (like SQS, Redis, or newer workflow engines) offer better performance, isolation, and architecture. The debate centers on trade-offs between “boring” consolidated stacks versus modular, specialized components, with many noting that PostgreSQL-based queues are fine for modest workloads but may become problematic at larger scales or under strict ordering and latency requirements.
When Postgres-as-queue Makes Sense
- Many commenters use Postgres as a job queue successfully for:
- Internal tools and low–to–moderate traffic apps (e.g., ~10k–1M jobs/day).
- Cases where the database is already required and adding new infra is politically or operationally hard.
- Work that isn’t ultra-latency-sensitive and doesn’t need “web scale.”
- Benefits cited:
- Single source of truth with ACID semantics; queue and business data share transactions.
- Simpler architecture: fewer services, fewer “moving parts,” easier local dev.
- Easy evolution using SQL, indexes, and schema changes; no new tech expertise needed.
Arguments Against Postgres-as-queue
- Some respondents describe it as one of the worst architectural decisions they’ve seen, though details are sparse (sometimes due to regulatory constraints).
- Main concerns:
- Mixing concerns: likened to using an IMAP server as an app queue; modularity and separation are considered more robust long-term.
- Scaling cost and complexity: Postgres can become expensive or cumbersome at high throughput and with many workers.
- Risk of lock contention, connection limits, and complex failure handling when worker counts grow.
Transactional Consistency & Patterns
- Strong support for using the database queue to avoid the “dual write” problem (DB + external queue not in one transaction).
- Transactional outbox / saga patterns are mentioned as alternatives when an external queue is used.
- Idempotency and leases (
lease_expiretimestamps, “visible_at” fields) are common patterns for handling crashed workers and retries.
Postgres Features Highlighted
SKIP LOCKEDfor concurrent workers without blocking.- Partial indexes and filtered queries for efficient selection of “ready” tasks.
LISTEN/NOTIFY(sometimes via triggers or extensions) to:- Reduce polling.
- Achieve low-latency wakeups when new work appears.
- But they are not durable; consumers must still periodically scan to cover missed notifications.
Alternatives & Ecosystem
- Other SQL databases (MySQL, SQL Server, MariaDB) offer similar primitives (
READPAST, filtered indexes, built-in message brokers). - Dedicated queues and workflow systems (SQS-like, Temporal-style, etc.) are suggested once scale or complexity justifies extra infrastructure.
- Several libraries in different languages implement Postgres-backed job queues, indicating an active ecosystem.