quinta-feira, 24 de setembro de 2026 · Edição online
Digitorack
Digitorack

Memory leak Node.js: como debugar em 7 passos

ResumoMemory leak em Node.js é um problema crítico que derruba aplicações em produção. O guia apresenta um procedimento de 7 passos para depuração, utilizando o depurador nativo do Node.js, snapshots de heap e monitoramento contínuo. A abordagem é prática e direta, sem teoria vaga, focando exclusivamente na identificação da causa raiz do vazamento de memória.

Memory leak em Node.js derruba apps em produção. Este guia mostra, passo a passo, como usar o depurador nativo, snapshots e monitoramento para achar a causa. Sem teoria vaga, só procedimento.

Letícia Sampaio Khoury Letícia Sampaio Khoury · Editora de Gadgets e Consumo Tech
· · 6 min de leitura
Memory leak Node.js: como debugar em 7 passos
Foto: Imagem ilustrativa · Digitorack

Memory leak em Node.js derruba apps em produção. Este guia mostra, passo a passo, como usar o depurador nativo, snapshots e monitoramento para achar a causa. Sem teoria vaga, só procedimento.

Memory leak em Node.js não aparece no monitoramento básico. Ele cresce devagar, até a aplicação começar a trocar memória por disco e o processo morrer com OOM. O objetivo deste guia é fazer você achar a causa raiz em produção, não só no ambiente local. Para isso, você vai usar o depurador nativo do V8, heap snapshots e uma rotina de comparação. Pré-requisito: Node.js 14 ou superior, acesso ao processo em produção (ou um dump de memória) e um pouco de paciência. Você não vai precisar de bibliotecas externas para o diagnóstico inicial.

Passo 1: Confirme que é leak, não pico de memória

O primeiro erro é tratar qualquer crescimento como leak. Um pico de memória pode ser normal, por exemplo, após um batch de processamento. Para separar as coisas, monitore o heap ao longo de horas, não minutos. Use process.memoryUsage() em intervalos regulares e registre os valores.

setInterval(() => { const mem = process.memoryUsage(); console.log(JSON.stringify({ heapUsed: mem.heapUsed, heapTotal: mem.heapTotal, rss: mem.rss })); }, 30000);

Se o heapUsed sobe e desce, é pico. Se ele só sobe e nunca retorna ao patamar anterior, você tem um leak. Dica: registre o rss também, pois em alguns casos o heap fica estável, mas a memória total cresce por buffers externos ao V8. Erro comum: olhar só o heap e ignorar o rss.

Passo 2: Capture o primeiro heap snapshot

O V8 tem um depurador embutido que permite tirar snapshots sem parar o processo. Inicie sua aplicação com node --inspect (ou --inspect-brk se precisar pausar no início) e abra chrome://inspect no Chrome. Você vai ver o alvo listado.

Clique em "Heap Snapshot" e tire uma amostra. Salve o arquivo .heapsnapshot com a data e hora no nome. Esse é seu ponto de referência. Dica: em produção, você pode usar kill -SIGUSR1 <pid> para habilitar o inspector sem reiniciar o processo, desde que a aplicação não tenha desabilitado o sinal. Erro comum: tirar o snapshot só depois que a memória já está alta, sem um baseline.

Passo 3: Deixe o leak se manifestar

Aqui entra a parte que exige tempo. Deixe a aplicação rodar sob carga real ou com um script de stress que reproduza as operações comuns. O leak precisa se manifestar de forma mensurável. Espere o heap crescer pelo menos 30% acima do baseline antes de tirar o segundo snapshot.

Se você não conseguir esperar em produção, configure um ambiente de staging com o mesmo tráfego. Dica: use um script que execute as mesmas chamadas de API que seus usuários fazem, em loop. Erro comum: tirar o segundo snapshot cedo demais, quando a diferença ainda é ruído estatístico.

Passo 4: Compare os snapshots

Com o Chrome DevTools aberto, carregue o primeiro snapshot e depois o segundo. Use a opção "Comparison" na lista de snapshots. A ferramenta mostra objetos que foram criados e não coletados, e o tamanho retido.

Filtre por objetos que cresceram em número e em tamanho. Por exemplo, se você vê milhares de Closure ou Array a mais, o problema está em funções que capturam escopo ou em listas que nunca são esvaziadas. Dica: foque nos retained size, não no shallow size. Um objeto pequeno pode reter uma árvore inteira. Erro comum: ignorar closures, achando que são inofensivas.

Passo 5: Analise a cadeia de retenção

Para cada objeto suspeito, clique nele e veja a aba "Retainers". Ela mostra o caminho que mantém o objeto vivo, desde a raiz do GC. O caminho tipicamente termina em um módulo, um setTimeout, um listener ou uma variável global.

