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

Inspector no Node.js: Guia Prático

Atualizado em: 11 de agosto de 2026

Estação de trabalho usada no desenvolvimento de aplicações Node.js

Quando uma aplicação Node.js apresenta lentidão, vazamento de memória, uso alto de CPU ou comportamento inesperado, logs nem sempre são suficientes. O módulo e o protocolo de Inspector no Node.js permitem conectar ferramentas de depuração ao processo, definir breakpoints, acompanhar variáveis, gerar perfis de CPU, capturar heap snapshots e executar comandos do Chrome DevTools Protocol.

O Inspector é poderoso, mas também sensível. Uma porta de depuração exposta pode permitir execução de código no processo. Por isso, o acesso deve permanecer restrito ao ambiente local, a redes administrativas ou a túneis autenticados.

Neste guia, você aprenderá a iniciar o Node.js com inspeção, usar Chrome DevTools, VS Code e o módulo node:inspector, coletar perfis, analisar memória, depurar processos em containers e proteger o endpoint de depuração.

O que é o Inspector?

O Node.js implementa o Chrome DevTools Protocol para expor recursos de depuração e profiling. A documentação oficial do módulo Inspector descreve a API programática, enquanto o guia oficial de debugging do Node.js apresenta formas de conexão.

Para investigar desempenho, veja também Performance Hooks no Node.js e Módulo V8 no Node.js.

Iniciando com –inspect

node --inspect server.js

O processo inicia normalmente e abre uma porta de depuração, geralmente em 127.0.0.1:9229. A aplicação não para automaticamente no começo.

Para alterar a porta:

node --inspect=127.0.0.1:9230 server.js

Prefira vincular ao loopback. Usar 0.0.0.0 expõe a porta em todas as interfaces.

Parando antes da primeira linha

node --inspect-brk server.js

--inspect-brk pausa antes da execução do código do usuário. Isso é útil para investigar inicialização, carregamento de módulos e configuração.

Conectando com Chrome DevTools

No Chrome, abra chrome://inspect, configure o destino e selecione o processo Node.js. O DevTools oferece:

  • breakpoints;
  • step over, step into e step out;
  • watch expressions;
  • console de depuração;
  • CPU profiler;
  • heap snapshots;
  • análise de chamadas assíncronas.

Em produção, não abra a porta diretamente na internet. Use túnel SSH ou uma plataforma de diagnóstico controlada.

Depuração no VS Code

Um arquivo launch.json pode iniciar a aplicação:

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Iniciar API",
      "program": "${workspaceFolder}/src/server.js",
      "envFile": "${workspaceFolder}/.env"
    }
  ]
}

Para anexar a um processo existente:

{
  "type": "node",
  "request": "attach",
  "name": "Anexar ao Node.js",
  "port": 9229,
  "restart": false
}

Evite armazenar segredos diretamente no arquivo de configuração versionado.

Breakpoints no código

function calculateTotal(items) {
  debugger;
  return items.reduce((sum, item) => sum + item.price, 0);
}

A palavra-chave debugger pausa somente quando um cliente de depuração está conectado. Remova breakpoints permanentes antes de liberar código ou controle seu uso por ambiente.

Depurando código assíncrono

O DevTools pode mostrar async stack traces que conectam Promises, timers e callbacks. Mesmo assim, stacks assíncronas podem ficar incompletas em bibliotecas nativas ou abstrações personalizadas.

AsyncLocalStorage ajuda a preservar contexto por requisição. Veja AsyncLocalStorage no Node.js para request IDs e traces.

Abrindo o Inspector em tempo de execução

const inspector = require('node:inspector');

if (process.env.ENABLE_INSPECTOR === 'true') {
  inspector.open(9229, '127.0.0.1', false);
}

O terceiro argumento define se o código deve aguardar um debugger. Ativar isso em produção sem controle pode interromper o serviço.

Obtendo a URL de inspeção

const url = inspector.url();
console.log(url);

A URL contém um identificador de sessão. Trate-a como informação sensível. Não a publique em logs acessíveis a usuários.

Fechando o Inspector

inspector.close();

Quando a investigação terminar, feche a porta. Em ambientes automatizados, aplique um tempo máximo de ativação.

Usando inspector.Session

A classe Session permite enviar comandos do protocolo:

const inspector = require('node:inspector');
const session = new inspector.Session();

session.connect();

session.post('Runtime.enable', error => {
  if (error) console.error(error);
});

Os nomes dos comandos seguem domínios do Chrome DevTools Protocol, como Runtime, Profiler e HeapProfiler.

Promisificando session.post

function post(session, method, params = {}) {
  return new Promise((resolve, reject) => {
    session.post(method, params, (error, result) => {
      if (error) reject(error);
      else resolve(result);
    });
  });
}

Essa função simplifica sequências com async e await.

Coletando perfil de CPU

const fs = require('node:fs/promises');

async function captureCpuProfile(durationMs = 10000) {
  const session = new inspector.Session();
  session.connect();

  try {
    await post(session, 'Profiler.enable');
    await post(session, 'Profiler.start');

    await new Promise(resolve => {
      setTimeout(resolve, durationMs);
    });

    const { profile } = await post(session, 'Profiler.stop');

    await fs.writeFile(
      './cpu-profile.cpuprofile',
      JSON.stringify(profile)
    );
  } finally {
    session.disconnect();
  }
}

O arquivo pode ser aberto no DevTools. Capture durante uma carga representativa e por tempo limitado. Perfis longos geram arquivos maiores e overhead.

Interpretando CPU profiles

Observe funções com alto tempo próprio e total. Uma função pode aparecer muito porque chama outras rotinas caras. Compare:

  • self time;
  • total time;
  • quantidade de amostras;
  • caminhos de chamada;
  • diferenças entre cenários.

