awesome-everything EN
↑ Обратно к восхождению

Базы данных

Ландшафт пулеров 2026, serverless connection storms и полная таксономия отказов

Суть PgBouncer против Odyssey, PgCat и Supavisor — когда использовать каждый; connection storm при cold start serverless; восемь режимов отказов и как обнаружить каждый.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на senior-высоте — в орбите
◷ 16 min

B2B SaaS на Postgres достигает 5 000 QPS пика. Что использовать — PgBouncer, Odyssey, PgCat, Supavisor или RDS Proxy? Ответ зависит от того, в чём узкое место: однопоточная пропускная способность, serverless cold start, масштаб multi-tenant или маршрутизация к read-репликам.

Ландшафт пулеров 2026

PgBouncer по-прежнему production-рабочая лошадка: однопоточный C, ~2 КБ на pooled-соединение, battle-tested за десятилетие, 1.21+ закрывает пробел с prepared statements. Используйте, когда нужен минималистичный, хорошо понятный пулер, располагающийся рядом с Postgres. Ограничение: однопоточность означает потолок одного ядра CPU для пропускной способности PgBouncer; при очень высоком QPS через один инстанс нужно несколько PgBouncer за HAProxy.

Odyssey (команда Яндекс/Tarantool): многопоточный C, нативно поддерживает prepared statements, показывает наименьшие накладные расходы CPU при высокой конкурентности в бенчмарках. Используйте, когда один нод PgBouncer становится узким местом по CPU (более ~100k QPS через один пулер). Компромисс: меньше сообщество, меньше операторов знакомо с ним.

PgCat (Rust): многопоточный, добавляет маршрутизацию запросов (read-реплики, шардинг) поверх пулинга. Используйте, когда нужен один компонент для пула, балансировки replica и маршрутизации запросов. Молодая кодовая база.

Supavisor (Supabase, Elixir/Erlang): cloud-native, спроектирован для serverless и multi-tenant SaaS, обрабатывает миллионы входящих соединений через легковесные Erlang-процессы. Используйте, когда входящих соединений массово много — serverless cold start, edge-функции, B2B SaaS с тысячами tenant-баз данных.

pgpool-II: традиционный выбор, объединяющий HA, балансировку read-нагрузки и пулинг. Тяжелее и сложнее; используется в legacy-развёртываниях, но менее популярен для greenfield.

ПулерМногопоточностьЛучше всего дляКомпромисс
PgBouncer 1.21+ОднопоточныйOLTP по умолчаниюПотолок CPU при очень высоком QPS
OdysseyМногопоточный>100k QPS на одном нодеМеньше сообщество
PgCatМногопоточный (Rust)Пулинг + маршрутизацияМолодая кодовая база
SupavisorBEAM (Erlang/Elixir)Serverless, edge, миллионы соединенийСложность эксплуатации

Serverless и edge: connection storm

Serverless-платформы (Lambda, Vercel Functions, Cloudflare Workers) при нагрузке холодно запускают сотни и тысячи воркеров. Каждый cold start открывает одно или несколько Postgres-соединений — connection storm. Даже при клиентских пулах каждый cold start открывает новое соединение до прогрева пула.

Паттерны смягчения:

  1. Всегда ставить пулер перед Postgres: RDS Proxy на AWS, Supavisor перед Supabase, PgBouncer на постоянном ноде. Пулер поглощает connection storm; Postgres видит ограниченное число backend’ов.

  2. HTTP-based драйвер для edge: серверлесс-драйвер Neon и Cloudflare Hyperdrive отправляют запросы через stateless HTTP к endpoint пулера — от edge-воркеров до origin нет постоянных соединений. Каждый запрос — один HTTP-запрос; пулер за ним поддерживает реальные Postgres-соединения.

  3. Агрессивные idle-таймауты: serverless-воркеры короткоживущие; простаивающие клиентские соединения от мёртвых воркеров должны быстро освобождаться. Устанавливайте idle_client_timeout на пулере и tcp_keepalives_idle в Postgres для обнаружения мёртвых соединений.

Архитектурный урок: постоянные пулы соединений предполагают долгоживущих клиентов. Serverless нарушает это. Проектируйте для stateless dispatch запросов; делегируйте управление постоянными соединениями расположенному рядом пулеру.

Таксономия режимов отказов

Выбери лучший вариант

Команда на Postgres при 5k QPS выбирает архитектуру пулинга для 2026. Выберите.

Восемь режимов отказов:

(а) Исчерпание пула из-за медленных запросов: отсутствующий индекс делает запрос за 5 с; при 1 000 QPS это 5 000 backend’ов в полёте, превышающих любой пул. Исправление: проиндексировать запрос, пагинировать большие сканы.

(б) Idle-in-transaction опустошает пул: необработанное исключение или внешний API-вызов внутри BEGIN оставляет backend’ы в idle in transaction. Исправление: idle_in_transaction_session_timeout = 60s; code review на отсутствие try/finally; outbox-паттерн для write-then-event.

