Setu vs. PostgreSQL LISTEN/NOTIFY: Why Logical Replication Ages Better
LISTEN/NOTIFY looks like the obvious answer the first time you need Postgres to call out when data changes. If you want the implementation this comparison is anchored to, see the Setu page.
It is not.
It is a lightweight signaling mechanism. Setu uses PostgreSQL logical replication to read row changes from the WAL, evaluate rules, and deliver actions with offset tracking. That difference matters the moment the change becomes operationally important.
What LISTEN/NOTIFY Actually Gives You
NOTIFY sends an event to connected listeners.
That is useful for:
- ephemeral coordination
- cache invalidation
- wake-up signals between services
- internal tooling with tolerant failure modes
It is not a durable event log.
If the listener is disconnected, the notification is gone. If the payload is too large, you are constrained. If you need replay, you build another system.
What Setu Changes
Setu does not rely on a transient notification channel.
It reads the change stream from PostgreSQL logical replication, so the change exists in a durable sequence before Setu decides what to do with it. That gives you a real delivery workflow:
WAL change
-> decode
-> filter rule
-> deliver destination
-> confirm offset
That is the right shape for production automation.
Why Triggers Break Down
The usual LISTEN/NOTIFY pattern starts with a trigger:
CREATE OR REPLACE FUNCTION notify_user_change()
RETURNS trigger AS $$
BEGIN
PERFORM pg_notify('user_changes', json_build_object(
'id', NEW.id,
'plan', NEW.plan
)::text);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
This works until it does not.
Common failure modes:
- payloads get more complex than the trigger can safely hold
- application logic creeps into the database layer
- listeners miss messages during disconnects
- retries and acknowledgements have to be built separately
- trigger maintenance becomes a hidden coupling point
The database becomes both the source of truth and the message broker. That is a bad trade when the workflow matters.
Why Logical Replication Ages Better
Logical replication was designed for change capture, not just wake-up signals.
Setu benefits from that because it can:
- read real row-level changes
- preserve delivery state with offset confirmation
- apply rules without embedding business logic in SQL triggers
- route one event to multiple destinations
That is a cleaner operational boundary.
The Architecture Difference
LISTEN/NOTIFY
Postgres row change -> trigger -> notification -> listener
Setu
Postgres row change -> logical replication -> rule engine -> delivery
The first is a signal. The second is an activation pipeline.
When LISTEN/NOTIFY Is Enough
Use LISTEN/NOTIFY if:
- the signal is disposable
- missing one event is acceptable
- the consumer can recover from source-of-truth state later
- you want the simplest possible coordination path
That is fine for cache refreshes and lightweight internal coordination.
When Setu Is the Better Fit
Use Setu if:
- the action must happen after a durable change
- you need at-least-once delivery semantics
- you want rule-based filtering on old and new values
- you need to send to webhooks, Slack, or Telegram
- you do not want to maintain trigger code in the database
That is the activation problem.
Trade-offs
| Dimension | LISTEN/NOTIFY | Setu |
|---|---|---|
| Simplicity | Very high | Moderate |
| Durability | Low | Higher |
| Replay | No | Yes, via replication flow |
| Payload size | Limited | Full row change context |
| Delivery guarantees | Weak | At-least-once oriented |
| Best fit | Signals | Production activation |
Decision Framework
- If the consumer can miss the event and recover later, use
LISTEN/NOTIFY. - If the event must survive disconnects and deliver to an external system, use Setu.
- If the database is starting to contain workflow logic, stop and move that logic out.
LISTEN/NOTIFY is a signal bus. Setu is a delivery engine. That is the dividing line.