'Too many connections': pool de conexões do banco explicado

'Too many connections' significa que todas as vagas de conexão permitidas pelo max_connections estão ocupadas, então o banco recusa novos clientes. Resolva reaproveitando conexões com um pool e fechando vazamentos, não aumentando o limite primeiro.

Atualizado em 6 min de leitura

Objetivos de aprendizado

Depois de ler este artigo, você vai conseguir:

  • Ler as mensagens de erro do MySQL e do PostgreSQL e entender a qual limite elas apontam
  • Descobrir quem está segurando as suas conexões
  • Configurar um pool de conexões com um tamanho seguro para a sua aplicação
Nesta página

Sua aplicação funcionava ontem. Hoje ela quebra ao iniciar, ou falha de forma aleatória sob carga, com uma mensagem dizendo que o banco não tem lugar para você. O banco não caiu. Ele só tem um número fixo de vagas de conexão, e alguma coisa ocupou todas.

Esse é um dos erros de produção mais comuns em bots, APIs e sites, e quase sempre é um problema do lado do cliente: processos demais, nenhum pool ou conexões que nunca são fechadas.

Processo 1Processo 2Processo 3novaconexãomax_connections3 × pool de 4 = 12 em usofolgaBanco de dadosToo many connections
Processos vezes tamanho do pool dá o total de conexões; ele precisa caber abaixo do max_connections, com folga.

Como o erro aparece?#

O MySQL (e o MariaDB) reportam o erro 1040:

text
ERROR 1040 (HY000): Too many connections

No Node.js com mysql2, aparece o mesmo texto com o código ER_CON_COUNT_ERROR.

O PostgreSQL tem duas variantes, ambas com SQLSTATE 53300:

text
FATAL:  sorry, too many clients already
FATAL:  remaining connection slots are reserved for roles with the SUPERUSER attribute

A primeira indica que o servidor chegou ao max_connections. A segunda indica que só restam as vagas reservadas para superusuários: papéis comuns ficam de fora, mas um administrador ainda consegue se conectar. Antes do PostgreSQL 16, a segunda mensagem dizia "remaining connection slots are reserved for non-replication superuser connections".

O que é uma conexão com o banco e por que ela é limitada?#

Uma conexão é uma sessão ativa entre um cliente e o servidor. No PostgreSQL cada uma é um processo separado no servidor; no MySQL cada uma ganha uma thread. Nos dois casos ela consome memória e estruturas internas do servidor, mesmo ociosa.

Por isso o servidor limita a quantidade com max_connections:

  • PostgreSQL: o padrão costuma ser 100, e o superuser_reserved_connections guarda 3 delas. Mudar o max_connections exige reiniciar o servidor.
  • MySQL: o padrão é 151. O servidor aceita max_connections + 1 clientes, e a vaga extra é para contas com o privilégio CONNECTION_ADMIN, para que um administrador ainda consiga se conectar e investigar o problema.

Aumentar esse número não sai de graça, porque cada vaga a mais consome recursos do servidor.

Por que as conexões acabam?#

Da causa mais comum para a menos comum:

  1. Sem pool, uma conexão por requisição. Código que abre um cliente novo a cada requisição ou evento multiplica as conexões pelo tráfego.
  2. Conexões vazadas. O código pega um cliente do pool e nunca o devolve, muitas vezes porque um caminho de erro pula o release() ou o close().
  3. Processos demais. Cada processo tem o seu próprio pool. Dez instâncias com pool de 10 dão 100 conexões, o padrão inteiro do PostgreSQL.
  4. Aplicações serverless ou que reiniciam sozinhas. Cada cold start ou loop de crash abre conexões novas antes que as antigas expirem no servidor.
  5. Transações longas e consultas lentas. As conexões ficam ocupadas, então o pool precisa de mais delas.
  6. Outros clientes. Ferramentas de administração, jobs de migration, scripts de cron e dashboards também contam para o mesmo limite.

Como ver quem está usando as conexões?#

No PostgreSQL, com um papel que tenha permissão para ver as outras sessões:

sql
SHOW max_connections;

SELECT count(*) AS total FROM pg_stat_activity;

SELECT usename, application_name, state, count(*)
FROM pg_stat_activity
GROUP BY usename, application_name, state
ORDER BY count(*) DESC;

Muitas linhas no estado idle com o mesmo application_name são o sinal clássico de vazamento ou de pool grande demais.

No MySQL:

sql
SHOW VARIABLES LIKE 'max_connections';
SHOW GLOBAL STATUS LIKE 'Threads_connected';
SHOW GLOBAL STATUS LIKE 'Max_used_connections';
SHOW FULL PROCESSLIST;

O Max_used_connections é o pico desde o último reinício. Se ele for igual ao max_connections, você bateu no teto pelo menos uma vez. As entradas Sleep na lista de processos são conexões ociosas.

Como resolver com pool de conexões?#

Um pool abre um número pequeno de conexões uma vez e as empresta para o seu código. As consultas esperam um instante por uma conexão livre em vez de abrir outra. Crie o pool uma vez na inicialização, compartilhe com o processo inteiro e nunca o crie dentro de um handler de requisição.

Com o pg (node-postgres), cujo pool tem max padrão de 10:

js
// db.js
import pg from "pg";

export const pool = new pg.Pool({
  connectionString: process.env.DATABASE_URL,
  max: 5, // limite máximo para ESTE processo
  idleTimeoutMillis: 10_000, // fecha clientes ociosos depois de 10 s
  connectionTimeoutMillis: 5_000, // falha rápido em vez de esperar para sempre
});

// Para consultas avulsas, deixe o pool cuidar de pegar e devolver:
const { rows } = await pool.query("SELECT now()");
console.log(rows[0]);

