Goal is to provide notification of interesting events (record creation, record deletion) and enable subscription to those events.
There are a couple options for doing this in postgres, though each fundamentally rely on a trigger to invoke some action that sends a message:
plpythonu3
In this case the trigger
is used to call a procedure defined in plpythonu3 (or similar scripting language). This procedure can execute any python code (within the environment of the python interpreter linked to the plpythonu3 language), and so can communicate messages to a consumer application that may be local or remote. The protocol used to send the messages is defined by the plpython script implementation.
The plpythonu3 script runs within postgres and is executed with each trigger. Hence, there are obvious performance factors to consider.
This approach is a bit invasive in that the python language extension needs to be installed. In practice, the plpythonu3 language setup has been a bit cumbersome. Note however, that the extension is available by default in pg 13+.
NOTIFY
/LISTEN
In this case the trigger
runs a pg_notify()
method or executes a NOTIFY
SQL statement. A consumer application running on an event loop with a connection of the postgres instance uses LISTEN
to detect events emitted by the NOTIFY
operation.
A benefit of this approach is minimal change to postgres - no extensions or additions are required beyond the trigger to call NOTIFY
.
NOTIFY
messages are limited to 8000 bytes. So generally a key is sent with expectation that a query will be issued to get more information associated with the notification.
If the listener is not operating postgres will continue with normal operations. If there are no listeners, then messages are a NOOP.
To drop the trigger:
pg_amqp
pg_amqp
is a small extension that provides a mechanism to send a message to an AMQP compatible queue service such as RabbitMQ.
The pg_amqp
extension is easy to install and use of a well established messaging protocol significantly reduces the amount of custom code needed. A service like RabbitMQ has broad language support and can be scaled across multiple servers.
The approach supports the option to send much richer messages than the NOTIFY mechanism (RabbitMQ suggests up to 128MB for messages).
A warning is issued by postgres if amqp.publish
is called without the AMQP service running, however there does not appear to be any disruption of normal operations.
Grant permissions to the amqp
schema:
To drop the trigger:
There's also pg-amqp-bridge
which is similar to pg-amqp
, though is implemented with a pattern like option 2 above. Also, pgsql-listen-exchange
implemented in option 2 pattern.