<h2>Connection Pooling em Node.js</h2>
<p>Connection pooling é uma técnica fundamental para otimizar o uso de conexões com bancos de dados. Em vez de criar uma nova conexão a cada requisição (operação custosa), mantemos um conjunto de conexões reutilizáveis. Isso reduz latência, economiza recursos e melhora a throughput da aplicação.</p>
<p>No Node.js, a maioria das bibliotecas de database já implementa pooling nativamente. Vamos explorar com PostgreSQL usando <code>pg</code>:</p>
<pre><code class="language-javascript">const { Pool } = require('pg');
const pool = new Pool({
user: 'usuario',
password: 'senha',
host: 'localhost',
port: 5432,
database: 'meu_banco',
max: 20, // máximo de conexões no pool
idleTimeoutMillis: 30000, // fecha conexões ociosas
connectionTimeoutMillis: 2000,
});
// Usar a conexão
pool.query('SELECT * FROM usuarios WHERE id = $1', [1], (err, res) => {
if (err) console.error(err);
else console.log(res.rows);
});
// Fechar o pool quando a app encerrar
pool.end();</code></pre>
<h3>Configuração Avançada</h3>
<p>A chave está em encontrar o equilíbrio entre <code>max</code> (número máximo de conexões) e consumo de memória. Para aplicações de médio porte, 20-50 conexões costumam ser suficientes. Se sua aplicação está em produção com alta concorrência, monitore métricas: quantas conexões estão ativas vs ociosas. Use <code>pool.totalCount</code> e <code>pool.availableCount</code> para debug.</p>
<pre><code class="language-javascript">setInterval(() => {
console.log(Ativas: ${pool.totalCount}, Disponíveis: ${pool.availableCount});
}, 5000);</code></pre>
<p>---</p>
<h2>Query Optimization</h2>
<p>Otimizar queries é onde a maioria ganha performance exponencial. A diferença entre uma query ruim e uma boa pode ser de 100x ou mais. Foque em três pilares: índices, evitar N+1 queries, e prepared statements.</p>
<h3>Índices e Explain</h3>
<p>Sempre use <code>EXPLAIN ANALYZE</code> antes de considerar uma query pronta para produção. Isso mostra o plano de execução e se está usando índices corretamente.</p>
<pre><code class="language-sql">EXPLAIN ANALYZE SELECT * FROM usuarios WHERE email = 'teste@example.com';
-- Criar índice se necessário
CREATE INDEX idx_usuarios_email ON usuarios(email);</code></pre>
<p>Em Node.js, pratique isso antes de fazer o deploy:</p>
<pre><code class="language-javascript">async function analisarQuery() {
const resultado = await pool.query(`
EXPLAIN ANALYZE
SELECT u.id, u.nome, COUNT(p.id) as posts
FROM usuarios u
LEFT JOIN posts p ON u.id = p.usuario_id
GROUP BY u.id
`);
console.log(resultado.rows);
}</code></pre>
<h3>Evitar o Problema N+1</h3>
<p>Este é o erro mais comum. Você faz uma query que retorna N linhas, depois faz N queries adicionais em um loop. Solução: use JOINs ou batch loading.</p>
<p><strong>❌ Errado — N+1 queries:</strong></p>
<pre><code class="language-javascript">async function buscarUsuariosComPostsErrado() {
const usuarios = await pool.query('SELECT * FROM usuarios LIMIT 10');
for (let user of usuarios.rows) {
const posts = await pool.query(
'SELECT * FROM posts WHERE usuario_id = $1',
[user.id]
); // 10 queries adicionais!
user.posts = posts.rows;
}
return usuarios.rows;
}</code></pre>
<p></p>
<p>Correto — Uma única query com JOIN:**</p>
<pre><code class="language-javascript">async function buscarUsuariosComPostsCerto() {
const resultado = await pool.query(`
SELECT
u.id, u.nome, u.email,
json_agg(json_build_object('id', p.id, 'titulo', p.titulo)) as posts
FROM usuarios u
LEFT JOIN posts p ON u.id = p.usuario_id
GROUP BY u.id
LIMIT 10
`);
return resultado.rows;
}</code></pre>
<p>Isso reduz 10+ queries para exatamente 1. Performance dramática.</p>
<h3>Prepared Statements e Parametrização</h3>
<p>Sempre use placeholders (<code>$1, $2</code>) ao invés de concatenar strings. Isso previne SQL injection e permite que o banco reutilize planos de execução compilados.</p>
<pre><code class="language-javascript"></code></pre>
<p>---</p>
<h2>Monitoramento e Boas Práticas</h2>
<p>Aplicações em produção precisam de observabilidade. Implemente métricas de performance de queries: tempo de execução, quantidade de linhas retornadas, e uso do pool.</p>
<pre><code class="language-javascript">const { performance } = require('perf_hooks');
async function queryComMonitoramento(sql, params) {
const inicio = performance.now();
try {
const resultado = await pool.query(sql, params);
const duracao = performance.now() - inicio;
console.log([QUERY] ${duracao.toFixed(2)}ms - ${sql.substring(0, 50)});
return resultado;
} catch (erro) {
console.error([ERRO] Query falhou após ${(performance.now() - inicio).toFixed(2)}ms);
throw erro;
}
}</code></pre>
<h3>Checklist de Otimização</h3>
<ul>
<li>Use índices nas colunas de filtro (WHERE, JOIN, ORDER BY)</li>
<li>Selecione apenas as colunas necessárias (evite SELECT *)</li>
<li>Aggregate dados no banco (GROUP BY, SUM) em vez de na aplicação</li>
<li>Cache resultados que mudam pouco frequentemente</li>
<li>Use transactions (<code>BEGIN/COMMIT</code>) para múltiplas operações relacionadas</li>
<li>Configure timeouts: <code>statement_timeout</code> no PostgreSQL para queries que travam</li>
</ul>
<p>---</p>
<h2>Conclusão</h2>
<p>Connection pooling e query optimization são competências essenciais para desenvolvedores Node.js que lidam com dados. Comece dominando EXPLAIN ANALYZE e eliminando N+1 queries—esses dois pontos podem resolver 80% dos problemas de performance. Em segundo lugar, configure seu pool conscientemente: nem muito pequeno (sufoca requisições) nem muito grande (desperdiça memória). Por fim, meça tudo: implemente logging e monitoramento desde o início, porque otimização sem métricas é apenas adivinhação.</p>
<p>---</p>
<h2>Referências</h2>
<ol>
<li><a href="https://www.postgresql.org/docs/current/sql-explain.html" target="_blank" rel="noopener noreferrer">PostgreSQL Documentation - EXPLAIN</a></li>
<li><a href="https://node-postgres.com/api/pool" target="_blank" rel="noopener noreferrer">node-postgres Pool Documentation</a></li>
<li><a href="https://use-the-index-luke.com/" target="_blank" rel="noopener noreferrer">High Performance Node.js - Use The Index, Luke</a></li>
<li><a href="https://blog.logrocket.com/node-js-database-performance/" target="_blank" rel="noopener noreferrer">Optimization Tips for Node.js + SQL - LogRocket</a></li>
<li><a href="https://www.postgresql.org/docs/current/runtime-config-query.html" target="_blank" rel="noopener noreferrer">PostgreSQL Query Tuning Official Guide</a></li>
</ol>