O que é o PgBouncer

O PostgreSQL tem um limite prático de conexões simultâneas. Cada conexão consome memoria e CPU, e quando você tem centenas de instâncias de app abrindo conexões diretas, o banco começa a sofrer. O PgBouncer resolve isso sendo um proxy leve que fica entre a aplicação e o PostgreSQL.

O PgBouncer mantem um pool de conexões abertas com o banco e as reutiliza entre múltiplos clientes. Em vez de cada requisição da app abrir e fechar uma conexão com o PostgreSQL, ela pega uma conexão do pool, usa e devolve. O banco ve pouquíssimas conexões, independente de quantas instâncias de app estão rodando.

O projeto e open source, mantido pela comunidade PostgreSQL, e e considerado a solução padrão para pooling de conexões em ambientes de produção com Postgres.

Como funciona o pool de conexões

O PgBouncer roda como um processo separado, geralmente na mesma máquina que a aplicação ou no servidor de banco. A aplicação se conecta ao PgBouncer como se fosse o PostgreSQL, e o PgBouncer gerência as conexões reais com o banco.

O mecanismo de pool tem três modos de operação, cada um com um nível diferente de reutilização de conexão:

  • Transaction mode: a conexão e reutilizada entre transações. E o modo mais eficiente e o recomendado para a maioria dos casos.
  • Session mode: cada sessão do cliente mantem uma conexão dedicada até desconectar. Menos eficiente, mas mais compatível com features de sessão do PostgreSQL.
  • Statement mode: a conexão e liberada após cada statement. Muito restritivo, pois não permite transações multistatement.
tip
Dica

Comece com transaction mode. Se encontrar erros relacionados a sessão, avalie mudar para session mode somente onde necessário.

Principais recursos do PgBouncer

O PgBouncer e pequeno e direto ao ponto. Seu foco e fazer uma coisa bem: gerenciar conexões.

  • Pool por banco e usuário: pools separados por banco e usuário, com limites configurados individualmente
  • Reconexao automática: se a conexão com o PostgreSQL cair, o PgBouncer reconecta automaticamente
  • Autenticação: suporte a métodos de autenticação do PostgreSQL
  • Admin interface: console de administração via PSQL para monitorar pools em tempo real
  • Leve: usa menos de 2MB de RAM por pool de 1000 conexões de servidor
warning
Atenção

Em transaction mode, prepared statements persistentes não funcionam. Se sua ORM usa prepared statements, configure para desabilitar ou use session mode.

Como começar: instalação e configuração básica

O PgBouncer esta disponível nos repositórios de todas as distribuições Linux principais. A instalação e simples:

sudo apt install pgbouncer

A configuração principal fica em pgbouncer.ini. O arquivo define os bancos, o pool e as permissões:

[databases]
meudb = host=127.0.0.1 port=5432 dbname=meudb

[pgbouncer]
listen_addr = 127.0.0.1
listen_port = 6432
auth_type = md5
auth_file = /etc/pgbouncer/userlist.txt
pool_mode = transaction
max_client_conn = 1000
default_pool_size = 20

O arquivo userlist.txt lista usuários e senhas que podem se conectar ao PgBouncer.

Exemplo prático: configurando para alta disponibilidade

Em um cenário típico de produção, múltiplas instâncias da aplicação conectam ao banco. Sem pool, cada instância com 10 threads abre 10 conexões. Com 50 instâncias, são 500 conexões.

-- Sem PgBouncer
50 instâncias x 10 threads = 500 conexões no PostgreSQL
max_connections no postgres.conf = 100 -- PROBLEMA

-- Com PgBouncer (transaction mode)
PgBouncer: max_client_conn = 1000
PgBouncer: default_pool_size = 20
PostgreSQL ve: 20 conexões -- OK

Com essa configuração, 500 clientes competem por 20 conexões reais. Em transaction mode, cada transação dura milissegundos, então as 20 conexões são suficientes.

pro
Pro tip

Monitore o campo sv_idle no console do PgBouncer. Se estiver sempre em zero, o pool_size esta muito pequeno e clientes ficam esperando conexão.

Comparação com alternativas

O PgPool-II e uma alternativa mais completa: além de pool, oferece replicação, balanceamento de carga e failover automático. Mas e mais complexo de configurar e mais pesado.

O Odyssey, criado pelo Yandex, e um pool moderno com melhor suporte a multiprocessamento. Mais rápido que o PgBouncer em benchmarks recentes, mas com adoção menor.

O HikariCP (Java) e o pgxpool (Go) são pools no lado do cliente. Mais simples, mas sem compartilhamento global entre instâncias da app.

Pontos positivos e limitações

Positivos: extremamente leve, maduro, simples de configurar, reduz drasticamente a pressão de conexões no PostgreSQL.

Limitações: transaction mode não e compatível com todas as features do PostgreSQL. Prepared statements globais, LISTEN/NOTIFY e SET LOCAL não funcionam em transaction mode.

  • Single-threaded: para cargas muito altas pode ser gargalo de CPU
  • Configuração de autenticação trabalhosa em ambientes com muitos usuários
  • Sem failover automático nativo (precisa de solução externa)

Casos de uso reais

APIs com muitas conexões curtas: o caso clássico. Uma API REST com dezenas de workers por instância e múltiplas replicas. Sem pool, o PostgreSQL sofre.

Ambientes serverless: funções serverless criam conexões efémeras a cada invocação. O PgBouncer e essencial para evitar esgotar as conexões do banco.

Manutenção sem downtime: o PgBouncer pode pausar conexões de clientes enquanto você executa migração no banco, depois libera tudo automaticamente.

Microservicos com PostgreSQL compartilhado: múltiplos serviços acessando o mesmo banco se beneficiam de um PgBouncer centralizado.

pro
Pro tip

Use o comando PAUSE no console admin do PgBouncer antes de fazer manutenção no PostgreSQL. O PgBouncer segura as conexões dos clientes e reconecta após RESUME.

Dicas e boas práticas

tip
Dica

Monitore o PgBouncer com SHOW POOLS; e SHOW STATS; no console admin. Os campos cl_waiting e sv_idle são os mais importantes para tunar o pool_size.

tip
Dica

Coloque o PgBouncer na mesma máquina que o PostgreSQL ou muito próximo na rede. Latência entre PgBouncer e banco tem impacto direto na performance.

warning
Atenção

Não coloque pool_size muito alto. Mais conexões no PostgreSQL não e necessariamente melhor. Teste com valores entre 10 e 25 e ajuste baseado em métricas reais.

danger
Cuidado

Em transaction mode, nunca use SET para configurar parâmetros de sessão. Configure search_path no pgbouncer.ini ou no nível do banco no PostgreSQL.

Vale a pena?

Para qualquer aplicação com PostgreSQL em produção que tem mais de 20-30 conexões simultâneas, o PgBouncer e quase obrigatório. O custo de configurar e mínimo e o ganho de performance e imediato.

Se você já tem problemas com too many connections no PostgreSQL, adicionar o PgBouncer e provavelmente a intervenção de maior impacto com menor esforço.

O próximo passo: instale o PgBouncer em staging, configure com transaction mode e pool_size=20, redirecione a aplicação para a porta 6432 e compare as métricas antes e depois.