PostgreSQL isn’t just a powerful relational database; it also supports real-time asynchronous messaging using the built-in LISTEN and pg_notify commands. These tools enable communication between sessions inside the same database, letting you trigger events, monitor activity, and synchronize workflows without external message brokers.
In this blog, you’ll learn how to:
* Use LISTEN and pg_notify for real-time messaging
* Run a live terminal demo with two psql sessions
* Track active listeners with pg_stat_activity
* Implement pg_notify inside triggers with a full example
What are LISTEN and pg_notify?
PostgreSQL has a native publish/subscribe system:
LISTEN
Registers the current session to receive notifications sent on a given channel.
From psql you can see its syntax with:
\h LISTEN
Output:
Command: LISTEN
Description: listen for a notification
Syntax:
LISTEN channel
URL: https://www.postgresql.org/docs/17/sql-listen.html
NOTIFY
Sends a notification (optionally with a payload) to all sessions listening on a channel.
Syntax help:
\h NOTIFY
Output:
Command: NOTIFY
Description: generate a notification
Syntax:
NOTIFY channel [ , payload ]
URL: https://www.postgresql.org/docs/17/sql-notify.html
When Should You Use It?
Use this feature to:
* Trigger events after database changes
* Communicate between sessions or scripts asynchronously.
* Implement lightweight real-time messaging within PostgreSQL.
* Avoid external message brokers for simple event signaling.
Simple Live Demo with Two psql Sessions
Session 1 — Listen on a Channel
Run:
LISTEN demo_channel;
The session now waits silently for notifications on demo_channel.
Session 2 — Send a Notification
Run:
SELECT pg_notify('demo_channel', 'Hello from pg_notify!');
You’ll see:
pg_notify
-----------
(1 row)
Important: See the Message in Session 1
In psql, notification messages appear only when the prompt refreshes.
Press ENTER or run a query like SELECT 1; in Session 1 to reveal:
Asynchronous notification "demo_channel" with payload "Hello from pg_notify!" received from server process with PID 4218.
Track Active Listeners with pg_stat_activity
To find sessions currently listening on channels:
SELECT pid, application_name, state, wait_event_type, wait_event, query
FROM pg_stat_activity
WHERE query LIKE 'LISTEN%';
This output shows active listening sessions for debugging or monitoring.
Using pg_notify Inside Triggers — Complete Example
You can automate sending notifications on table changes using triggers.
Step 1: Create a Sample Table
CREATE TABLE demo_users (
id SERIAL PRIMARY KEY,
username TEXT,
email TEXT
);
Step 2: Create the Trigger Function
CREATE OR REPLACE FUNCTION notify_user_changes() RETURNS trigger AS $$
DECLARE
action TEXT;
BEGIN
IF TG_OP = 'INSERT' THEN
action := 'Inserted';
ELSIF TG_OP = 'UPDATE' THEN
action := 'Updated';
END IF;
PERFORM pg_notify(
'user_changes_channel',
action || ' user: ID=' || NEW.id || ', Username=' || NEW.username
);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
Step 3: Attach the Trigger to the Table
CREATE TRIGGER trg_notify_user_changes
AFTER INSERT OR UPDATE ON demo_users
FOR EACH ROW
EXECUTE FUNCTION notify_user_changes();
Step 4: Listen to the Channel (Session 1)
LISTEN user_changes_channel;
Step 5: Test by Inserting and Updating (Session 2)
Insert:
INSERT INTO demo_users (username, email) VALUES ('cybrosys 'cybrosys@example.com');
Switch to Session 1 and press ENTER. You should see:
Asynchronous notification "user_changes_channel" with payload "Inserted user: ID=1, Username=cybrosys" received from server process with PID 5055.
Update:
UPDATE demo_users SET email = 'cybrosys@newmail.com' WHERE id = 1;
Press ENTER in Session 1 again to see:
Asynchronous notification "user_changes_channel" with payload "Updated user: ID=1, Username=cybrosys" received from server process with PID 5055.
Conclusion
PostgreSQL’s LISTEN and pg_notify commands provide a robust and efficient way to implement real-time communication directly within your database, eliminating the need for external messaging systems. This built-in pub/sub mechanism is lightweight, reliable, and seamlessly integrates with your existing workflows.
The trigger example demonstrated in this blog highlights how easily you can automate notifications on data changes, enabling powerful event-driven architectures, real-time monitoring, and responsive applications. Whether you’re building simple alert systems or complex asynchronous workflows, these features allow your database to actively participate in the communication process.
By experimenting with two psql sessions—one listening on a channel and the other sending notifications—you’ll gain hands-on experience that reveals the true power of PostgreSQL’s asynchronous messaging. Remember, to see messages in psql, you need to press ENTER or run a query, as notifications are delivered asynchronously.