PRODPlataforma BaaS europeia soberanaAbra o painel →

Desempenho · 9 minutos de leitura

Postgres max_connections sem pooler

Affane Daylami · Fondateur · 6 de junho de 2026

Voltar ao blog

Sem pooling na frente do seu servidor, max_connections deve cobrir todas as conexões abertas do cliente ao mesmo tempo, e não o número de solicitações que o Postgres pode processar eficientemente em paralelo. Confundir esses dois números é a causa mais comum de max_connections configurados incorretamente: muito baixo para absorver a carga ou muito alto para a memória realmente disponível.

Este texto em inglês foi gerado automaticamente a partir do original em francês e ainda não foi revisado.
Esta página foi traduzida automaticamente. A versão em inglês é oficial.

Este artigo fornece a fórmula publicada pelo wiki do PostgreSQL para calcular a simultaneidade ideal do seu hardware (a fórmula de dimensionamento do pool de conexões mais citada no ecossistema), explica por que cada conexão custa mais do que um thread de aplicativo e detalha o procedimento para definir max_connections sem adivinhar. Nossa metodologia de benchmark documenta o protocolo de medição usado para quaisquer declarações de desempenho neste blog.

O essencial

  • Sem pooling, max_connections deve cobrir todas as conexões de clientes simultâneas, não apenas aquelas que o Postgres pode processar eficientemente em paralelo.
  • Fórmula de referência do wiki PostgreSQL: simultaneidade ativa ideal = (núcleos físicos × 2) + discos eficientes. Um ponto de partida a ser validado por medição, não um limite rígido.
  • max_connections é um parâmetro de contexto postmaster: alterá-lo requer uma reinicialização completa do servidor, não uma simples recarga.
  • Cada conexão do Postgres é um processo de sistema separado, não um thread leve: é isso que torna a sobrecarga real assim que o número de conexões aumenta.
  • Verificado no código: em seus clusters Postgres dedicados, o Aurabase varia max_connections de 50 (nível gratuito) a 400 (nível empresarial) dependendo do tamanho do cluster.
#
Diagnóstico

Por que uma conexão Postgres custa mais que um thread de aplicativo

O Postgres não usa um pool de threads leve para suas conexões. Cada conexão do cliente aciona um processo de sistema completo.

O processo postmaster cria um novo (“fork”) para cada tentativa de conexão, dedicado a esta única sessão até que ela seja fechada. A documentação oficial do projeto descreve precisamente esse mecanismo em seu capítulo sobre fundamentos arquitetônicos (postgresql.org/docs/current/connect-estab.html, seção “Connection Semantics”, acessado em 24 de agosto de 2026).

Esta escolha tem uma vantagem real: uma falha em uma conexão não afeta as outras, ficando cada processo isolado do resto do servidor. Também tem um custo direto: cada conexão adicional adiciona um processo inteiro do sistema operacional para agendar, com seu próprio espaço de memória e sua própria sobrecarga de troca de contexto para o kernel.

O que isso muda na prática

Uma aplicação que abre 500 conexões diretas ao Postgres sem pooling força o servidor a gerenciar 500 processos simultâneos do sistema, mesmo que a grande maioria deles permaneça ociosa entre duas solicitações.

#
Custo de memória

O que uma conexão realmente consome: memória compartilhada e work_mem

Dois mecanismos distintos afetam a memória e confundi-los quase sempre leva a um diagnóstico errado.

O primeiro está consertado. Na inicialização, o Postgres reserva estruturas de memória compartilhada (bloqueios, tabela de processos) dimensionadas no valor de max_connections, independentemente de essas conexões serem abertas posteriormente ou não. A documentação oficial para a configuração aponta explicitamente: aumentá-la pode exigir mais memória compartilhada do sistema do que a configuração padrão do seu sistema operacional permite (postgresql.org/docs/current/runtime-config-connection.html, acessado em 24 de agosto de 2026).

