Quando uma página demora, “o backend está lento” costuma ser a primeira hipótese. Às vezes está. Em outras, o tempo desapareceu na resolução de DNS, no handshake TLS, em uma conexão que não foi reutilizada, em consultas repetidas ou em JavaScript demais antes da primeira renderização.
O caminho completo importa porque o usuário não experimenta camadas. Ele experimenta o total.
Meça antes de escolher o culpado
Abra o painel de rede do navegador e observe a requisição principal. Os tempos normalmente aparecem divididos em etapas:
- resolução de DNS;
- abertura da conexão;
- negociação TLS;
- espera pelo primeiro byte;
- transferência da resposta;
- trabalho realizado pelo browser depois da resposta.
O Server-Timing permite expor métricas internas na mesma visão:
Server-Timing: auth;dur=8, db;dur=42, render;dur=17Com isso, uma espera de 180 ms deixa de ser um bloco opaco. Você sabe quanto pertence à autenticação, ao banco, à renderização e ao restante do caminho.
Preserve um identificador de correlação
Gere ou aceite um request-id na borda e carregue esse valor por todas as chamadas internas. Inclua o identificador nos logs e, quando possível, devolva-o no cabeçalho da resposta.
const requestId = request.headers['x-request-id'] ?? crypto.randomUUID();
logger.info({
requestId,
route: request.url,
method: request.method,
});Se a operação publicar mensagens ou iniciar um job, propague o mesmo contexto. O objetivo é seguir a ação, não apenas uma conexão HTTP.
Procure multiplicação de trabalho
Muitos problemas de desempenho não vêm de uma operação lenta, mas de uma operação razoável executada vezes demais.
Uma listagem que faz uma consulta para carregar os itens e depois uma consulta por item pode funcionar com dez registros e falhar com mil. Esse padrão aparece como uma sequência repetida nos traces e como aumento quase linear da latência.
Antes de adicionar cache:
- conte quantas consultas uma rota executa;
- confira os planos das consultas mais caras;
- verifique índices e volume retornado;
- remova dados que o cliente não usa;
- só então decida o que pode ser armazenado em cache.
Cache sem estratégia de invalidação troca um problema de velocidade por um problema de consistência.
Não termine a análise no primeiro byte
Uma resposta rápida ainda pode produzir uma página lenta. O browser precisa analisar HTML, baixar recursos, executar scripts, calcular estilos e desenhar o resultado.
No frontend, acompanhe pelo menos:
- LCP, para saber quando o principal conteúdo visível aparece;
- INP, para medir a resposta às interações;
- CLS, para identificar mudanças inesperadas de layout;
- tamanho e custo de execução do JavaScript enviado.
Renderizar conteúdo essencial no servidor, reservar dimensões de imagens e carregar módulos sob demanda costuma oferecer ganhos mais confiáveis do que micro-otimizações isoladas.
Construa uma linha do tempo única
Logs dizem o que aconteceu. Métricas mostram frequência e tendência. Traces conectam as etapas da operação. Os três sinais se complementam.
Comece pequeno: identificador de correlação, duração total por rota, tempo de banco e código de resultado. Depois adicione spans para dependências externas e filas. Um conjunto enxuto de dados relacionados é mais útil do que uma coleção enorme que ninguém consegue consultar durante um incidente.
Quando cada etapa fica visível, desempenho deixa de ser uma discussão por intuição. A equipe consegue localizar o custo, comparar versões e decidir se a correção pertence ao browser, à rede, ao servidor ou ao modelo de dados.
