Erro 'Too many connections' no PostgreSQL durante pico de faturamento — guia prático de diagnóstico e correção

Por · Publicado em · Atualizado em · 8 min de leitura

Painel frontal de servidores em rack com baias e uma mão ajustando um componente
Racks de servidores e armazenamento — contexto adequado para incidentes e diagnóstico de banco de dados Foto: ColossusCloud / Pixabay

Erro 'Too many connections' no PostgreSQL durante pico de faturamento: como diagnosticar e resolver. O colapso geralmente combina storms de conexão, transações longas e falta de pooling. Aqui você mede a situação em minutos, aplica contenção segura, corrige causas raiz (pool, timeouts, SQL) e prepara o banco e a aplicação para o próximo fechamento sem sustos.

O que o erro significa e por que explode no pico

O PostgreSQL limita sessões simultâneas por max_connections. Ao atingir o teto, novas conexões falham e a aplicação erra. Em picos de faturamento, tráfego, jobs e relatórios coincidem e multiplicam sessões. Sem pool, cada requisição vira uma conexão. Transações abertas prendem slots e travam filas.

Se suspeitar de jobs concorrendo com o checkout, revise sua janela de execução. Este guia sobre bloqueios e cron detalha impactos e correções: auditar e otimizar jobs cron.

  • Tempestade de conexões: múltiplas instâncias/threads abrindo sessões ao mesmo tempo.
  • Transações longas e bloqueios: filas crescem, conexões ficam ativas ou presas.
  • Jobs e relatórios simultâneos competindo com tráfego de checkout.
  • Health checks mal configurados saturando o banco.

Passo 1 — Medir agora: quantas conexões e de onde vêm

Mapeie estados e origens das sessões. Descubra quem consome slots: aplicação, endereço IP, usuário. Isso separa causa de sintoma e orienta as próximas ações. Rode as consultas abaixo no banco afetado.

-- Sessões por estado
SELECT state, count(*)
FROM pg_stat_activity
WHERE datname = current_database()
GROUP BY 1 ORDER BY 2 DESC;

-- Origem por application_name
SELECT coalesce(application_name, 'unknown') AS app, count(*)
FROM pg_stat_activity
WHERE datname = current_database()
GROUP BY 1 ORDER BY 2 DESC;

-- Clientes que mais abrem conexões
SELECT client_addr, count(*)
FROM pg_stat_activity
WHERE datname = current_database()
GROUP BY 1 ORDER BY 2 DESC;

-- 'idle in transaction' retém slots
SELECT count(*) AS idle_in_tx
FROM pg_stat_activity
WHERE state = 'idle in transaction';

Passo 2 — Pool de conexões: o amortecedor que falta

Sem pooling, cada requisição abre uma sessão no PostgreSQL. Um pool limita e reutiliza conexões, protegendo o banco de storms. Verifique o pool do app e, se usar PgBouncer, revise limites e modo de pooling. Em picos, o pooling por transação costuma reduzir pressão.

  • Prefira pooling por transação para apps web de alta concorrência.
  • Dimensione pools por serviço, evitando somar máximos teóricos de todos.
  • Aplique timeouts para sessões ociosas e quedas de rede.
; Exemplo de PgBouncer (ilustrativo)
[databases]
mydb = host=127.0.0.1 port=5432 dbname=mydb

[pgbouncer]
max_client_conn = 2000
default_pool_size = 50
reserve_pool_size = 20
pool_mode = transaction
server_idle_timeout = 30
query_timeout = 30
idle_transaction_timeout = 30

Passo 3 — App sob controle: evite tempestade de conexões

Mesmo com pool, a aplicação pode esgotar sessões ao iniciar múltiplos workers ou em retries agressivos. Ajuste padrões de conexão e backoff. Reduza concorrência durante o pico se necessário. Health checks devem ser leves e não conectar no banco a cada probe.

  • Inicialize o pool uma vez por processo; não abra/feche a cada requisição.
  • Implemente retries com backoff exponencial e jitter, com limites claros.
  • Limite workers simultâneos em horários de pico.
  • Tempo de vida de conexão: reciclar periodicamente, sem sincronizar reciclagem.

Passo 4 — Transações longas e SQL pesadas drenam slots

Transações abertas seguram conexões e bloqueios. Relatórios sem índice e N+1 ampliam o tempo preso ao banco. Monitore as consultas mais antigas e foque nas que afetam tabelas quentes. Para acelerar rotas de faturamento, veja este guia de tuning: otimização de consultas PostgreSQL para ERP.

  • Encerre sessões travadas e refine índices em rotas de faturamento.
  • Evite 'idle in transaction': sempre COMMIT/ROLLBACK.
  • Revise jobs de horário comercial e reprograme relatórios pesados.
