PostgreSQL 19: меньше кода приложения, больше SQL
16 июля 2026 года вышла вторая бета PostgreSQL 19 — после первой беты 4 июня, стабильный релиз ожидается между сентябрём и октябрём. Главное здесь не список возможностей, а направление: работа, которая годами жила в слое приложения, возвращается туда, где ей место, — внутрь самого движка.
Проблема: компенсирующий слой
У любой команды, выпустившей серьёзный продукт, есть код, написанный ради того, чтобы закрыть пробелы в самом SQL:
- Двойной upsert. Вставляем строку, ловим конфликт, затем делаем второй
SELECT, чтобы получить уже существующую строку. Два обращения к базе и гонка между ними. - Отставание реплик. Пишем в основной узел, читаем с реплики — и пользователь сразу после сохранения видит устаревшие данные. Обычный обходной путь: временно направлять чтение на основной узел или использовать sticky sessions. Это заплатки, а не решение.
- Темпоральная история. Нужно изменить цену только на конкретный интервал — и приходится вручную строить таблицы истории и писать логику разрезания периодов.
Всё это работает. Но это дополнительный код, который нужно тестировать и поддерживать, и каждая его строка — потенциальное место для ошибки.
Что изменилось в 19
Результат upsert без второго запроса. INSERT ... ON CONFLICT DO SELECT ... RETURNING возвращает конфликтующую строку вместо пустого результата и повторного запроса.
Read-your-writes на репликах. Новая команда WAIT FOR LSN заставляет реплику дождаться нужной точки журнала предзаписи, прежде чем выполнить запрос.
Стандартные темпоральные изменения. Конструкция FOR PORTION OF теперь поддерживается в UPDATE и DELETE, дополняя темпоральные ограничения из PostgreSQL 18.
Кроме того: GROUP BY ALL, ALTER TABLE ... MERGE PARTITIONS и SPLIT PARTITIONS, новая команда REPACK ... CONCURRENTLY, параллельные воркеры autovacuum, ускорение вставки с проверкой внешних ключей до двух раз и запросы к графам через SQL/PGQ.
Практический пример
-- Раньше: два обращения плюс окно гонки
INSERT INTO customers (email, name)
VALUES ('sara@example.com', 'Sara')
ON CONFLICT (email) DO NOTHING
RETURNING id;
-- Пустой результат означает необходимость второго запроса
-- В 19: одно обращение, существующая строка возвращается сразу
INSERT INTO customers (email, name)
VALUES ('sara@example.com', 'Sara')
ON CONFLICT (email) DO SELECT
RETURNING id, email, created_at;Чтение сразу после записи:
-- На основном узле, сразу после записи
SELECT pg_current_wal_insert_lsn(); -- '0/3A1F0C8'
-- На реплике, перед запросом
WAIT FOR LSN '0/3A1F0C8';
SELECT id, total FROM orders WHERE customer_id = 42;Изменение только одного интервала времени:
UPDATE prices
FOR PORTION OF valid_period
FROM DATE '2026-08-01' TO DATE '2026-09-01'
SET amount = amount * 0.9
WHERE sku = 'ABC-123';Оговорки из практики
- Бета остаётся бетой. В продакшн её ставить нельзя. Правильное применение этого этапа — копия ваших данных, ваши реальные запросы и отчёт о любом странном поведении.
- `WAIT FOR LSN` — не волшебство. LSN нужно передать от пишущего узла к читающему через контекст запроса (заголовок или cookie), а также предусмотреть таймаут и запасной путь на основной узел.
- JIT теперь отключён по умолчанию. Тяжёлым аналитическим запросам, которые на него опирались, потребуется явное включение и замеры до и после.
- Настройки безопасности тоже сдвинулись. Аутентификация RADIUS удалена, а успешная аутентификация через
md5теперь выдаёт предупреждения. Проверьтеpg_hba.confдо обновления. - `default_toast_compression` по умолчанию стал `lz4`.
- Мажорное обновление — это проект, а не команда. Нужен
pg_upgradeлибоpg_dump/pg_restore, и его место в календаре — тот же переход к плановым обновлениям, что и в программе security-релизов Next.js.
Вывод
Направление PostgreSQL 19 важнее любой отдельной возможности: чем больше логики корректности данных переезжает из приложения в движок, тем меньше площадь, на которой может жить ошибка. Читать release notes и гонять бету на копии своих данных стоит сейчас — до того, как осенью выйдет стабильная версия.
Первоисточник: анонс PostgreSQL 19 Beta 2 и анонс Beta 1 от проекта PostgreSQL.