// Para transações, segure um cliente e SEMPRE devolva:
const client = await pool.connect();
try {
  await client.query("BEGIN");
  await client.query("UPDATE accounts SET balance = balance - 10 WHERE id = $1", [1]);
  await client.query("COMMIT");
} catch (err) {
  await client.query("ROLLBACK");
  throw err;
} finally {
  client.release();
}

Não rode uma transação pelo pool.query, porque cada chamada pode cair num cliente diferente.

Com o mysql2:

js
import mysql from "mysql2/promise";

export const pool = mysql.createPool({
  uri: process.env.DATABASE_URL,
  connectionLimit: 5,
  waitForConnections: true,
});

const [rows] = await pool.query("SELECT NOW() AS now");
console.log(rows[0]);

Em Python funciona do mesmo jeito: crie um engine (SQLAlchemy) ou pool na importação do módulo e reaproveite.

Qual deve ser o tamanho do pool?#

Faça a multiplicação antes de escolher um número:

text
total de conexões = processos x tamanho do pool

Se você roda 4 processos com pool de 5, usa 20 conexões. Some uma folga para migrations, um cliente SQL que você abre na mão e jobs de cron, e mantenha o total bem abaixo do limite. Um pool de 5 a 10 por processo costuma bastar, porque cada conexão só fica ocupada enquanto a consulta roda e, por isso, atende muitas requisições por segundo.

Se um único processo realmente precisa de centenas de consultas simultâneas, o gargalo provavelmente é o banco, e mais conexões não vão deixá-lo mais rápido.

Quando aumentar o limite ou adicionar o PgBouncer?#

Aumente o max_connections quando os seus pools já estão bem dimensionados e você simplesmente tem mais processos do que vagas. No MySQL dá para mudar com o servidor rodando:

sql
SET GLOBAL max_connections = 300;   -- perdido no reinício
SET PERSIST max_connections = 300;  -- sobrevive ao reinício

No PostgreSQL, edite o postgresql.conf e reinicie. Lembre que mais conexões usam mais memória.

Quando você tem muitos processos ou clientes de vida curta, coloque um pooler como o PgBouncer na frente do PostgreSQL. No modo de transaction pooling, uma conexão do servidor é atribuída só durante uma transação, então um conjunto pequeno de conexões do servidor atende muito mais clientes. A contrapartida: recursos que dependem de estado de sessão, como SET, LISTEN, advisory locks em nível de sessão e o PREPARE em SQL, não funcionam de forma confiável nesse modo.

Como evitar que volte?#

  • Crie um pool por processo, na inicialização.
  • Devolva as conexões em blocos finally e feche o pool no desligamento com pool.end().
  • Configure timeouts de ociosidade e de aquisição para que os problemas falhem de forma visível.
  • Dê a cada aplicação o seu próprio usuário do banco ou application_name, para saber quem está conectado.
  • Crie um alerta quando o Threads_connected ou a contagem de linhas do pg_stat_activity se aproximar de 80% do limite.

Em dúvida sobre qual motor serve para o seu projeto? Como escolher um banco de dados compara as opções, o que é o PostgreSQL explica o motor em si e como hospedar um banco de dados mostra o passo a passo para colocar um no ar.

Como fazer isso na Square Cloud#

Na Square Cloud você cria o banco no painel e faz o deploy das suas aplicações, então as configurações do pool ficam no seu código e nas variáveis de ambiente. A hospedagem de MongoDB, PostgreSQL, MySQL e Redis começa no plano Standard. Os bancos rodam no mesmo datacenter das aplicações, com TLS obrigatório.

Cada banco aceita até 512 conexões e não há pooler na frente, então quem controla o número de conexões é o pool da sua aplicação. Guarde a URL de conexão numa variável de ambiente de cada aplicação e dimensione o pool de cada processo como mostrado acima. Some os pools de todas as aplicações que apontam para o mesmo banco e mantenha o total com folga abaixo desse teto.

Cada reinício abre o pool de novo. O reinício automático é opcional (vem ligado no deploy pelo painel) e só age quando o processo encerra com erro. Se a aplicação entrar em loop de crash, cada volta abre um pool novo, então procure nos logs a causa do erro e corrija.

Para conhecer os motores e os planos, veja a página de hospedagem de bancos de dados.

Hospedagem de bancos

MongoDB, PostgreSQL, MySQL e Redis no mesmo datacenter do app

Saiba mais

Perguntas frequentes

Qual é o max_connections padrão no PostgreSQL e no MySQL?

O PostgreSQL usa 100 por padrão (pode ser menos se o kernel não suportar) e reserva 3 vagas para superusuários. O MySQL usa 151 por padrão, mais uma vaga extra para contas de administrador.

Devo simplesmente aumentar o max_connections?

Só depois de procurar vazamentos e adicionar um pool. Cada conexão custa memória no servidor, e o PostgreSQL precisa de reinício para mudar o valor. Um limite maior muitas vezes só adia o mesmo erro.

Quantas conexões um pool deve abrir?

Comece pequeno, algo entre 5 e 10 por processo da aplicação, e multiplique pelo número de processos e instâncias. O total precisa ficar abaixo do limite do banco, com folga para ferramentas de administração e migrations.

Qual a diferença entre um pool na minha aplicação e o PgBouncer?

Um pool dentro da aplicação compartilha conexões dentro de um processo. O PgBouncer fica na frente do PostgreSQL e compartilha um conjunto menor de conexões do servidor entre muitos processos ou servidores.

Próximo artigoMigrations de banco de dados no deployRode migrations de banco no deploy com Prisma, Drizzle ou Alembic: um passo antes do código novo subir, seguro contra falhas. Comandos, verificação e erros.

Mais em Bancos de dados

Ver todos os 24 artigos