Se o retainer é um EventEmitter ou um setInterval, o problema é um listener que não foi removido ou um timer que não foi limpo. Se é uma variável global, o problema é acúmulo de dados em cache. Dica: procure por window ou global na cadeia, pois isso indica vazamento para o escopo global. Erro comum: achar que o leak é de uma biblioteca, quando na verdade é do seu código que segura referências.

Passo 6: Teste a correção e repita

Depois de identificar a causa, aplique a correção. Isso pode ser remover um removeListener, limpar um array após uso, ou usar WeakRef para caches que não precisam ser fortes. Rode o mesmo script de stress de novo e monitore o heap.

O heap deve subir até um patamar e estabilizar. Se ele continuar subindo, a correção foi parcial. Repita o processo de snapshot e comparação até a linha ficar plana. Dica: crie um teste de integração que rode 10 mil requisições e verifique se o heap não cresce mais que 5% após o aquecimento. Erro comum: corrigir um leak e não testar com o mesmo volume de carga.

Passo 7: Automatize o monitoramento

Leak que não é monitorado volta. Configure um alerta que rode a cada hora e compare o heap com o baseline. Você não precisa de uma ferramenta cara, um script com process.memoryUsage() já resolve.

const baseline = { heapUsed: 0, rss: 0 }; // compare e alerte se heapUsed > baseline * 1.2

Dica: use um serviço de métricas como Prometheus ou Datadog, mas se não tiver, um cron com log já é suficiente. Erro comum: desligar o monitoramento depois de corrigir, achando que o problema não volta.

Checklist rápido

Antes de encerrar, confira se você:

  • Confirmou que é leak, não pico.
  • Capturou snapshot baseline.
  • Deixou o leak se manifestar sob carga.
  • Comparou os snapshots no DevTools.
  • Identificou a cadeia de retenção.
  • Aplicou a correção e validou.
  • Automatizou o monitoramento.

FAQ

Como saber se minha aplicação Node.js tem memory leak?

Monitore o heap com process.memoryUsage() por algumas horas. Se o heap cresce continuamente e não retorna ao patamar inicial após a carga, há leak. Um pico temporário que volta ao normal não é leak.

Qual a diferença entre heap snapshot e heap dump?

Heap snapshot é uma foto do estado da memória em um momento, capturada pelo V8. Heap dump é termo genérico para qualquer coleta de dados de memória. No Node.js, o snapshot é o formato .heapsnapshot que o Chrome DevTools lê.

O que causa memory leak em Node.js?

As causas comuns são variáveis globais não limpas, listeners de eventos não removidos, timers não cancelados, caches que crescem sem limite e closures que capturam escopo externo. Também pode ocorrer ao usar a API Fetch sem ler o corpo da resposta.

Como usar o Chrome DevTools para debugar Node.js?

Inicie o Node com --inspect, abra chrome://inspect e clique no alvo. Na aba "Memory", você pode tirar snapshots e comparar. A análise de retenção mostra o caminho que mantém objetos vivos.

Memory leak pode causar queda do processo?

Sim. Quando a memória atinge o limite do container ou do sistema, o Node.js lança um erro OOM e o processo morre. O monitoramento preventivo evita quedas em produção.

Preciso de biblioteca externa para debugar leak?

Não. O depurador nativo do V8 e o Chrome DevTools são suficientes. Bibliotecas como heapdump são úteis para capturar snapshots em produção sem o inspector, mas o diagnóstico pode ser feito com as ferramentas nativas.

Compartilhar:
Letícia Sampaio Khoury

Letícia Sampaio Khoury

Editora de Gadgets e Consumo Tech

Testa o gadget no dia a dia real, avalia se vale a grana sem deslumbre de novidade.

Ver todos os artigos →

Leia também

Validação de Dados: 11 Bibliotecas Mais Usadas
Apps e Software

Validação de Dados: 11 Bibliotecas Mais Usadas

Validar dados antes de gravar ou exibir evita retrabalho e falhas de segurança. Listamos 11 bibliotecas de validação de dados com critérios concretos para você escolher a melhor para cada linguagem e contexto.

17 de setembro de 2026 · Camila Bressane Drumond
GraphQL Subscriptions: Guia Passo a Passo Prático
Apps e Software

GraphQL Subscriptions: Guia Passo a Passo Prático

Implementar GraphQL subscriptions assusta menos do que parece. Neste guia passo a passo, mostro como configurar o servidor, escolher o pubsub certo e conectar o cliente, com os erros que eu mesmo cometi no caminho.

17 de setembro de 2026 · Letícia Sampaio Khoury
Consultar placa de carro: comprar às cegas x com dados
Apps e Software

Consultar placa de carro: comprar às cegas x com dados

Comprar carro sem checar a placa é apostar no escuro. Veja o que a tecnologia de consulta veicular mostra e como isso muda a negociação.

16 de setembro de 2026 · Redação

Gostou? Receba mais análises

Newsletter quinzenal · curadoria editorial · sem spam