Cache: não recalcular o que você já sabe
Se uma operação é cara (uma consulta pesada, uma chamada externa) e seu resultado muda pouco, coloque em cache. Um armazenamento em memória como o Redis guarda pares chave-valor com acesso quase instantâneo e um TTL (tempo de vida) opcional:
// Pseudocódigo conceitual:
let dados = await redis.get("usuario:1");
if (!dados) { // "miss": não estava em cache
dados = await db.buscarUsuario(1);
await redis.set("usuario:1", dados, "EX", 60); // expira em 60 s
}
O padrão cache-aside: olhe o cache primeiro; se houver hit, devolva-o; se houver miss, calcule, guarde no cache e devolva.
Usar todos os núcleos
Um processo do Node usa um núcleo para o seu JS. Para aproveitar uma máquina com vários núcleos há duas ferramentas complementares:
- Clustering (
node:cluster): lança vários processos idênticos (workers) que compartilham a mesma porta. O sistema reparte as conexões entrantes entre eles. Resolve a escalabilidade de um servidor HTTP: mais processos atendem mais requisições em paralelo, e se um cai, os demais seguem. worker_threads: threads dentro de um processo, com seu próprio event loop. Servem para trabalho de CPU intensivo (processar imagens, cálculos pesados) sem bloquear a thread principal.
Não bloquear o event loop
Como o seu JS é single-thread, uma operação síncrona e longa congela TUDO: enquanto calcula, nenhuma outra requisição é atendida.
// RUIM: bloqueia o event loop durante todo o laço.
function somaLenta(n) {
let total = 0;
for (let i = 0; i < n; i++) total += i; // se n for enorme, ninguém mais avança
return total;
}
A regra de ouro: mantenha a thread principal livre. O trabalho pesado de CPU vai para
um worker_thread; o I/O (rede, disco, BD) já é assíncrono e não bloqueia. Assim o
event loop segue aceitando e respondendo requisições.
Exemplos
Cache-aside: hit evita recalcular
const cache = new Map();
function obterCaro(chave, calcular) {
if (cache.has(chave)) return cache.get(chave); // hit
const valor = calcular(); // miss: calcula
cache.set(chave, valor); // e guarda
return valor;
}
let vezes = 0;
const calc = () => { vezes++; return 42; };
obterCaro("x", calc);
obterCaro("x", calc); // segunda vez: hit, não recalcula
console.log(vezes); // 1