deniz.in

Markets

Weather

Loading weather

· via dev.to (home feed)

PostgreSQL NOTIFY queue failure reproduced with one idle transaction

A dev.to reproduction shows how a listener left idle inside an open transaction fills PostgreSQL's NOTIFY queue, and why raising max_notify_queue_pages does not fix it.

PostgreSQL NOTIFY queue failure reproduced with one idle transaction

A developer has published a compact, reproducible account of one of PostgreSQL's quieter failure modes: the error too many notifications in the NOTIFY queue. Writing on dev.to, the author recreated the condition on PostgreSQL 17 running in Docker with two psql sessions, and showed that the deciding factor is not queue capacity but a transaction left open on the listening side.

Shrinking the queue to 512 KiB

PostgreSQL's notification queue is multi-gigabyte by default, so filling it under normal settings would take an extreme workload. To make the experiment practical, the author started the server with max_notify_queue_pages=64. Because each page is 8 KiB, total queue capacity came to just 512 KiB.

The test used two connections. In the first, the listener ran LISTEN demo; followed by BEGIN;, then stayed idle while holding that transaction open. From the second connection, the author issued 100 large pg_notify() calls.

The results were easy to observe, according to the post: 64 sends succeeded, 36 failed, and pg_notification_queue_usage() reported the queue at 100 percent capacity. Every failed send returned the error above.

The open transaction is the real culprit

The interesting part is why the queue filled at all. The listener never sent anything; it simply remained inside an open transaction while notifications arrived. The author's stated takeaway is that a larger max_notify_queue_pages only adds breathing room. It does nothing about the transaction that is blocking notification cleanup. With cleanup blocked, incoming notifications accumulated until capacity was exhausted and senders began failing.

That distinction matters operationally. The error looks like a capacity problem, and the obvious response is to raise the limit. The reproduction shows this buys time at best: as long as a transaction pins the queue, notifications keep accumulating and the limit is reached again, only later.

Recovery is a single COMMIT

The failure also proved fully reversible. Returning to the listener session and running COMMIT; delivered the pending notifications, and a follow-up check with SELECT pg_notification_queue_usage(); showed usage back at 0. No restart or manual intervention was needed; ending the transaction let the queue drain.

The author points to a longer companion write-up that covers the Docker Compose setup, the SQL commands, queue measurements at each step, a look at the notify implementation, and verification of the recovery.

Why it matters

LISTEN/NOTIFY is a common way to build lightweight event channels and job triggers without standing up a separate message broker. This reproduction shows how easily the mechanism can be wedged by accident: a listener that begins a transaction and then idles pins the queue, while the resulting errors surface on the sender side, far from the actual cause.

The practical guidance that follows is straightforward. Keep transactions short on connections that use LISTEN, treat pg_notification_queue_usage() as an early-warning metric worth monitoring, and when the too-many-notifications error appears, hunt for a stuck transaction before reaching for a larger max_notify_queue_pages.

  • #postgresql
  • #listen-notify
  • #databases
  • #queues
  • #debugging