-- Top transações antigas e o que aguardam
SELECT pid,
       now() - xact_start AS xact_age,
       state,
       wait_event_type,
       wait_event,
       left(query, 200) AS query
FROM pg_stat_activity
WHERE datname = current_database()
  AND xact_start IS NOT NULL
ORDER BY xact_age DESC
LIMIT 15;

Passo 5 — Ajustar max_connections com segurança (sem adivinhação)

Aumentar max_connections sem planejamento causa OOM e quedas piores. Dimensione memória e prefira pools. Mantenha o banco com número estável de sessões e absorva picos no pool do lado de fora. Use timeouts para evitar conexões eternas.

Parâmetro Impacto Regra prática
max_connections Limite de sessões no PostgreSQL Mantenha moderado e estável; use pool para atender milhares de clientes.
shared_buffers Cache de páginas do banco Dimensione de acordo com a RAM disponível, evitando competir com SO e cache do filesystem.
work_mem Memória por operação (sort/hash) Evite valores altos globais; ajuste por sessão/consulta quando necessário.
statement_timeout / idle_in_transaction_session_timeout Evita sessões presas Defina limites realistas para evitar conexões eternas e filas.
Pool (app/PgBouncer) Amortece picos Some pools reais e verifique piores cenários de concorrência.
-- Checar parâmetros atuais
SHOW max_connections;
SHOW shared_buffers;
SHOW work_mem;
SHOW statement_timeout;
SHOW idle_in_transaction_session_timeout;

Passo 6 — Contenção imediata durante o incidente (com cautela)

Estas ações aliviam o colapso enquanto a causa raiz é tratada. Aplicar em produção é arriscado: teste primeiro e limite o escopo ao database/role/aplicação afetada. Foque no tráfego não essencial e em sessões que só ocupam slots.

  • Reduza tráfego não essencial (relatórios, integrações menos críticas).
  • Cancele consultas lentas; termine sessões zumbis.
  • Aplique timeouts temporários para evitar novas filas infinitas.
-- Definir timeouts no DB afetado (temporário)
ALTER DATABASE mydb SET statement_timeout = '30s';
ALTER DATABASE mydb SET idle_in_transaction_session_timeout = '30s';

-- Encerrar sessões ociosas de uma aplicação específica
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = 'mydb'
  AND application_name = 'checkout'
  AND state IN ('idle','idle in transaction');

Passo 7 — Prevenção para o próximo pico

Consolide aprendizados e crie proteções. Monitore conexões, latência e bloqueios. Teste carga do caminho de faturamento. Isolar relatórios pesados e adotar telemetria e logs estruturados ajuda a antecipar degradações e correlacionar causas.

Perguntas frequentes

Aumentar o max_connections resolve o erro de vez?

Nem sempre. Pode agravar consumo de memória e latência. O caminho sustentável é manter um número moderado de sessões e usar pool de conexões para absorver picos. Corrija transações longas, consultas lentas e storms na aplicação.

PgBouncer em modo sessão ou transação para apps web?

Para apps web de alta concorrência, o modo por transação costuma funcionar melhor, pois libera conexões rapidamente. O modo por sessão mantém conexões presas durante toda a sessão do cliente, elevando o uso em picos.

Como identificar qual serviço está esgotando conexões?

Use pg_stat_activity para agrupar por application_name, usuário e client_addr. Habilite logs com identificação de aplicação e correlação de requisições. Isso permite mapear rotas e jobs que mais consomem sessões nos horários críticos.

Read replicas ajudam a reduzir ‘Too many connections’?

Replicas aliviam consultas de leitura, mas cada réplica também tem limite de conexões. Sem pool e sem otimizar transações, o problema pode apenas se deslocar. Direcione leituras pesadas para réplicas com pooling adequado.

Por que o erro só aparece no fechamento do mês?

Nesses horários, há picos simultâneos: faturamento, conciliações, relatórios, integrações e aumento de tráfego. Se todos competem e o banco não tem pool, índices e timeouts adequados, o limite de conexões é atingido rapidamente.

Precisa estabilizar o PostgreSQL antes do próximo pico?

Se o erro ‘Too many connections’ apareceu no faturamento, podemos revisar conexões, pool, consultas críticas e timeouts para reduzir o risco de nova queda.

Falar sobre o diagnóstico

Veja também