Decisão: como configurar o pooling de conexões?
Cada conexão com o banco carrega custo de memória e de escalonamento; um crescimento descontrolado do número de conexões deixa o servidor lento ou até o derruba. Um pool de conexões resolve isso reutilizando um pequeno número de conexões persistentes. Esta árvore orienta as decisões sobre onde o pool fica, qual modo usar (session/transaction/statement) e o tamanho correto, e enfatiza por que um pooler externo é obrigatório em ambientes serverless.
Como a arquitetura da sua aplicação se conecta?
A decisão de pooling começa pela arquitetura. É um único processo de aplicação de longa duração (servidor clássico), muitos processos/instâncias independentes (microsserviços, muitos pods) ou funções serverless/Lambda que nascem e morrem a cada request? Cada caso exige um posicionamento diferente do pool.
- Um/poucos processos de aplicação de longa duração
- Muitos processos/instâncias/pods se conectam ao mesmo banco
- Serverless / Lambda / funções de curta duração
- Primeiro, mostre-me como escolher o tamanho certo do pool
Como escolher o modo do pooler intermediário?
Com muitos clientes, um pooler intermediário (PgBouncer, ProxySQL) mantém baixo o número de conexões no banco. Mas o modo do pool depende dos recursos que a aplicação usa: você depende de estado vinculado à sessão (prepared statements, tabelas temporárias, SET, advisory locks, recursos no nível de sessão), ou tudo se conclui dentro de uma única transação?
- Dependo do estado da sessão (SET, tabelas temporárias, prepared statements de sessão)
- As transações são curtas e independentes; não mantenho estado de sessão
Recomendação: pool de conexões dentro da aplicação
Para um/poucos processos de longa duração, uma biblioteca de pool dentro da aplicação (HikariCP, o pool nativo do database/sql do Go, o pooling de conexões do .NET) atende à maioria das necessidades. As conexões são abertas uma vez e reutilizadas repetidamente.
Recomendação: dimensione o pool corretamente
O pool não deve ser pequeno demais (os requests esperam) nem grande demais. Conexões em excesso geram troca de contexto de CPU e contenção de locks e reduzem o throughput. O tamanho não é um número a crescer indefinidamente, mas um número pequeno baseado em núcleos e I/O.
Recomendação: modo de pool session
No modo session, a conexão de um cliente fica presa a uma conexão de servidor backend até o fim da sessão. O estado no nível de sessão (SET, tabelas temporárias, advisory locks, prepared statements de sessão) é preservado, mas o compartilhamento de conexões é mínimo.
Recomendação: modo de pool transaction
No modo transaction, uma conexão de servidor é emprestada ao cliente apenas durante uma transação e volta ao pool quando ela termina. Assim, milhares de clientes podem trabalhar com pouquíssimas conexões reais no banco; é o modo mais comum em alta escala.
Recomendação: um pooler externo é obrigatório em serverless
Funções serverless/Lambda escalam rapidamente e cada instância abre a própria conexão; um pool dentro da aplicação não ajuda aqui porque as instâncias têm vida curta e não compartilham nada. Quando centenas/milhares de instâncias surgem de repente, o limite de conexões do banco estoura. A solução é um pool de conexões externo à frente do banco.