Node.js
PostgreSQL
LISTEN/NOTIFY
real-time applications
database notifications

Node.js and postgres LISTEN

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

PostgreSQL LISTEN and NOTIFY give a Node.js application a lightweight way to react to database events without constant polling. The main rule is to treat the listener as a long-lived dedicated database connection and to understand that notifications are event hints, not a durable message queue.

How LISTEN and NOTIFY Work

One PostgreSQL session executes LISTEN channel_name. Another session later sends NOTIFY channel_name, 'payload'. Every listening session on that channel receives the notification.

This is useful for cache invalidation, background workers, and simple real-time updates where the application only needs to know that something changed.

Basic Node.js Listener with pg

A straightforward listener using the pg package looks like this:

javascript
1const { Client } = require('pg');
2
3async function main() {
4  const client = new Client({
5    connectionString: process.env.DATABASE_URL,
6  });
7
8  await client.connect();
9  await client.query('LISTEN orders_changed');
10
11  client.on('notification', (msg) => {
12    console.log('channel:', msg.channel);
13    console.log('payload:', msg.payload);
14  });
15
16  client.on('error', (err) => {
17    console.error('listener connection error', err);
18  });
19}
20
21main().catch(console.error);

To send a notification from SQL:

sql
NOTIFY orders_changed, 'order-42';

When PostgreSQL emits that event, the Node process receives it through the notification handler.

Use a Dedicated Connection

Do not put LISTEN on a pooled connection that your application also uses for ordinary queries. A pooled client may be returned to the pool, replaced, or reused unexpectedly.

Instead, keep a dedicated long-lived client just for notifications. Use your normal connection pool separately for regular reads and writes.

That separation avoids many hard-to-debug issues where notifications seem to stop randomly because the listening connection was not actually stable.

Common Pattern with Triggers

A common setup is to fire notifications from a trigger when a table changes.

sql
1CREATE OR REPLACE FUNCTION notify_order_change()
2RETURNS trigger AS $$
3BEGIN
4  PERFORM pg_notify('orders_changed', NEW.id::text);
5  RETURN NEW;
6END;
7$$ LANGUAGE plpgsql;
8
9CREATE TRIGGER orders_notify_trigger
10AFTER INSERT OR UPDATE ON orders
11FOR EACH ROW
12EXECUTE FUNCTION notify_order_change();

With that in place, Node.js gets notified whenever rows in orders are inserted or updated.

Understand the Reliability Model

LISTEN/NOTIFY is not a durable job queue. Notifications are delivered to sessions that are currently connected and listening. If your Node listener is down, it will not later replay the missed notifications automatically.

That means LISTEN/NOTIFY works best for:

  • cache invalidation
  • “something changed” signals
  • lightweight coordination

If you need guaranteed delivery, replay, or durable backpressure handling, use a proper queue or store events in a table that workers can read reliably.

Reconnect and Resubscribe

Production code should reconnect if the listener connection drops. On reconnect, issue the LISTEN command again because subscription state belongs to the session that was lost.

A simple reconnection strategy is often enough for internal tools, but a production service should also log disconnects, back off between retries, and expose health status so you know when the listener is unhealthy.

Common Pitfalls

The most common mistake is using a connection pool client for LISTEN and expecting the subscription to behave like a permanent socket. Use one dedicated client instead.

Another issue is treating notifications as a durable messaging system. If the listener is offline, notifications can be missed.

People also put too much data in the payload. Keep payloads small and let the application fetch full details if needed.

Finally, remember that LISTEN/NOTIFY is about signaling, not about replacing a broader event-processing architecture.

Summary

  • 'LISTEN/NOTIFY lets Node.js react to PostgreSQL events without polling.'
  • Use a dedicated long-lived pg client for the listener connection.
  • Triggers can publish notifications automatically when tables change.
  • Notifications are lightweight signals, not a durable queue.
  • Reconnect logic must resubscribe with LISTEN after a dropped session.

Course illustration
Course illustration

All Rights Reserved.