Every backend team eventually has the same argument in a different wrapper: can we keep this in Postgres, or do we need another moving part?
DBOS poured fuel on that argument with a July 24 post claiming its optimized Postgres LISTEN/NOTIFY-backed streams reached up to 60,000 writes per second on a single Postgres server with millisecond-scale latency. That number is attractive because it attacks a developer instinct that has hardened into folklore: LISTEN/NOTIFY is cute, but it does not scale.
The better reading is more useful and less tribal. LISTEN/NOTIFY can be good infrastructure if you understand what it is. It becomes dangerous when you pretend it is a full message broker.
What DBOS changed
DBOS started with a simple stream design: write chunks into a table, then use LISTEN/NOTIFY to wake readers when new data arrives. That is exactly the kind of architecture teams reach for when they want low-latency behavior without adding Redis, Kafka, NATS or another queue.
The initial version called NOTIFY for every stream write. DBOS says that hit a wall around 2.9K stream writes per second. The bottleneck was not obvious CPU, memory or I/O pressure. It was Postgres behavior around NOTIFY at transaction commit.
The optimized version changed the shape of the problem. Instead of firing a notification for every write, DBOS buffered notifications in memory and flushed them in batches. Readers still used notifications to wake up quickly, but they also had a low-frequency polling fallback in case a process crashed before buffered notifications were delivered.
That design detail is the whole lesson. The notification is not the data. The table is the data.
| Approach | What happens |
|---|---|
| NOTIFY on every write | Low latency, but commit-time contention can dominate |
| Buffered/batched NOTIFY | Fewer lock hits and better write throughput |
| Polling only | Simpler, but interactive latency or database load can get ugly |
| NOTIFY plus fallback polling | Fast wakeups with a safety net for missed nudges |
Why Postgres behaves this way
PostgreSQL’s official documentation describes NOTIFY as a way to send notification events to sessions that have issued LISTEN on a channel. It also explains several constraints that matter in production: notifications inside a transaction are delivered only if the transaction commits, listening sessions receive notifications between transactions, payloads are limited, and a queue holds pending notifications.
That is elegant for signaling. It is not a magic transport layer.
DBOS points to a global lock involved in preserving notification order at commit. Its argument is not that the old warnings were imaginary. It is that the warnings apply most painfully when you ask NOTIFY to do the wrong job at the wrong frequency.
Recall.ai’s earlier “does not scale” post remains useful because it reflects a real production concern: if notification behavior serializes important write paths or wakes too much work, the database can look idle while latency goes bad. The DBOS response is not a dunk. It is a design pattern: batch the nudge, keep the source of truth in a table, and make readers resilient to missed notifications.
The part developers should not overlearn
The tempting takeaway is “you do not need Redis.” That is too broad.
You may not need Redis for a particular class of low-latency database-backed streams. You may not need Kafka for a modest internal notification path. You may be able to avoid a separate queue when durability already lives in Postgres and the notification only tells clients to go look.
But if you need cross-service fanout at high volume, replay semantics, long retention, consumer groups, external delivery guarantees, multi-region event flow or operational isolation from your primary database, a dedicated queue is not architecture vanity. It is the tool doing its job.
The best engineering judgment here is boring and valuable: fewer systems are better until the workload proves otherwise. Then the extra system has to earn its keep.
Why this is relevant now
AI products are making this pattern more common. Streaming tokens, workflow updates, background-job progress, collaborative editing, agent traces and dashboard events all want to feel live. Many teams already have Postgres. Adding a heavyweight event stack for every live UI can be wasteful.
That is why DBOS’s article lands. It gives developers a more nuanced option than “poll badly” or “ship another broker on day one.” It also makes clear that the implementation details are not optional. Batch too aggressively and latency suffers. Poll too often and you rebuild the load problem. Treat notifications as durable messages and you will eventually lose something important.
Bottom line
Postgres LISTEN/NOTIFY is not dead, and it is not a universal message bus.
The DBOS benchmark is relevant because it shows a practical middle lane: use Postgres as the durable source, use NOTIFY as a fast nudge, batch the expensive part, and keep a fallback for the moment reality interrupts your clean design. That is the kind of infrastructure opinion that survives contact with production.