A segunda é variável e muito mais perigosa em escala: work_mem não é alocado uma vez por conexão, mas uma vez por operação de classificação ou hash no plano de consulta. A documentação oficial é explícita neste ponto: uma consulta complexa pode lançar várias dessas operações em paralelo, e várias sessões podem fazer o mesmo simultaneamente, de modo que a memória realmente utilizada pode valer várias vezes work_mem (postgresql.org/docs/current/runtime-config-resource.html, acessado em 24 de agosto de 2026).

O pior caso real para lembrar

Não é apenas max_connections × work_mem que ameaça a memória de um servidor. É max_connections × work_mem × número de operações simultâneas por consulta. É este produto que explica um servidor que troca, ou que fica sem memória após um aumento em max_connections considerado inócuo.

#
Fórmula

A fórmula de dimensionamento do wiki PostgreSQL

O wiki oficial do projeto PostgreSQL documenta uma fórmula de referência para calcular quantas conexões ativas seu hardware pode processar eficientemente em paralelo, não quantas conexões abertas no total (wiki.postgresql.org/wiki/Number_Of_Database_Connections, acessado em 24 de agosto de 2026).

A fórmula

simultaneidade ativa ideal = (núcleos físicos × 2) + discos eficientes. O número de núcleos exclui hyperthreading. O número de discos efetivos permanece próximo de 1 no armazenamento SSD moderno, onde a noção de um disco físico separado (“spindle”) perde muito do seu significado original.

Em um servidor com 8 núcleos físicos e armazenamento SSD, a fórmula fornece (8 × 2) + 1 = 17 conexões ativas antes que o rendimento comece a diminuir. Esse número costuma ser surpreendente: parece minúsculo comparado às centenas de conexões que um aplicativo abre na prática. Este é precisamente o assunto do parágrafo seguinte.

O número calculado pela fórmula mede a simultaneidade que a CPU e o disco podem absorver, e não o número de conexões de cliente que seu aplicativo precisa abrir. Uma frota de 20 processos de aplicação, cada um com seu próprio conjunto de 10 conexões, abre 200 conexões simultâneas com o Postgres, mesmo que apenas 17 delas estejam funcionando ativamente em um determinado momento. Sem um pooler, max_connections deve cobrir 200, não 17. É essa lacuna que leva a maioria das arquiteturas a adicionar um pooler no modo de transação, mesmo que isso signifique escolher qual deles (veja nossa comparação PgBouncer, Supavisor e PgCat).

#
Procedimento

Como alterar max_connections (e por que é necessária uma reinicialização)

max_connections não é hot swap. Este é um parâmetro de contexto postmaster: o Postgres o lê uma vez, na inicialização, para dimensionar sua memória compartilhada. Uma recarga de configuração (pg_reload_conf() ou SIGHUP) não é suficiente, é necessário reiniciar o servidor.

Primeiro verifique o valor atual e seu contexto, para confirmar se será necessário reiniciar:

psqlsql
SHOW max_connections;

SELECT name, setting, context
FROM pg_settings
WHERE name = 'max_connections';

-- context='postmaster' confirma que uma reinicialização é necessária

Em seguida, aplique o novo valor e reinicie:

psqlsql
ALTER SYSTEM SET max_connections = '300';

-- Escrito em postgresql.auto.conf.
-- Nenhum efeito até que o Postgres seja reiniciado.
terminalbash
# Com sistema
sudo systemctl restart postgresql

# Sem systemd, diretamente com pg_ctl
pg_ctl restart -D $PGDATA -m fast
Uma margem que muitos esquecem

max_connections inclui por padrão superuser_reserved_connections (3 por padrão): essas conexões são reservadas para um superusuário em caso de saturação, nunca ficam disponíveis para sua aplicação, mesmo que o contador global ainda não tenha sido atingido.

#
Verificado no código

Como a Aurabase orçamenta max_connections em seus clusters Postgres

Dimensionar max_connections não é apenas um exercício teórico. Aqui está como a Aurabase faz o orçamento em seus clusters Postgres gerenciados:

100
PADRÃO DE POSTGRES
max_connections antes de qualquer ajuste
50→400
ROLAMENTOS AURABASE DEDICADOS
gratuito para empresas, por cluster CNPG
3
SUPERUSUÁRIO RESERVADO
superuser_reserved_connections, padrão do Postgres