Não otimize apenas a função mais visível sem confirmar impacto no throughput ou na latência.

Heap snapshots

Snapshots mostram objetos vivos e referências que os mantêm na memória. É possível gerar um snapshot pelo DevTools ou pelo protocolo:

async function captureHeapSnapshot(filePath) {
  const session = new inspector.Session();
  const fs = require('node:fs');
  const output = fs.createWriteStream(filePath);

  session.connect();

  session.on('HeapProfiler.addHeapSnapshotChunk', message => {
    output.write(message.params.chunk);
  });

  try {
    await post(session, 'HeapProfiler.enable');
    await post(session, 'HeapProfiler.takeHeapSnapshot', {
      reportProgress: false
    });
  } finally {
    output.end();
    session.disconnect();
  }
}

Heap snapshots podem congelar o processo e duplicar temporariamente consumo de memória. Em uma instância próxima do limite, a captura pode causar encerramento.

Dados sensíveis em snapshots

Um snapshot pode conter:

  • tokens;
  • objetos de usuário;
  • conteúdo de requisições;
  • variáveis de ambiente;
  • chaves e configurações;
  • dados mantidos em caches.

Armazene o arquivo com acesso restrito, criptografe durante transporte e apague depois da análise.

Comparando snapshots

Para investigar vazamento, capture:

  1. um snapshot após aquecimento;
  2. execute a carga repetida;
  3. force um período de estabilização;
  4. capture outro snapshot;
  5. compare objetos e retained size.

Objetos crescentes podem ser caches legítimos. Confirme se continuam aumentando sob carga constante.

Sampling heap profiler

O sampling profiler possui overhead menor que snapshots completos e ajuda a descobrir onde alocações acontecem. Ele não mostra todas as referências, mas pode identificar caminhos de criação responsáveis por grande volume.

Inspector e containers

Para depuração local em Docker:

docker run \
  -p 127.0.0.1:9229:9229 \
  -p 3000:3000 \
  app \
  node --inspect=0.0.0.0:9229 server.js

Dentro do container, o processo precisa ouvir em 0.0.0.0, mas a publicação no host deve permanecer em 127.0.0.1. Não publique a porta globalmente.

Port forwarding no Kubernetes

kubectl port-forward pod/api-123 9229:9229

Essa abordagem reduz exposição. Ainda assim, controle permissões de acesso ao cluster e encerre o port-forward depois do diagnóstico.

Debug em Cluster

Cada worker é um processo e precisa de uma porta diferente. Ao iniciar múltiplos workers com a mesma porta de inspeção, podem ocorrer conflitos. É possível derivar a porta do worker ou depurar apenas uma instância.

Veja Cluster no Node.js para entender processos e workers.

Debug em Worker Threads

Worker Threads executam no mesmo processo, mas possuem contextos de execução próprios. Ferramentas modernas podem listar threads e permitir seleção. Para cargas de CPU, consulte Worker Threads no Node.js.

Signals para ativação

Em sistemas Unix, determinados sinais podem ativar o Inspector dependendo da versão e configuração do runtime. Verifique a documentação da versão usada e restrinja quem pode enviar sinais ao processo.

Profiling sem pausar usuários

Em produção, prefira:

  • uma réplica retirada do balanceador;
  • perfil curto;
  • carga controlada;
  • limites de armazenamento;
  • monitoramento de CPU e memória durante a captura;
  • plano de rollback.

Para métricas contínuas, use instrumentação de baixo overhead. O artigo de OpenTelemetry no Node.js apresenta observabilidade distribuída.

Source maps

Aplicações TypeScript ou empacotadas precisam de source maps para mostrar o código original. Configure o compilador e o debugger corretamente. Não publique mapas contendo código sensível em ambientes públicos sem necessidade.

Breakpoints condicionais

Um breakpoint condicional interrompe apenas quando uma expressão é verdadeira, por exemplo:

request.userId === 'test-user'

Use condições simples. Expressões pesadas executadas em alta frequência podem alterar o comportamento observado.

Logpoints

Logpoints registram valores sem modificar o código. Eles são úteis para diagnósticos temporários, mas ainda adicionam custo e podem expor dados. Não registre credenciais ou payloads completos.

Erros comuns

  • Expor 9229 na internet: o processo fica vulnerável a controle remoto.
  • Capturar snapshot sem memória livre: a instância pode ser encerrada.
  • Perfilar por tempo excessivo: overhead e arquivos crescem.
  • Ignorar dados sensíveis: snapshots contêm conteúdo da aplicação.
  • Usar breakpoint em produção ativa: requisições ficam paradas.
  • Depurar todos os workers: portas e custo se multiplicam.
  • Otimizar sem comparar métricas: a mudança pode não melhorar o sistema.

Boas práticas para produção

  • Vincule o Inspector ao loopback.
  • Use túnel autenticado ou port-forward.
  • Ative por tempo limitado.
  • Prefira uma réplica isolada.
  • Monitore overhead durante a coleta.
  • Proteja perfis e snapshots.
  • Remova arquivos depois da análise.
  • Use source maps corretos.
  • Compare antes e depois da correção.
  • Combine profiling com métricas e logs.

Conclusão

O Inspector no Node.js oferece uma visão profunda da execução: breakpoints, pilhas assíncronas, perfis de CPU, alocações e heap snapshots. Ele é uma ferramenta essencial quando logs e métricas mostram o sintoma, mas não revelam a causa.

Essa capacidade exige proteção. Portas restritas, sessões curtas, réplicas isoladas e tratamento seguro dos arquivos reduzem o risco. Com uma investigação controlada e comparação de métricas, o Inspector ajuda a corrigir gargalos e vazamentos com evidências, em vez de suposições.

Os 10 Melhores Cursos de Programação de 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