Matemática de Conexões
O max_connections do PostgreSQL é um teto rígido. Instâncias do aplicativo × tamanho do pool devem ficar abaixo dele, com margem para administração, replicação e autovacuum. Use PgBouncer (ou o pooler do provedor) para que centenas de threads do aplicativo multiplexem em dezenas de backends reais.
Receita
budget_seguro_backend = max_connections - reservado
reservado ≈ 10 (superuser) + slots_de_replicação + monitoramento + margem_admin (15-30)
conexoes_servidor_app = instancias_app × pool_max_por_instancia
conexoes_servidor_pgbouncer = pool_size (para o Postgres)
Regra: pgbouncer_pool_size ≤ budget_seguro_backend × 0.8
Regra: soma(todos os server_conn dos pools) ≤ budget_seguro_backend
SHOW max_connections;
SELECT count(*) FROM pg_stat_activity WHERE backend_type = 'client backend';Quando usar isso:
- Erros de produção "too many clients already"
- Aumento da contagem de pods no Kubernetes HPA
- Dimensionamento de um novo grupo de parâmetros de instância RDS
Exemplo de Trabalho
40 pods de API, cada um com pool máximo de 20, modo de transação PgBouncer, max_connections do RDS = 200.
Lado do aplicativo (potencial): 40 × 20 = 800 conexões de cliente para o PgBouncer (OK)
pgbouncer default_pool_size = 40 conexões de servidor para o Postgres
Reservado: 20 admin/replicação/monitoramento
Usado: 40 + 20 = 60 ≤ 200 × 0.8 = 160 ✓
# Trecho do pgbouncer.ini
[databases]
orders = host=primary.internal port=5432 dbname=orders
[pgbouncer]
pool_mode = transaction
default_pool_size = 40
max_client_conn = 1000
reserve_pool_size = 5-- Verificar uso ao vivo
SELECT state, count(*) FROM pg_stat_activity
WHERE backend_type = 'client backend'
GROUP BY 1;
SELECT setting::int FROM pg_settings WHERE name = 'max_connections';O que isso demonstra:
- O aplicativo pode abrir 800 conexões lógicas enquanto o Postgres vê ~40 backends ativos
- Reserva de margem para sessões não-app
max_client_connno PgBouncer é separado domax_connectionsdo Postgres
Mergulho Profundo
Sem Pooler (anti-padrão em escala)
50 pods × 20 conexões = 1000 > max_connections 200 → falha
Impacto dos Modos de Pool
| Modo | Backends de servidor | Observação |
|---|---|---|
| Sessão | Até a contagem de clientes | Pouca economia |
| Transação | Multiplexado por transação | Sem persistência de GUC de sessão |
| Declaração | Raro | Quebra muitos ORMs |
Pools por Função
# Pools separados para api vs migrator (migrator acessa o pooler diretamente)
orders_api = host=primary dbname=orders pool_size=35O CI do Migrator conecta diretamente com pool_size=1 sessão para DDL.
Armadilhas
- Pool padrão do ORM = num_cpus × 5 por pod - explode com HPA. Correção: limitar o pool (geralmente 5-20 por pod).
- PgBouncer pool_size = max_connections - sem margem administrativa. Correção: no máximo 60-70% do orçamento.
- Múltiplos serviços compartilhando o mesmo pool DSN - matemática agregada necessária. Correção: mapear a contribuição de pool por serviço.
max_connectionsdo RDS escala com RAM, mas não linearmente com pods do aplicativo - sempre use pool. Correção: grupo de parâmetros + sidecar PgBouncer.- Conexões ociosas ainda consomem memória - ~5-10 MB por backend. Correção: pooling de transação, diminuir o tempo limite de inatividade.
- Funções Serverless × alta concorrência - pooler Neon/Supabase necessário. Correção: URL do pooler, não direto.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
| PgBouncer | Frotas OLTP padrão | Precisa de tabelas temporárias com escopo de sessão em todos os lugares |
| RDS Proxy | AWS sem operar pooler | Não-AWS |
| Supavisor / Neon pooler | Serverless hospedado | Auto-hospedado, a menos que você adote o proxy deles |
| pgpool-II | Implantações legadas | Greenfield (prefira PgBouncer) |
FAQs
Pool ideal por pod?
5-20 para API típica; teste de carga; menor se as consultas forem rápidas e o HPA for amplo.
Fórmula max_connections RDS?
Documentação do provedor: LEAST({DBInstanceClassMemory/9531392}, 5000) estilo - verifique a documentação da AWS para a classe.
Prepared statements com pool de transação?
Use a configuração do ORM para desabilitar o prepare do lado do servidor ou use o pool de sessão para esse serviço.
Monitorar espera do pool?
PgBouncer SHOW POOLS cl_waiting; alerte quando > 0 sustentado.
Conexões de réplica de leitura?
Pool separado por endpoint; réplicas têm seu próprio max_connections.
Slots de worker de replicação lógica?
Contar no orçamento reservado; slots usam conexões walsender.
Tempestade de conexões na implantação?
Alternar rollout de pods; aquecimento do pool; evitar "thundering herd" na reinicialização do DB.
pg_stat_activity max?
Mostra backends de servidor; compare com métricas de conexão de servidor PgBouncer para uma imagem completa.
Quando aumentar max_connections?
Após otimizar o pooler e ainda assim haver esgotamento de backend - prefira escalar CPU/RAM com ele.
Documentar matemática onde?
Tabela do runbook do serviço: pods, pool, tamanho do pooler, max_connections, data de atualização.
Relacionado
- Modos do PgBouncer - semântica do pool
- Noções Básicas de Capacidade - contexto de RAM e CPU
- Proxies de Conexão - roteamento HA
- Melhores Práticas do PostgreSQL Gerenciado - pooling na nuvem
- Melhores Práticas de Planejamento de Capacidade - revisão trimestral
Versões da Stack: Esta página foi escrita para PostgreSQL 18.4 (estável 18, manutenção 17), pgvector 0.8+, PgBouncer 1.x, Patroni 3.x e PostGIS 3.5+.