Clusters dedicados: um cluster Postgres por projeto

Neste nível (veja nossa comparação dedicada vs base compartilhada), cada projeto recebe seu próprio cluster CloudNativePG e seu próprio orçamento max_connections, dimensionado com o tamanho da instância:

grátis (dedicado)max_conexões 501 instância · 500 milhões de vCPU · 512 Mi
profissional (padrão)max_conexões 2002 instâncias · 1 vCPU · 2Gi
equipemax_conexões 3003 instâncias · 2 vCPU · 3Gi
negóciomax_conexões 4003 instâncias · 2 vCPU · 4Gi

Clusters compartilhados: vários projetos de uma organização, um orçamento compartilhado

Neste segundo caminho, todos os projetos da mesma organização se conectam através de um pooler CNPG (PgBouncer, modo transaction) na frente de um primário compartilhado:

grátismax_conexões 50max_client_conn 100max_user_connections 20
profissionalmax_conexões 100max_client_conn 200max_user_connections 60
equipemax_conexões 200max_client_conn 400max_user_connections 150

Todos os projetos de uma organização se conectam por meio de uma função de aplicativo compartilhada. max_user_connections portanto, por si só, limita o total de conexões de servidor que esta função pode abrir em todo o cluster: esta é a verdadeira proteção global do cluster, não max_client_conn, que limita apenas as conexões do cliente ao próprio pooler.

No entanto, esse pooler atende apenas ao tráfego de aplicativos SDK. O PostgREST, por sua vez, permanece diretamente conectado ao primário (serviço-rw): o pooling no modo de transação quebraria seu mecanismo de recarga de esquema, que escuta um canal LISTEN dedicado chamado pgrst. Suas próprias conexões (2 por réplica no nível compartilhado, 10 por réplica no nível dedicado) contam, portanto, diretamente no orçamento max_connections do primário, fora de qualquer pooler, exatamente o tipo de conexão “esquecida” que a etapa 1 do procedimento abaixo deve incluir.

Números atualmente em calibração, assumidos como tal

O código documenta explicitamente estes orçamentos partilhados como valores iniciais a serem calibrados em condições reais, medindo pg_stat_activity sob carga, e não como valores fixos de um benchmark publicado. Esta é a mesma disciplina descrita em nossa metodologia de benchmark : medir antes de ajustar, não adivinhar e depois esperar. Esses clusters são executados no PostgreSQL 16, uma escolha documentada em nossa comparação Postgres 16 vs 17 vs 18.

#
Método

O procedimento de 5 etapas para dimensionar max_connections sem pooling

Este procedimento não depende de nenhuma ferramenta específica: aplica-se a qualquer servidor Postgres, gerenciado ou auto-hospedado.

  1. Conte suas conexões reais de cliente. Número de processos de aplicação multiplicado pelo tamanho do seu pool interno, além de ferramentas de administração, replicação e monitoramento. É esse número, e não a fórmula, que define o limite mínimo de max_connections.
  2. Calcule a simultaneidade ideal do seu hardware com a fórmula do wiki do PostgreSQL: (núcleos físicos × 2) + discos eficientes. Este número indica quantas dessas conexões podem realmente funcionar em paralelo sem degradar o rendimento.
  3. Defina max_connections acima da necessidade real da etapa 1, com margem para superuser_reserved_connections e para quaisquer ferramentas administrativas que abram suas próprias conexões fora do aplicativo.
  4. Aplique a alteração com ALTER SYSTEM SET e reinicie o servidor. Este é um parâmetro do postmaster: uma simples recarga não é suficiente, conforme detalhado acima.
  5. Monitore pg_stat_activity ao longo do tempo. Se o número de conexões ociosas exceder muito o número de conexões ativas, isso não é um problema de max_connections: é o sinal de que você precisa de um pooler na frente do servidor, e não de um número maior.

A solicitação de monitoramento da etapa 5, diretamente utilizável:

