Noções Básicas de Desempenho
8 exemplos para você começar com Desempenho para backends Node.js - 6 básicos e 2 intermediários.
Busque em todas as páginas da documentação
8 exemplos para você começar com Desempenho para backends Node.js - 6 básicos e 2 intermediários.
npm install -g clinic para profiling (veja Clinic.js Suite).hrtimeTimers de alta resolução superam Date.now() para medição de latência.
import { createServer } from "node:http";
const server = createServer((req, res) => {
const start = process.hrtime.bigint();
res.end("ok");
const elapsedMs = Number(process.hrtime.bigint() - start) / 1_000_000;
console.log(JSON.stringify({ path: req.url, durationMs: elapsedMs }));
});
server.listen(3000);process.hrtime.bigint() é monotônico - não afetado por desvios de relógio.Relacionado: Testes de Carga - saturação e p95 sob concorrência
Percentis importam mais que médias para SLOs de API.
const durations: number[] = [];
function recordDuration(ms: number): void {
durations.push(ms);
if (durations.length > 10_000) durations.shift();
}
function p95(): number {
const sorted = [...durations].sort((a, b) => a - b);
const idx = Math.ceil(sorted.length * 0.95) - 1;
return sorted[idx] ?? 0;
}
// Exponha via /metrics ou registre a cada N requisiçõesRelacionado: Métricas que Importam - RPS, p95, taxa de erros
O atraso do loop atrasa todos os clientes concorrentes, não apenas uma rota lenta.
import { monitorEventLoopDelay } from "node:perf_hooks";
const histogram = monitorEventLoopDelay({ resolution: 20 });
histogram.enable();
setInterval(() => {
console.log(JSON.stringify({
event: "loop_delay",
p99Ms: histogram.percentile(99) / 1e6,
maxMs: histogram.max / 1e6,
}));
histogram.reset();
}, 10_000);monitorEventLoopDelay mede o quão atrasado o loop executa o trabalho agendado.Relacionado: Detectando Bloqueio do Loop de Eventos - ferramentas de atribuição
performance.mark para Caminhos CríticosMarcas integradas se integram ao Chrome DevTools e ao clinic.js.
import { performance } from "node:perf_hooks";
async function fetchUser(id: string) {
performance.mark("fetchUser:start");
const user = await db.query("SELECT * FROM users WHERE id = $1", [id]);
performance.mark("fetchUser:end");
performance.measure("fetchUser", "fetchUser:start", "fetchUser:end");
return user;
}performance.getEntriesByName("fetchUser") retorna arrays de duração para análise.Relacionado: Clinic.js Suite - flame graphs para caminhos críticos
Conheça as requisições por segundo na concorrência alvo antes de alterar o código.
# Smoke rápido (não um teste de carga completo)
npx autocannon -c 50 -d 10 http://localhost:3000/health-c 50 simula 50 conexões concorrentes - mais próximo da produção do que um único curl.Relacionado: Testes de Carga - cenários k6 e pontos de saturação
Corpos JSON grandes bloqueiam a análise de forma síncrona na thread principal.
import express from "express";
const app = express();
app.use(express.json({ limit: "1mb" }));
app.post("/events", (req, res) => {
// corpo já limitado - rejeita tamanhos excessivos no parser
res.status(201).json({ ok: true });
});limit retorna 413 antes que seu handler seja executado - economiza CPU em abusos.Relacionado: Custo de Serialização JSON - otimização da forma da resposta
Concorrência sustentada revela bloqueios que requisições únicas escondem.
// Script k6 - salve como load-test.js
import http from "k6/http";
import { check, sleep } from "k6";
export const options = {
stages: [
{ duration: "1m", target: 50 },
{ duration: "3m", target: 50 },
{ duration: "1m", target: 0 },
],
thresholds: { http_req_duration: ["p(95)<200"] },
};
export default function () {
const res = http.get("http://localhost:3000/users");
check(res, { "status is 200": (r) => r.status === 200 });
sleep(0.1);
}thresholds falha a execução quando p95 excede 200ms - controle merges em regressões.Relacionado: Desempenho no Express - ajuste do Express sob carga
Vazamentos suspeitos precisam de evidências antes de ajustar --max-old-space-size.
import { writeHeapSnapshot } from "node:v8";
import { writeFileSync } from "node:fs";
function captureHeap(label: string): void {
const path = writeHeapSnapshot();
writeFileSync(`/tmp/heap-${label}.json`, ""); // arquivo marcador
console.log(JSON.stringify({ event: "heap_snapshot", label, path }));
}
// Chame em SIGUSR2 ou após N requisições em staging
process.on("SIGUSR2", () => captureHeap("manual"));Relacionado: Ajuste de Memória e GC -
--max-old-space-sizee flags de GC
Versões da Stack: Esta página foi escrita para Node.js 24.18.0 (Active LTS), npm 10+, TypeScript 5.6+, Express 5, Fastify 5 e NestJS 11.
Revisado por Chris St. John·Última atualização: 16 de jul. de 2026