Home > Blog > Desenvolvimento Web
Desenvolvimento Web
JavaScript
Programação

Clinic.js no Node.js

Atualizado em: 27 de setembro de 2026

Rack de servidores processando fluxos de dados no Node.js

Clinic.js é um conjunto de ferramentas para diagnosticar desempenho em aplicações Node.js. Ele reúne coleta, visualização e análise de métricas que normalmente exigiriam vários comandos separados. Com Clinic Doctor, Bubbleprof, Flame e Heap Profiler, é possível investigar CPU alta, event loop bloqueado, operações assíncronas lentas, uso excessivo de memória e regressões sob carga.

A principal vantagem é transformar dados técnicos em relatórios interativos. Em vez de analisar somente números isolados, você consegue relacionar o comportamento do processo com pilhas de chamadas, recursos assíncronos e períodos de carga. Ainda assim, Clinic.js não substitui observabilidade contínua: ele é uma ferramenta de diagnóstico usada para responder a uma hipótese concreta.

Quando usar Clinic.js

Use Clinic.js quando uma aplicação apresenta sintomas como:

  • latência alta mesmo com banco de dados saudável;
  • CPU crescente durante determinadas rotas;
  • event loop delay elevado;
  • throughput abaixo do esperado;
  • requisições que permanecem abertas por muito tempo;
  • memória que cresce durante testes de longa duração;
  • regressão depois de uma mudança de código.

Antes de iniciar, defina uma pergunta. Exemplos: “qual função bloqueia o event loop?”, “qual etapa assíncrona prolonga a requisição?” ou “quais alocações aumentam o heap?”. Uma captura sem hipótese tende a produzir muito dado e pouca decisão.

Instalação

npm install --save-dev clinic
npx clinic --help

Em ambientes controlados, também é possível instalar globalmente. Para projetos reproduzíveis, prefira dependência de desenvolvimento e fixe a versão no lockfile.

Prepare uma carga representativa

O profiler precisa observar o problema. Inicie a aplicação com dados, configurações e volume próximos do cenário real. Aqueça caches, pools de conexão, JIT e rotas antes de capturar. Depois gere carga com uma ferramenta como Autocannon ou k6.

npx autocannon -c 40 -d 45 http://127.0.0.1:3000/api/items

Execute o gerador em outro terminal. Em medições sérias, use outra máquina ou container para impedir que o cliente dispute CPU com o servidor.

Clinic Doctor

Doctor é o ponto de partida. Ele coleta CPU, memória, event loop delay e atividade de I/O para indicar a classe provável do problema.

npx clinic doctor -- node dist/server.js

Gere carga, espere o sintoma aparecer e encerre o processo de forma controlada. Clinic.js processará os dados e abrirá um relatório. O Doctor pode apontar:

  • CPU limitada;
  • event loop bloqueado;
  • I/O insuficiente ou inconsistente;
  • memória crescente;
  • comportamento saudável no período medido.

A recomendação é uma pista, não uma prova. Valide com Flame, Bubbleprof, Heap Profiler e métricas da aplicação.

Clinic Flame

Flame gera uma visualização de CPU por pilha de chamadas. Barras largas indicam funções presentes em muitas amostras. Procure funções folha largas, serialização, regex, loops, compressão, criptografia e bibliotecas nativas.

npx clinic flame -- node dist/server.js

Para concentrar a análise no código da aplicação, use os filtros disponíveis com cuidado. Não remova módulos internos cedo demais, porque o gargalo pode estar no runtime ou em um addon.

Clinic Bubbleprof

Bubbleprof visualiza operações assíncronas e os relacionamentos entre elas. Ele é útil quando CPU parece normal, mas requisições permanecem lentas devido a filas, chamadas HTTP, banco, timers, promises ou recursos que não encerram.

npx clinic bubbleprof -- node dist/server.js

As “bolhas” agrupam recursos assíncronos relacionados. Uma área grande ou conexão longa pode indicar uma operação que domina o tempo total. Compare o diagrama com traces distribuídos e logs correlacionados.

Clinic Heap Profiler

Heap Profiler mostra onde a aplicação aloca memória ao longo do tempo. Ele complementa heap snapshots: o profiler ajuda a localizar fontes de alocação, enquanto snapshots ajudam a entender retenção e caminhos até raízes do garbage collector.

npx clinic heapprofiler -- node dist/server.js

Reproduza o fluxo suspeito várias vezes. Observe funções que continuam acumulando alocações. Caches sem limite, listeners, closures, buffers e filas são causas comuns.

Usando o comando on-port