psqlsql
SELECT state, count(*)
FROM pg_stat_activity
GROUP BY state
ORDER BY count(*) DESC;
#
Sinal de alerta

Quando a fórmula não é mais suficiente: os sinais de que você precisa de um pooler

Três sinais retornam sistematicamente quando max_connections por si só não é mais suficiente, qualquer que seja o seu valor.

  1. O erro FATAL: sorry, too many clients already aparece durante o pico de carga, enquanto a maioria das conexões exibidas por pg_stat_activity estão no estado inativo.
  2. O aplicativo é executado em um ambiente sem servidor ou com trabalhadores efêmeros (funções de borda, trabalhos curtos), que abrem e fecham conexões muito mais rápido do que o modelo de processo por conexão do Postgres foi projetado para acomodar.
  3. A fórmula e o procedimento acima já foram aplicados, e a necessidade real de conexões de clientes continua excedendo a memória disponível que pode ser alocada sem colocar em risco work_mem ou shared_buffers.

Nestes três casos, a resposta correta é quase sempre um pooler posicionado entre a aplicação e o Postgres, e não um max_connections mais alto. Nossa comparação PgBouncer, Supavisor e PgCat detalha as três opções, e nosso guia para modo de transação explica o comprometimento mais comum quando o pooler estiver instalado. Para todos os ajustes do Postgres além das conexões, consulte nossa lista de verificação de ajuste do Postgres de produção.

#
Perguntas frequentes

Perguntas frequentes

Qual é o max_connections padrão do PostgreSQL?+
100, com 3 conexões reservadas para o superusuário por padrão (superuser_reserved_connections). Esse padrão é adequado para muitos aplicativos que passam por um pooler, mas rapidamente se torna insuficiente sem pooling assim que uma frota de aplicativos processa cada um abrindo seu próprio lote de conexões.
Podemos alterar max_connections sem reiniciar o PostgreSQL?+
Não. max_connections é um parâmetro de contexto do postmaster: o Postgres o lê uma vez na inicialização para dimensionar sua memória compartilhada. ALTER SYSTEM SET grava o novo valor em postgresql.auto.conf, mas apenas uma reinicialização completa do servidor o aplica; uma recarga ou um SIGHUP não são suficientes.
Quanta memória uma conexão PostgreSQL ociosa consome?+
Não existe um número oficial único: depende de work_mem, shared_buffers e extensões carregadas por sessão. O que está documentado, entretanto, é que work_mem é alocado por operação de classificação ou hash em uma consulta, não por conexão: uma única consulta complexa pode, portanto, consumir work_mem várias vezes em uma única conexão ativa.
Devemos sempre preferir um pooler como o PgBouncer a um max_connections mais alto?+
Na maioria dos casos, sim, assim que o número de conexões reais do cliente exceder em muito a simultaneidade ideal calculada pela fórmula wiki do PostgreSQL. Um pooler de modo de transação agrupa um pequeno número de conexões físicas entre um número muito maior de conexões lógicas no lado do aplicativo. Veja nossa comparação entre PgBouncer, Supavisor e PgCat para escolher qual deles.
O que exatamente a fórmula (núcleos × 2) + discos eficientes mede?+
Ele estima a simultaneidade ativa ideal: o número de solicitações que a CPU e o disco de um determinado servidor podem processar em paralelo sem degradar o rendimento, e não o número total de conexões a serem abertas em max_connections. Este é um ponto de partida a ser validado por medição, documentado pelo wiki oficial do projeto PostgreSQL, e não um limite rígido.
Como posso saber se meu servidor Postgres está próximo do limite de conexões?+
Consulte pg_stat_activity e compare o número de conexões em estado ativo com aquelas em estado inativo. Um grande número de conexões ociosas próximas ao limite de max_connections, sem nenhuma solicitação ativa por trás dele, quase sempre indica uma necessidade de pool em vez de uma necessidade de aumentar ainda mais max_connections.

PRONTO PARA IMPLEMENTAR?

Seu back-end em cinco minutos.

Não é necessário cartão de crédito · 500 MB grátis · 50.000 MAU