How Far One Postgres Database Goes Before You Need Redis or a Queue

A new benchmark pushed Postgres LISTEN/NOTIFY to 60,000 writes per second. The documented limits, the doorbell pattern, and the four conditions that actually justify a second system.

For a one-person product, Postgres alone will usually carry your job queue, your pub-sub notifications and your background processing well past product-market fit, and the case for that claim got sharper this week. A benchmark from DBOS, currently doing the rounds on Hacker News, pushed Postgres LISTEN/NOTIFY to 60,000 stream writes per second, twenty times the naive approach, with 15 to 100 millisecond latency. The advice to bolt on Redis, RabbitMQ or SQS on day one assumes traffic that products at this stage essentially never see. Here are the measured numbers, the documented limits that actually bite, and a decision rule for when the second system earns its keep.

What the benchmark measured

The DBOS post (checked July 25, 2026) tested LISTEN/NOTIFY as the signaling layer for streaming workloads, like pushing LLM tokens to waiting readers. The naive design, a database trigger firing a notification per inserted row, topped out at 2,900 writes per second. The interesting part is why: Postgres takes a global exclusive lock when committing any transaction that contains a NOTIFY, serializing those commits. The fix was architectural, not heroic: writers buffer notifications in memory and flush them periodically, notifications carry no data and merely wake readers, the table remains the source of truth, and a slow polling loop backstops any notification lost to a crash. That design reached 60,000 writes per second on the same hardware, with the database CPU, not the lock, as the final ceiling.

That last detail is the transferable lesson, and it generalizes beyond streaming: use notifications as a doorbell, never as the mail. Readers wake up, then read state from the table. Any design where the notification payload is the data reintroduces both the lock contention and the delivery-guarantee problem.

What the manual says before you hit any of that

The official NOTIFY documentation lists the constraints that matter long before 60,000 of anything:

  • Payloads must stay under 8,000 bytes in the default configuration; the docs themselves tell you to store big data in a table and send the key. The doorbell pattern is official advice, not a community trick.
  • Notifications are delivered only when the sending transaction commits, and a listener sitting inside its own transaction receives nothing until that transaction ends. Long-running transactions and real-time signaling do not mix.
  • The notification queue is 8GB in a standard installation. Postgres logs warnings once it is half full, and if it fills, transactions calling NOTIFY fail at commit.
  • Identical payloads sent on the same channel within one transaction are deduplicated to a single delivery.
  • A transaction that has executed NOTIFY cannot be prepared for two-phase commit.

None of these is exotic. They are exactly the kind of edge you want to know about at design time, and the mitigation for each is the same doorbell pattern the benchmark used.

Translating the ceiling into product terms

This arithmetic is ours. Suppose your product has 10,000 active users each generating 100 background events a day: emails to send, webhooks to process, exports to build. That is one million events per day, which averages out to about 12 events per second. The naive, unoptimized LISTEN/NOTIFY figure of 2,900 per second gives you 240 times that headroom without doing anything clever; the optimized pattern is three orders of magnitude above your load. Even a 100x growth spurt leaves you below the ceiling of the lazy version. For a solo product, the binding constraint is nearly never queue throughput. It is your operational attention, which is precisely what a second infrastructure system consumes.

Queues without a broker

LISTEN/NOTIFY handles wake-ups; it does not give you retries, visibility timeouts or exactly-once handoff. You still do not need a broker for that. Supabase Queues is a durable message queue built on pgmq, an open-source Postgres extension from Tembo: messages live in Postgres, delivery is guaranteed, and a message is delivered exactly once to a consumer within a configurable visibility window. Because the queue is just tables and functions, you operate it with the SQL tools you already run, your queue state joins your business data in one backup, and a job insert can commit atomically in the same transaction as the order that caused it. That atomicity is the quiet killer feature: with a separate broker, "write the row, then enqueue the job" is a distributed-consistency problem you inherit on day one.

The actual switch conditions

Move queueing or messaging out of Postgres when one of these becomes true, and not before:

  1. Sustained high-frequency writes from many producers where NOTIFY sits in the hot path. The global commit lock serializes those transactions; if you are building multi-tenant real-time streaming as the product itself, you will feel it.
  2. Fan-out to consumers that are not database clients. Browsers, mobile apps and third-party services should not hold Postgres connections; that is a job for your application layer or a push service in front of it.
  3. Message volume or size pressuring the limits above: payloads that will not fit the doorbell pattern, or backlogs approaching the queue's capacity because consumers fall behind for hours.
  4. You genuinely need two-phase commit across systems in transactions that also notify.

Note what is not on the list: "we might scale later." Caching is also a separate question; nothing here says Redis is never useful, only that "queue plus pub-sub" is not the reason to add it to a small product.

This is the same argument as the boring stack, but with the numbers attached: the benchmark and the manual agree that one well-understood database covers the messaging needs of a product until it is definitionally no longer small. Every system you do not add is an upgrade cycle, a failure mode and a 3am page that a company of one never staffs. Add the second system when a number in this article shows up in your monitoring, not when a tutorial assumes you already have it.

Discussion

Sign in with Google or just a name. No email link, no password to remember.