DevPath · Aprenda a programar ESPTEN

Observabilidade e desempenho

Desempenho: cache, lazy loading e o BD

A regra de ouro: o trabalho mais rápido é o que você não faz

Otimizar o desempenho é, quase sempre, evitar trabalho repetido: não recalcular, não pedir de novo, não enviar o que já está lá. A ferramenta central para isso é o cache, e convém pensá-lo em níveis.

Cache por níveis

  1. Navegador / HTTP: o cliente guarda respostas conforme os cabeçalhos Cache-Control e ETag. Se o recurso não mudou, o servidor responde 304 Not Modified e não reenvia o corpo. Custo de rede: zero.

  2. CDN para estáticos: uma rede de servidores próximos ao usuário serve imagens, JS e CSS a partir da borda, sem tocar no seu origin. Mais perto = menos latência e menos carga no seu backend.

  3. Cache no backend (Redis) com o padrão cache-aside:

    está no cache?  → sim → devolve (rápido)
                    → não → vai ao BD, guarda o resultado no cache, devolve
    

    A aplicação gerencia o cache "ao lado" do BD. É preciso decidir o TTL (quanto tempo o dado vive) e invalidar a entrada quando o dado muda, ou você servirá dados velhos. Invalidar um cache é um dos problemas verdadeiramente difíceis.

No frontend: enviar menos e mais tarde

No banco de dados: índices e o problema N+1

O BD costuma ser o gargalo. Dois clássicos:

Meça antes de otimizar. "Acho que isto é lento" não é um dado; um p95 e um trace, sim. Otimizar às cegas adiciona complexidade sem garantia de melhora.

Exemplos

Cache-aside com um Map: não recalcular o já calculado

function cachear(fn) {
  const cache = new Map();
  return function (chave) {
    if (cache.has(chave)) return cache.get(chave);
    const valor = fn(chave);
    cache.set(chave, valor);
    return valor;
  };
}

let chamadas = 0;
const quadrado = cachear((n) => { chamadas++; return n * n; });
quadrado(8); quadrado(8); quadrado(8);
console.log("resultado:", quadrado(8), "chamadas reais:", chamadas); // 64, 1

N+1 vs. batching: 1 consulta em vez de N

// Simula uma carga "em bloco" de vários ids de uma vez.
function carregarUsuarios(ids) {
  console.log("consultas ao BD:", 1, "para", ids.length, "ids");
  return ids.map((id) => ({ id, nome: "Usuário " + id }));
}

const ids = [1, 2, 3, 4, 5];
const usuarios = carregarUsuarios(ids); // 1 viagem, não 5
console.log(usuarios.length, "usuários carregados");
Coloque isto em prática

O DevPath é um curso prático: aqui você lê a teoria; no app você a coloca em prática com exercícios que rodam de verdade, offline.

Comece grátis no app →
← Os três pilares da observabilidadeEscalonamento: horizontal, balanceadores e stateless →