2026-09-27 · 6 min read · Rahul Chitturi
- sql
- postgresql
- notifications
PostgreSQL NOTIFY delivers a small payload to sessions listening on a named channel. Notifications are sent after the notifying transaction commits, so a rollback emits nothing and a long transaction delays delivery.
A listener can appear healthy while using the wrong pooled connection, waiting inside a transaction, or missing events during reconnect. LISTEN and NOTIFY are signaling primitives, not a durable queue.
Trace the session and transaction
Record the database, role, backend session, channel spelling, LISTEN commit, NOTIFY transaction outcome, driver event loop, and receive timestamp. Verify that the connection receiving notifications remains checked out and actively reads from the server.
- Commit LISTEN before relying on notifications.
- Keep a dedicated listener connection when pooling.
- Treat channel names as SQL identifiers.
- Keep payloads small and non-sensitive.
Separate wake-up from durable state
Store authoritative work in a table within the same transaction that sends NOTIFY. On receipt, query that table by a stable cursor or identifier. This lets the consumer recover after a disconnect, process coalesced signals, and avoid relying on payload delivery for correctness.
Make processing idempotent because reconnect scans, repeated notifications, and worker races can all point to the same work. Monitor queue usage and long transactions that prevent notification cleanup.
Rehearse failure windows
Use Flashman's SQL formatter for LISTEN, NOTIFY, and outbox queries, JSON formatter for synthetic payloads, timestamp converter for commit timelines, and diff for cursor snapshots.
Test commit and rollback, listener startup races, pool checkout, process restart, network loss, failover, duplicate signals, payload limits, full queues, slow consumers, permissions, channel quoting, and catch-up from durable state.