Welcome to pg_relay¶
What is pg_relay?¶
pg_relay lets your PostgreSQL database run a piece of SQL in response to something that happened — reliably, automatically, and with a written record of every outcome.
Here is the whole idea in one sentence: your code calls pgrelay.notify('channel', data) inside a database transaction, and pg_relay takes care of running the action you registered for that channel — outside your transaction, in its own clean transaction. If your calling transaction fails and rolls back, the pg_relay event is rolled back with it. That is a deliberate design choice, not a bug: an event should never exist for something that never actually happened.
pg_relay is made up of two parts:
- A PostgreSQL extension — a set of SQL functions you call directly from the database.
- A Processor — a small program that runs alongside your database and does the actual work.
Pebble IT (the team behind pg_relay) also wrote an article explaining why pg_relay and its companion extension, pg_auto_mv, exist. You can read it on the Pebble IT website.
Why is that useful?¶
Imagine a function that saves a new customer order. Without pg_relay, that same function might also try to send a webhook, refresh a report, and check stock levels — all inside the same database transaction. If any one of those extra steps fails, the whole order can roll back, even though the order itself was fine.
With pg_relay, your function saves the order and calls pgrelay.notify('order_created', order_id). That one call commits along with the order. pg_relay then runs the webhook, the report refresh, and the stock check separately — each in its own transaction — and records the outcome of every single one.
In short: pg_relay lets heavy or "nice to have" work happen after your main transaction, so your application stays fast and responsive while the database gets on with the slower jobs in the background.
Key benefits¶
- Durable. Events survive a Processor restart, a database restart, or a brief network outage. Nothing is lost.
- Logged. Every event is recorded — you can always see what happened, when, and whether it succeeded.
- Validated. Misspelling a channel name raises an error immediately, at the point you called it — not silently doing nothing.
- No hidden logic. The Processor only ever runs what you have told it to run. You stay in control of every action.
Not sure if pg_relay is right for your use case?
See the Technical Guide for a deeper look at the architecture and how it compares to other approaches.
New in v1.1¶
- Per-channel dispatch concurrency — a setting called
concurrency_modelets you decide whether events on a channel can run at the same time as each other, or must be serialised (queued up and run one after another). See Managing Channels. - Fleet control — pause and resume every Processor you are running with a single SQL command, and make them all reload their configuration without a restart. See the Technical Guide's section on fleet control.
- pg_relay_notifier compatibility — pg_relay v1.1 works with the separate pg_relay_notifier 1.0 extension, which sends notifications out of the database: emails via SMTP, and Microsoft 365 email via the Graph API — all delivered by the same Processor, with the same durability, retries, and audit trail as ordinary SQL events. Later releases of pg_relay_notifier are expected to add more delivery options, such as SMS and Teams/Slack messages.
- Multi-master and high-availability modes — a new
--modestartup option lets the Processor run against a single database with automatic failover, or across a multi-write-master (active-active) cluster. Single-database users do not need to configure anything — this is entirely optional. See the Multi-Master Deployment book for the full details.
Continue to the next chapter to see how pg_relay actually works, or jump straight to Core Concepts if you prefer definitions first.