LISTEN / NOTIFY - вбудований у PostgreSQL механізм публікації й підписки. Одне з'єднання підписується на канал, інше надсилає в нього повідомлення:
-- з'єднання A
LISTEN order_events;
-- з'єднання B
NOTIFY order_events, '{"order_id": 42, "status": "paid"}';
-- або функцією, зручно в тригерах
SELECT pg_notify('order_events', json_build_object('order_id', 42)::text);
Підписник отримує повідомлення асинхронно - без опитування таблиці.
Ключові властивості:
- транзакційність: повідомлення доставляються лише після коміту транзакції, що їх надіслала. Відкат - повідомлень немає. Це головна перевага перед відправкою подій із застосунку;
- дедуплікація: однакові повідомлення в одній транзакції об'єднуються в одне;
- без збереження: якщо в момент
NOTIFYніхто не слухає, повідомлення зникає. Підписник, що перепідключився, пропущених повідомлень не отримає; - розмір: до 8000 байтів за замовчуванням - передають ідентифікатор, а не дані;
- черга повідомлень на сервері обмежена (8 ГБ за замовчуванням): повільний підписник, що не читає повідомлення, врешті блокує
NOTIFYдля всіх.
Типове застосування - тригер + NOTIFY:
CREATE FUNCTION notify_order_change() RETURNS trigger LANGUAGE plpgsql AS $$
BEGIN
PERFORM pg_notify('order_events', NEW.id::text);
RETURN NEW;
END;
$$;
Сервіс-підписник отримує id, читає актуальні дані й інвалідує кеш, оновлює пошуковий індекс чи відправляє подію в WebSocket.
Обмеження для веб-застосунку:
- PHP-FPM не тримає довгих з'єднань - слухати потрібно окремим довгоживучим процесом (консольна команда під Supervisor), що читає повідомлення через
pgsqlGetNotifyу PDO; - PgBouncer у режимі transaction pooling не підтримує
LISTEN- підписнику потрібне пряме з'єднання з базою; - гарантій доставки немає: для подій, які не можна втратити, - transactional outbox (таблиця подій), а
NOTIFYлише як сигнал «перевір таблицю», щоб не опитувати її щосекунди.
Порівняно з Redis pub/sub і Reverb: NOTIFY не потребує додаткової інфраструктури й знає про транзакції, але не масштабується на тисячі підписників і не призначений для доставки клієнтам напряму. Схема на практиці: база → NOTIFY → процес-слухач → broadcasting через Reverb до браузерів.