Clinic.js pode iniciar um comando quando a porta estiver disponível. Isso automatiza o teste e reduz diferenças entre execuções.

npx clinic doctor \
  --on-port 'autocannon -c 40 -d 30 localhost:$PORT/api/items' \
  -- node dist/server.js

Adapte a variável de porta ao projeto. Confirme que o comando de carga termina, pois Clinic.js precisa encerrar e processar a captura.

Nomeando e organizando relatórios

Salve cada execução com contexto: commit, ambiente, cenário, duração e parâmetros de carga. Uma estrutura simples evita misturar resultados.

diagnostics/
  2026-09-27-checkout-before/
  2026-09-27-checkout-after/

Não versionar relatórios grandes no repositório principal costuma ser melhor. Use armazenamento interno com retenção definida.

Comparação antes e depois

Uma otimização só é válida quando melhora o resultado do usuário sem criar regressões. Repita exatamente:

  • mesma versão do Node.js;
  • mesma máquina e limites de CPU;
  • mesmo conjunto de dados;
  • mesma duração e concorrência;
  • mesmo aquecimento;
  • mesmos percentis observados.

Compare throughput, p95, p99, taxa de erro, CPU, memória, event loop delay e o relatório Clinic.js. Uma função menor no flamegraph pode apenas ter movido custo para outra etapa.

Exemplo de bloqueio síncrono

import express from 'express';
import crypto from 'node:crypto';

const app = express();

app.get('/hash', (req, res) => {
  const result = crypto.pbkdf2Sync('senha', 'salt', 300000, 32, 'sha256');
  res.json({ hash: result.toString('hex') });
});

app.listen(3000);

Durante carga concorrente, a função síncrona bloqueia a thread principal. Doctor pode detectar event loop bloqueado e Flame deve mostrar a pilha de criptografia. A correção pode usar API assíncrona, worker thread ou arquitetura de fila, sem reduzir parâmetros de segurança arbitrariamente.

Exemplo de cadeia assíncrona lenta

app.get('/dashboard', async (req, res) => {
  const user = await users.findById(req.user.id);
  const orders = await ordersApi.list(user.id);
  const recommendations = await recommendationsApi.get(user.id);
  res.json({ user, orders, recommendations });
});

Bubbleprof pode revelar que chamadas independentes foram executadas em sequência. Quando seguro, use concorrência controlada:

const [orders, recommendations] = await Promise.all([
  ordersApi.list(user.id),
  recommendationsApi.get(user.id),
]);

Defina timeouts, cancelamento e limites para evitar sobrecarga em dependências.

Produção

Profiling adiciona overhead e pode gerar arquivos sensíveis. Em produção:

  • use uma réplica isolada;
  • capture por período curto;
  • monitore impacto;
  • controle acesso aos relatórios;
  • não exponha interfaces de diagnóstico publicamente;
  • remova arquivos após a análise;
  • registre quem iniciou a captura.

Quando possível, reproduza em staging com tráfego ou dados sintéticos representativos.

Containers

Em Docker, monte um volume para persistir relatórios e garanta que sinais cheguem ao processo Node.js. Use um init apropriado e não execute o profiler em todas as réplicas.

docker run --rm \
  -p 3000:3000 \
  -v "$PWD/diagnostics:/app/.clinic" \
  app-clinic

Limites baixos de CPU ou memória podem alterar o perfil. Registre requests, limits e throttling.

Erros comuns

  • capturar sem reproduzir o problema;
  • usar carga curta demais;
  • confundir correlação com causa;
  • otimizar apenas média e ignorar p99;
  • executar cliente e servidor na mesma CPU saturada;
  • comparar relatórios de ambientes diferentes;
  • publicar arquivos de diagnóstico;
  • não validar a correção com novo teste.

Fluxo recomendado

  1. confirme o sintoma em métricas;
  2. formule uma hipótese;
  3. reproduza com carga estável;
  4. comece pelo Doctor;
  5. aprofunde com Flame, Bubbleprof ou Heap Profiler;
  6. relacione o resultado ao código;
  7. faça uma alteração pequena;
  8. repita o teste;
  9. documente os números antes e depois.

Combine Clinic.js com Flamegraphs no Node.js, carga com Autocannon ou k6, memória com Heap Snapshots e profiling contínuo com Pyroscope.

Consulte a documentação oficial do Clinic.js e o repositório oficial do projeto.

10 melhores cursos de programação em 2026

Descubra os melhores cursos de programação. Aprenda a escolher o curso ideal para iniciar ou avançar na carreira de desenvolvedor

POSTS RELACIONADOS

Ver todos

Seta para a direita