> Full Neon documentation index: https://neon.com/docs/llms.txt

# Using LISTEN and NOTIFY for Pub/Sub in PostgreSQL

A step-by-step guide describing how to use LISTEN and NOTIFY for pub/sub in Postgres

PostgreSQL has a built-in mechanism for publish/subscribe (Pub/Sub) communication using the `LISTEN` and `NOTIFY` commands.
This allows different sessions to send messages to each other using Postgres, without needing a separate service like Kafka or RabbitMQ.

## Steps

- Overview
- Set Up a Listener in Node.js
- Send a Message using `NOTIFY`
- Limitations of `LISTEN`/`NOTIFY`

### Overview

At a high level, the following is how `LISTEN` and `NOTIFY` are used.

1. A client subscribes to a notification channel using `LISTEN`.
2. Another client sends a message to that channel using `NOTIFY`.
3. The subscribed client receives the notification asynchronously.

### Set Up a Listener in Node.js

Because of connection pooling, setting up a pub/sub listener in the Neon console is tricky.
But you can create a Node.js script that listens to notifications on the channel `my_channel` as follows.
Note that you do **not** need to explicitly create the `my_channel` channel, subscribing to the channel also creates the channel.

Create a new directory and initialize a new Node.js project.

```bash
mkdir pg-listen-notify
cd pg-listen-notify
npm init -y && npm install pg dotenv
```

Then, create a new file `listener.js` with the following content.

```javascript
const { Client } = require('pg');
require('dotenv').config();

const client = new Client({
  connectionString: process.env.DATABASE_URL,
});

async function setupListener() {
  await client.connect();
  await client.query('LISTEN my_channel');
  console.log('Listening for notifications on my_channel...');

  client.on('notification', (msg) => {
    console.log('Received notification:', msg.payload);
  });
}

setupListener().catch(console.error);
```

Make sure to disable connection pooling in your Neon connection string (make sure your connection string does not include `-pooler`).

![Connection String without Pooler](https://neon.com/docs/connect/connection_details_without_connection_pooling.png)

`LISTEN` and `NOTIFY` are session-specific features and are not compatible with Neon connection pooling.

Create a `.env` file in the same directory with your Neon connection string.

```
DATABASE_URL=your_neon_connection_string_without_pooler
```

Run the listener script:

```bash
node listener.js
```

You should see the following output:

```
Listening for notifications on my_channel...
```

Keep the above script running, you will trigger a notification in the next section.

### Send a Message using NOTIFY

With the listener now configured, connect to your Neon database using the [Neon SQL Editor](https://neon.com/docs/get-started/query-with-neon-sql-editor) or a client like [psql](https://neon.com/docs/connect/query-with-psql-editor). Then, run the following command to publish a notification to the `my_channel` channel.

```sql
NOTIFY my_channel, 'Hello from another session!';
```

After running the above, your Node.js script should print out the following output.

```
Received notification: Hello from another session!
```

You can also use the `pg_notify()` function as follows, which is equivalent to the `NOTIFY` command above.

```sql
SELECT pg_notify('my_channel', 'Hello from pg_notify!');
```

Note that you don't need to explicitly create a channel.

### Limitations of LISTEN/NOTIFY

Postgres `LISTEN` and `NOTIFY` run entirely in memory and do not persist any data.
If there are no listeners when a `NOTIFY` runs, the message disappears and Postgres does not provide a mechanism to replay messages.
While the memory overhead of `LISTEN` is minimal, `LISTEN` can cause performance degradations at scale if notifications start using up too much memory.

There is also no way to ensure that a message was delivered to a listener.
If you need message persistence or guarantees that a message was processed, you should look at dedicated message queues like RabbitMQ or Kafka.

If you are using `LISTEN` and `NOTIFY`, you should disable Neon's [Scale to Zero feature](https://neon.com/docs/introduction/scale-to-zero).
If Neon scales your compute to 0, [it will terminate all listeners](https://neon.com/docs/reference/compatibility#session-context), which may lead to lost messages when your database reactivates.

## Resources

- [PostgreSQL Documentation on LISTEN and NOTIFY](https://www.postgresql.org/docs/current/sql-listen.html)
