Unless it has been updated, another caveat of LISTEN / NOTIFY is that it becomes slower and slower the more NOTIFY you use within a transaction.
If I remember correctly, the reason is that postgres attempts to de-duplicate messages using a naive quadratic algorithm, causing horrible slowdowns for large query with a FOR EACH ROW trigger.
The way we mitigated that is by creating a temporary table and write the notification payloads. An AFTER * trigger reads distinct rows, groups the data and sends the messages.