(в) Внешний API внутри транзакции: BEGIN → платёж Stripe (таймаут = 120 с) → COMMIT. Каждый запрос в полёте удерживает backend до 120 с. Исправление: COMMIT перед вызовом; outbox-паттерн.

(г) NAT/фаервол тихо дропает TCP: backend выглядит простаивающим для PgBouncer, но TCP-сокет мёртв. Новые запросы получают RST или таймаут. Исправление: tcp_keepalives_idle = 60s в postgresql.conf; tcp_keepalives_interval = 10s; client_connection_check_interval = 30s (Postgres 14+).

(д) Коллизии prepared statements (до PgBouncer 1.21): устаревший код с SQL-level PREPARE + transaction mode = “prepared statement does not exist” случайным образом. Исправление: обновить до PgBouncer 1.21+ + max_prepared_statements > 0; или переписать на prepared statements уровня протокола драйвера.

(е) Утечка состояния между клиентами (DISCARD ALL не срабатывает): SET без LOCAL утекает от одного клиента к следующему через пул. Исправление: server_reset_query = DISCARD ALL в pgbouncer.ini; аудит на голые SET.

(ж) Неправильный размер пула для пика vs стабильного состояния: пул рассчитан на стабильную нагрузку; всплески его исчерпывают. Исправление: reserve_pool_size ~25% от pool_size; автомасштабирование на уровне приложения; очередь с деградацией (возвращать 503 с Retry-After до полного исчерпания).

(з) Потолок однопоточного CPU PgBouncer при экстремальном QPS: при очень высоком QPS один нод PgBouncer занимает одно ядро CPU. Исправление: горизонтальное масштабирование PgBouncer за HAProxy/keepalived для VIP-failover; или мигрировать на Odyssey/PgCat.

Почему это работает

Почему архитектура (клиентский пул → PgBouncer → Postgres) многоуровневая, а не просто один пулер? Клиентский пул обрабатывает кэширование соединений внутри одного процесса — бесплатно на горячих путях, без установки сокета, checkout за субмиллисекунды. PgBouncer обрабатывает мультиплексирование между процессами. Убрать клиентский пул означает, что каждый запрос открывает TCP-соединение к PgBouncer — всё ещё быстро (PgBouncer локальный), но не бесплатно. Убрать PgBouncer означает, что клиентские пулы подключаются напрямую к Postgres — нормально для маленьких приложений, фатально при масштабе, когда число воркеров превышает max_connections.

Критерии выбора пулера
PgBouncer: память на клиентское соединение
~2 КБ
PgBouncer: потолок однопоточного QPS
~100k QPS
Преимущество Odyssey над PgBouncer
Многопоточный, меньше CPU при высокой конкурентности
Целевое число входящих соединений Supavisor
Миллионы (Erlang/Elixir)
Паттерн HA PgBouncer
Несколько инстансов за HAProxy
Serverless-паттерн
HTTP-based драйвер + расположенный рядом пулер
Рекомендованный tcp_keepalives_idle
60 с
Викторина

Команда строит multi-tenant B2B SaaS на Postgres, где у каждого tenant своя база данных. 10 000 tenant'ов × 50 параллельных пользователей каждый. Какая архитектура пулера наиболее подходит?

Викторина

Serverless-функции холодно запускаются под нагрузкой и каждая открывает Postgres-соединение. Что происходит без расположенного рядом пулера?

Вспомните перед уходом
  1. 01
    Сравните PgBouncer и Odyssey — когда вы выберете Odyssey вместо PgBouncer?
  2. 02
    Опишите проблему serverless connection storm и правильный архитектурный ответ.
  3. 03
    Назовите и опишите четыре режима отказа из таксономии пулинга и диагностический сигнал для каждого.
Итог

Ландшафт пулеров в 2026: PgBouncer 1.21+ — выбор по умолчанию для большинства OLTP-стеков — battle-tested, минималистичный и теперь полностью совместимый с prepared statements в transaction mode. Odyssey и PgCat добавляют многопоточную пропускную способность и маршрутизацию запросов для команд, переросших однопоточный потолок PgBouncer. Supavisor и RDS Proxy решают проблему serverless и multi-tenant масштаба, где число входящих соединений достигает миллионов. Serverless cold start — отдельная проблема: архитектурное решение — расположенный рядом пулер, поглощающий всплеск, плюс HTTP-based драйвер для истинного stateless edge. Восемь режимов отказов (исчерпание пула из-за медленных запросов, idle-in-transaction, внешний API внутри транзакции, NAT TCP drop, коллизия prepared statement, утечка состояния, неправильный размер на пик, потолок CPU PgBouncer) — каждый имеет явный сигнал и систематическое исправление. Наблюдаемость — cl_waiting, возраст idle-in-transaction, задержка checkout пула — превращает «инцидент в 3 ночи» в «алерт перед деплоем».

Связанные уроки
встречается в258
Продолжить восхождение ↑Connection pooling: тест с выбором ответа
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources5
expand
  1. 01
  2. 02
  3. 03
  4. 04
  5. 05

Trademarks belong to their respective owners. Editorial reference only.