Пул соединений в PostgreSQL: чек-лист для продакшена
Большой пул не ускоряет PostgreSQL автоматически: он может лишь перенести очередь с приложения на базу и увеличить расход ресурсов. Проверьте лимит соединений, режим PgBouncer, поведение драйвера и метрики ожидания — по этому чек-листу.

Если при росте числа запросов приложение упирается в ожидание соединения, просто увеличить пул — не всегда решение: PostgreSQL получит больше одновременной работы и может начать отвечать медленнее. Этот чек-лист поможет выбрать между пулом в приложении, PgBouncer и прямыми подключениями, а затем проверить конфигурацию на PostgreSQL 16 и PgBouncer 1.23. Названия параметров и совместимость сверяйте с документацией именно вашей версии.
Сначала определите, где стоит очередь
Пул соединений переиспользует открытые подключения вместо того, чтобы создавать новое для каждого запроса. Но у очереди может быть несколько мест: запрос ждёт свободное соединение в приложении, PgBouncer ждёт серверное соединение или сама база занята обработкой запросов. Увеличение лимита помогает только в первом случае и только если PostgreSQL выдерживает дополнительную параллельную работу.
Перед настройкой соберите данные за период пиковой нагрузки:
- сколько экземпляров приложения одновременно работает и сколько процессов или воркеров запускает каждый;
- какой максимальный и текущий размер пула настроен в каждом экземпляре;
- сколько подключений занято, сколько простаивает и сколько запросов ждёт получения соединения;
- сколько подключений PostgreSQL одновременно использует для приложения, фоновых задач, миграций, мониторинга и администрирования;
- как меняются время ответа базы и ожидания в ней, когда растёт число активных запросов.
Сравнивайте показатели в один и тот же период. Если приложение ждёт соединение, а база при этом не загружена и подключений немного, узкое место может быть в слишком маленьком пуле. Если же база уже занята, а увеличение параллельности удлиняет запросы, дополнительные подключения проблему усугубят.
Выберите схему, а не максимальное число
У пула в приложении и PgBouncer разные задачи. Первый ограничивает и переиспользует подключения внутри процесса приложения. PgBouncer принимает клиентские подключения и может распределять их по меньшему числу серверных соединений. Прямые подключения проще, но каждое клиентское соединение доходит до PostgreSQL.
| Вариант | Что выигрываете | Чем платите | Когда рассматривать |
|---|---|---|---|
| Пул в приложении | Меньше постоянных подключений, чем при создании соединения на каждый запрос; настройка рядом с кодом. | Суммарное число соединений растёт вместе с числом экземпляров и процессов приложения. | Небольшая или предсказуемая нагрузка; число процессов и лимиты можно посчитать и контролировать. |
| Пул приложения плюс PgBouncer в режиме session | Клиентское соединение привязано к серверному на время сессии; совместимость с поведением сессии обычно проще, чем в режиме transaction. | Свободные клиентские подключения могут удерживать серверные, поэтому мультиплексирование ограничено. | Нужен прокси, но приложение полагается на состояние соединения между транзакциями. |
| Пул приложения плюс PgBouncer в режиме transaction | Серверное соединение выдаётся на транзакцию и после её завершения может достаться другому клиенту. | Нельзя без проверки рассчитывать на состояние, сохраняемое между транзакциями на одном серверном соединении. | Много коротких транзакций и проверенная совместимость драйвера и приложения. |
Транзакционное мультиплексирование¹ не делает запросы быстрее само по себе. Оно позволяет обслуживать больше клиентских подключений меньшим числом серверных соединений, если клиентам не нужно постоянно удерживать одно и то же соединение.
Настраивайте не «самый большой пул», а максимальную очередь, которую система способна обработать без нарушения времени ответа.
Чек-лист настройки
- Посчитайте верхнюю границу подключений от приложения. Умножьте лимит пула на число процессов приложения, которые могут одновременно запуститься. Отдельно добавьте воркеры и другие сервисы с собственными пулами. Проверьте результат на максимальном количестве экземпляров при масштабировании и во время деплоя, когда старые и новые экземпляры могут работать одновременно. Проверка: расчёт учитывает не среднее число процессов, а максимальное.
- Оставьте резерв PostgreSQL. В бюджет входят не только веб-запросы, но и фоновые задачи, миграции, мониторинг и доступ для аварийной диагностики. Не задавайте лимит пула, равный
max_connections: это параметр сервера, а не бюджет одного приложения. Проверка: после вычитания остальных потребителей остаётся запас на обслуживание и редкие операции. - Ограничьте размер пула приложения. Учитывайте, что настройка часто действует на процесс, а не на весь кластер приложения. Сопоставьте её с числом процессов и экземпляров. Проверка: при максимальном масштабе сумма лимитов не превышает выделенный приложению бюджет.
- Если используете PgBouncer, определите его режим осознанно. Session сохраняет привязку клиента к серверному соединению на время сессии; transaction — только на время транзакции. Для transaction проверьте использование временных таблиц, команд изменения состояния сессии, LISTEN, блокировок, зависящих от сессии, и подготовленных запросов. Поддержка зависит от конкретного поведения приложения, драйвера и конфигурации PgBouncer. Проверка: тесты проходят через тот же режим и версию прокси, что и продакшен.
- Настройте ожидание и тайм-ауты согласованно. Клиентский запрос не должен бесконечно ждать свободного соединения. Сопоставьте время ожидания пула с общим бюджетом времени запроса и тайм-аутами на следующих уровнях. Конкретные параметры зависят от драйвера и версии; не переносите название настройки из чужого примера без сверки документации. Проверка: при заполненном пуле запрос завершается контролируемой ошибкой, а не висит неопределённо долго.
- Проверьте поведение при запуске и сбое. Резкий запуск множества процессов может одновременно открыть слишком много соединений. Проверьте старт после деплоя, восстановление после потери сети и повторные попытки подключения. Проверка: рестарт не создаёт лавину повторных подключений и не выбивает остальные сервисы по лимиту.
- Добавьте метрики с обеих сторон. В приложении следите за занятыми и свободными соединениями, временем ожидания, ошибками получения соединения и тайм-аутами. В PostgreSQL — за количеством и состоянием подключений, активностью запросов и ожиданиями. Для PgBouncer смотрите клиентские и серверные подключения и ожидание свободного серверного соединения. Проверка: графики позволяют отличить очередь в пуле от перегрузки базы.
- Проверьте лимиты в реалистичном сценарии. Нагрузочный тест должен включать длительные запросы, фоновые задачи и число процессов, близкое к пиковому. Сравните не только пропускную способность, но и время ожидания соединения, задержку запросов и число активных соединений. Проверка: увеличение пула не ухудшает задержки и не доводит сервер до отказа в новых подключениях.
Что обычно ломается
Пул вырос вместе с числом реплик. Лимит выглядел безопасным на одном экземпляре, но после масштабирования приложения число подключений умножилось. Пересчитайте бюджет на максимальное число процессов и проверьте сценарий деплоя.
Transaction-режим меняет смысл сессионного состояния. Код может работать при прямом подключении и ломаться за PgBouncer, если рассчитывает на то же серверное соединение после завершения транзакции. Проверьте каждый такой сценарий интеграционными тестами или выберите другой режим.
Ожидание соединения приняли за медленную базу. Если долго занято соединение, причина может быть в долгой транзакции или запросе приложения, а не в малом размере пула. Найдите, кто удерживает соединение, и проверьте длительность транзакций и запросов.
Тайм-ауты запускают шторм повторов. Когда все клиенты одновременно переподключаются, нагрузка на базу резко возрастает. Проверьте стратегию повторов в драйвере и приложении, добавьте ограничение частоты и убедитесь, что ошибка не вызывает бесконечный цикл запросов.
Инвалидация данных и кеширование запросов могут снизить нагрузку на базу, но это отдельные задачи: здесь речь только об управлении соединениями.
Что делать дальше
Начните с расчёта максимального числа процессов и подключений, затем измерьте очередь в приложении и состояние соединений PostgreSQL в пиковое время. Если выбираете PgBouncer, сначала прогоните приложение в тестовой среде через нужный режим, особенно при transaction pooling. После изменения лимитов сравните задержки и ожидания до и после на одинаковой нагрузке; не увеличивайте пул, если очередь уже находится внутри базы.
¹ Транзакционное мультиплексирование — выдача серверного соединения клиенту на время транзакции с последующим возвращением соединения в общий пул.
Тендерный специалист 44-ФЗ / 223-ФЗ: Разбор PDF-документации закупки, поиск «заточек» под поставщика, чек-лист заявки.
Спросить за 20 ₽Источники: PostgreSQL 16: параметры подключений, PgBouncer: конфигурация и режимы пулов
Частые вопросы
Как понять, что мне нужен PgBouncer, а не больший пул приложения?
Можно ли включить transaction pooling без изменений в приложении?
Что будет, если пул выставлен слишком большим?
Подойдёт ли этот чек-лист для другой версии PostgreSQL или PgBouncer?
Какие метрики смотреть в продакшене в первую очередь?
Нужно ли менять max_connections, если приложение не получает соединение?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.