Erro "FATAL: remaining connection slots are reserved" no PostgreSQL durante pico de faturamento
Por Kevin Marcondes · Publicado em · 8 min de leitura
O erro "FATAL: remaining connection slots are reserved" no PostgreSQL durante pico de faturamento indica que quase todos os slots de conexão acabaram e os restantes estão reservados para o superusuário. O efeito é bloqueio de logins da aplicação. Veja como diagnosticar em minutos, liberar conexões com segurança e aplicar correções rápidas que estabilizam o ambiente.
O que esse erro significa e por que aparece
O PostgreSQL reserva alguns slots de conexão para o superusuário. Quando os demais se esgotam, usuários comuns recebem o erro. Isso ocorre em picos, tempestades de conexões e sessões presas em "idle in transaction".
Não é só falta de max_connections. Ausência de pooler, reinícios simultâneos de workers web e jobs paralelos agravam. Se o problema for genérico de lotação, veja também o guia de "Too many connections". Para carga contínua pesada, veja o serviço de hardening e tuning de PostgreSQL.
- Conexões normais esgotadas; sobram apenas slots reservados ao superusuário.
- Aplicações sem pool ampliam picos ao abrir muitas conexões curtas.
- Sessões "idle in transaction" mantêm slots ocupados por muito tempo.
O que conferir primeiro durante o pico?
Você precisa de visibilidade imediata: quantos slots existem, quem está ocupando e em que estado. Priorize acesso administrativo e reduza a dependência de rede conectando via socket local, se disponível.
Use consultas rápidas para limites, agrupamento por estado/usuário/aplicação e top sessões ativas ou presas. Esses dados guiam as primeiras ações com menor risco.
-- Limites atuais
SELECT name, setting FROM pg_settings
WHERE name IN ('max_connections','superuser_reserved_connections');
-- Quem está ocupando mais conexões agora?
SELECT state, application_name, usename, client_addr, count(*) AS qtd
FROM pg_stat_activity
GROUP BY 1,2,3,4
ORDER BY qtd DESC;
-- Top sessões ativas ou presas em transação
SELECT pid, state, xact_start, wait_event_type, wait_event, application_name, query
FROM pg_stat_activity
WHERE state IN ('active','idle in transaction')
ORDER BY xact_start NULLS LAST
LIMIT 20;
Como liberar conexões com segurança sem reiniciar?
Cancele consultas longas antes de encerrar sessões. Encerrar força rollback da transação; escolha alvos de baixo risco e comunique o time de negócio.
Reduza a taxa de novas conexões na aplicação: ative ou ajuste o pool do driver, limite processos web temporariamente e suspenda tarefas de fundo não críticas até estabilizar.
- Cancelar consultas antes de finalizar sessões reduz impacto.
- Atue primeiro em sessões "idle in transaction" muito antigas.
- Diminua novas conexões na camada de aplicação durante a normalização.
-- 1) Cancelar consultas em execução (encerra com graça)
SELECT pg_cancel_backend(pid)
FROM pg_stat_activity
WHERE state = 'active' AND now() - xact_start > interval '30 seconds';
-- 2) Encerrar sessões problemáticas (gera rollback)
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE state = 'idle in transaction' AND now() - xact_start > interval '2 minutes';
Quais ajustes rápidos no PostgreSQL ajudam no pico?
Alguns parâmetros aliviam a saturação, mas mudanças em max_connections e superuser_reserved_connections exigem reinício. Planeje memória e testes antes de alterar.
O caminho sustentável é manter um limite razoável de conexões no PostgreSQL e colocar um pooler à frente. Isso reduz churn e estabiliza a latência sob pico.
| Componente | Parâmetro/Opção | O que faz | Risco/Observação |
|---|---|---|---|
| PostgreSQL | max_connections | Aumenta o número de conexões simultâneas aceitas. | Requer restart; mais conexões elevam uso de memória e context-switch. |
| PostgreSQL | superuser_reserved_connections | Reserva slots para superusuário acessar quando o banco satura. | Requer restart; não zere. Mantenha poucos, porém suficientes. |
| PgBouncer | pool_mode = transaction | Reutiliza conexões por transação, reduzindo saturação. | Quebra recursos de sessão (tabelas temporárias, prepared statements de sessão, LISTEN/NOTIFY). |
| PgBouncer | reserve_pool_size | Mantém conexões de servidor sobressalentes para picos. | Ajuste junto com max_client_conn e default_pool_size. |
| SO (Linux) | net.core.somaxconn | Aumenta a fila de aceitação de conexões (accept queue). | Ajuda sob tempestade; não resolve estouro de max_connections. |
| SO (Linux) | net.ipv4.tcp_max_syn_backlog | Aumenta fila de SYN pendentes no handshake. | Reduz perdas em rajadas; não substitui pooler. |
| Aplicação | Pool no driver/ORM | Reúso de conexões e limitação de concorrência. | Evite abrir/fechar por requisição; prefira conexões persistentes. |
# Exemplos no postgresql.conf (requer restart)
max_connections = 300
superuser_reserved_connections = 3
Pool de conexões: quando usar PgBouncer e quais modos
Use PgBouncer quando a aplicação abre muitas conexões curtas ou vários processos sobem em paralelo. O modo transaction pooling atende a maioria dos cenários web por reduzir sessões no servidor.
Evite transaction pooling se precisa de estado de sessão, como tabelas temporárias, prepared statements por sessão ou LISTEN/NOTIFY. Nesse caso, use session pooling ou adapte a aplicação.
- Transaction pooling: ideal para HTTP com consultas curtas e alta taxa de requisições.
- Session pooling: preserva sessão, porém escala menos.
- Ajuste max_client_conn, default_pool_size e reserve_pool_size conforme a carga.
# Exemplo mínimo de PgBouncer
[databases]
mydb = host=127.0.0.1 port=5432 dbname=mydb
[pgbouncer]
listen_port = 6432
pool_mode = transaction
max_client_conn = 1000
default_pool_size = 50
min_pool_size = 5
reserve_pool_size = 20
server_reset_query = DISCARD ALL
Backlog e kernel para segurar tempestades de conexões
Rajadas de novas conexões podem enfileirar o accept do sistema. Ajustar somaxconn e tcp_max_syn_backlog reduz recusas sob pico, sem criar mais slots no PostgreSQL.
A correção estrutural continua sendo limitar concorrência com pooler e reuso no app. O backlog é complementar e deve ser validado em staging. Mudanças de sysctl afetam todo o sistema.
- Persistir ajustes em /etc/sysctl.d/ e versionar o arquivo.
- Testar em ambiente de staging antes de produção.
- Monitorar novas conexões por segundo e falhas de handshake.
# Ajustes temporários (teste controlado)
sudo sysctl -w net.core.somaxconn=4096
sudo sysctl -w net.ipv4.tcp_max_syn_backlog=8192
# Persistir em /etc/sysctl.d/99-tuning.conf
# net.core.somaxconn=4096
# net.ipv4.tcp_max_syn_backlog=8192
# sudo sysctl --system
Como evitar que volte a acontecer?
Defina limites claros e crie visibilidade contínua. Métricas e alertas sobre conexões, estados de sessão e tempo de transação evitam repetição durante faturamento.
Monte um runbook com consultas de diagnóstico e critérios para cancelar ou encerrar sessões. Treine a equipe e valide o plano. Para disciplina transacional, veja o guia de migrations e rollbacks em PostgreSQL e implemente alertas com base em runbooks, como no serviço de observabilidade e runbooks.
- Colete métricas: conexões ativas, novas conexões por segundo e "idle in transaction".
- Alerta quando "idle in transaction" ultrapassar um limiar definido.
- Simule pico com carga sintética para validar configurações.
Perguntas frequentes
Aumentar max_connections resolve o erro definitivamente?
Não. Aumentar max_connections alivia no curto prazo, mas pode piorar latência e consumo de memória. O caminho sustentável é usar pool de conexões (PgBouncer ou no driver) e corrigir sessões longas, combinando com ajuste moderado do limite.
Posso mudar superuser_reserved_connections sem reiniciar o PostgreSQL?
Não. superuser_reserved_connections, assim como max_connections, requer reinício do servidor. Planeje janela e valide memória antes. Para alívio imediato, cancele/encerre sessões e reduza novas conexões via pooler e aplicação.
Como identificar rapidamente quem mais consome conexões no momento?
Agrupe pg_stat_activity por state, application_name, usename e client_addr. As contagens por grupo evidenciam quais serviços, usuários ou hosts saturam. Filtre por "idle in transaction" e duração da transação para priorizar a ação com menor risco.
PgBouncer em transaction pooling quebra quais recursos?
Transaction pooling não preserva estado de sessão entre comandos. Recursos como tabelas temporárias, prepared statements por sessão, SET LOCAL e LISTEN/NOTIFY podem falhar. Se precisar deles, use session pooling ou adapte a aplicação para transações curtas e sem estado.
É melhor matar sessões ou apenas cancelar consultas longas?
Comece com pg_cancel_backend, que tenta encerrar a consulta sem derrubar a sessão. Se não resolver, use pg_terminate_backend em sessões de baixo risco, ciente do rollback. Priorize sessões "idle in transaction" antigas e queries claramente travadas.
Backlog do kernel aumenta a capacidade de conexões do PostgreSQL?
Não. Backlog (somaxconn, tcp_max_syn_backlog) apenas melhora a fila de aceitação do sistema sob rajadas de novas conexões. A capacidade de sessões simultâneas depende de max_connections e da eficiência do pool de conexões.
Precisa destravar o banco sem arriscar dados?
Se o erro surgiu no pico de faturamento, um diagnóstico rápido e ajustes de pool, limites e backlog podem estabilizar o ambiente. Vamos conversar sobre um plano seguro.
Falar sobre diagnóstico rápidoVeja também
- 502 Bad Gateway intermitente em Docker Compose com Nginx e PHP‑FPM: como diagnosticar e corrigir timeouts e excesso de conexões
- Como diagnosticar e capturar pacotes para intermitência de rede entre containers Docker no Debian
- Como reduzir tempo de build e evitar artefatos duplicados em CI para monólitos PHP grandes
- Como detectar e corrigir inconsistências de SKU duplicados entre WooCommerce e ERP sem perder pedidos