🌐 Detecting your location…
📢 Advertisement — Configure AdSense in Appearance → Customize → AdSense Settings

Como depurar vazamentos de memória em Node.js: guia passo a passo completo 2026

⏱️6 min read  ·  1,301 words

{
“@context”: “https://schema.org”,
“@type”: “TechArticle”,
“headline”: “Como depurar vazamentos de memória em Node.js: guia passo a passo completo 2026”,
“description”: “Diagnosticar e corrigir vazamentos de memória do Node.js usando Chrome DevTools, clinic.js e sinalizador –inspect. Abrange padrões de vazamento comuns com exemplos de código reais.”,
“url”: “https://techpulsesite.com/how-to-debug-memory-leaks-in-node-js-com-pt/”,
“datePublished”: “2026-06-28T16:35:00+00:00”,
“dateModified”: “2026-06-29T04:14:14+00:00”,
“author”: {
“@type”: “Organization”,
“name”: “TechPulse Editorial Team”,
“url”: “https://techpulsesite.com”
},
“publisher”: {
“@type”: “Organization”,
“name”: “TechPulse”,
“url”: “https://techpulsesite.com”
},
“inLanguage”: “pt”
}

{
“@context”: “https://schema.org”,
“@type”: “TechArticle”,
“headline”: “Como depurar vazamentos de memória em Node.js: guia passo a passo completo 2026”,
“description”: “Diagnosticar e corrigir vazamentos de memória do Node.js usando Chrome DevTools, clinic.js e sinalizador –inspect. Abrange padrões de vazamento comuns com exemplos de código reais.”,
“url”: “https://techpulsesite.com/how-to-debug-memory-leaks-in-node-js-com-pt/”,
“datePublished”: “2026-06-28T16:35:00+00:00”,
“dateModified”: “2026-06-28T18:23:22+00:00”,
“author”: {
“@type”: “Organization”,
“name”: “TechPulse Editorial Team”,
“url”: “https://techpulsesite.com”
},
“publisher”: {
“@type”: “Organization”,
“name”: “TechPulse”,
“url”: “https://techpulsesite.com”
},
“inLanguage”: “pt”
}

Um Node.jsvazamento de memória faz com que seu processo consuma gradualmente mais RAM até travar comFATAL ERROR: Reached heap limit ou fica muito lento para atender solicitações. Na produção, isso geralmente se manifesta como reinicializações semanais do servidor ou tempos de resposta degradantes. Veja como encontrá-los e corrigi-los.

O que é um vazamento de memória no Node.js?

Um vazamento de memória ocorre quando os objetos são alocados na memória, mas nunca são liberados — porque algo ainda mantém uma referência a eles, impedindo a coleta de lixo. Causas comuns: variáveis globais acumulando dados, ouvintes de eventos nunca removidos, encerramentos que capturam objetos grandes, caches que crescem ilimitadamente e retornos de chamada de temporizador contendo referências a objetos.

Etapa 1: confirme se há vazamento de memória

// Monitor memory usage in your application
function logMemory() {
  const used = process.memoryUsage();
  console.log({
    heapUsed:   `${Math.round(used.heapUsed / 1024 / 1024)}MB`,
    heapTotal:  `${Math.round(used.heapTotal / 1024 / 1024)}MB`,
    rss:        `${Math.round(used.rss / 1024 / 1024)}MB`,
    external:   `${Math.round(used.external / 1024 / 1024)}MB`,
  });
}

setInterval(logMemory, 5000);  // log every 5 seconds under load

Execute testes de carga e observe os números. SeheapUsed cresce continuamente e nunca cai após os ciclos de GC, há um vazamento.

Etapa 2: Use –inspect + Chrome DevTools

# Start Node with inspector
node --inspect app.js
# or for existing process
kill -USR1 <PID>

Abra o Chrome e navegue atéchrome://inspect. Clique em “Abrir DevTools dedicados para Node”. Na guia Memória, tire um instantâneo de heap, gere carga, aguarde 60 segundos e tire outro instantâneo. Compare-os:

No segundo instantâneo, selecione “Comparação” no menu suspenso. Classifique por “Tamanho Delta” – os objetos que crescem mais rapidamente são os candidatos a vazamento.

Etapa 3: Use clinic.js para diagnóstico automático

npm install -g clinic

# Run your app under clinic
clinic doctor -- node app.js

# More detailed heap analysis
clinic heapprofiler -- node app.js

# Flame graph for CPU + memory
clinic flame -- node app.js

Clinic gera um relatório HTML mostrando o crescimento da memória ao longo do tempo, identifica intervalos problemáticos e muitas vezes aponta diretamente para o padrão de código vazado.

Padrão de vazamento comum 1: ouvintes de eventos não removidos

// 🐛 Bug: listener added but never removed
class DataProcessor {
  constructor(emitter) {
    emitter.on('data', this.processData.bind(this));
    // When DataProcessor is destroyed, emitter still holds reference
    // → DataProcessor and its data are never GC'd
  }
}

// ✅ Fix: remove listener when done
class DataProcessor {
  constructor(emitter) {
    this.emitter = emitter;
    this.handler = this.processData.bind(this);
    emitter.on('data', this.handler);
  }

  destroy() {
    this.emitter.off('data', this.handler);  // cleanup
  }
}

// Check for listener leaks (Node warns at 11+ listeners)
emitter.setMaxListeners(20);  // raise limit if legitimately needed
console.log(emitter.listenerCount('data'));  // monitor count

Padrão de vazamento comum 2: cache ou mapa ilimitado

// 🐛 Bug: cache grows forever
const cache = new Map();
function getCachedData(key) {
  if (!cache.has(key)) {
    cache.set(key, fetchFromDB(key));  // never evicted
  }
  return cache.get(key);
}

// ✅ Fix: bounded LRU cache
const LRU = require('lru-cache');
const cache = new LRU({ max: 1000, ttl: 1000 * 60 * 5 });  // 5-min TTL, max 1000 entries

// Or simple manual TTL approach
const cache = new Map();
function getCachedData(key) {
  const entry = cache.get(key);
  if (entry && Date.now() - entry.time < 300000) {
    return entry.data;
  }
  const data = fetchFromDB(key);
  cache.set(key, { data, time: Date.now() });
  // Evict old entries periodically
  if (cache.size > 1000) cache.delete(cache.keys().next().value);
  return data;
}

Padrão de vazamento comum 3: fechamentos capturando objetos grandes

// 🐛 Bug: closure keeps large data alive
function processLargeFile(data) {
  const hugeBuffer = Buffer.alloc(100 * 1024 * 1024); // 100MB
  hugeBuffer.copy(data);

  return function processChunk(chunk) {
    // This closure captures hugeBuffer — stays in memory as long as
    // processChunk function exists, even if we only need one small field
    return hugeBuffer.slice(0, 10);
  };
}

// ✅ Fix: extract only what you need before creating closure
function processLargeFile(data) {
  const hugeBuffer = Buffer.alloc(100 * 1024 * 1024);
  hugeBuffer.copy(data);
  const needed = hugeBuffer.slice(0, 10);  // extract needed data
  // hugeBuffer can now be GC'd — closure only captures 'needed'
  return function processChunk(chunk) {
    return needed;
  };
}

Padrão de vazamento comum 4: setInterval sem clearInterval

// 🐛 Bug: interval keeps closure alive forever
function startWorker(data) {
  const interval = setInterval(() => {
    process(data);  // data never released because interval holds it
  }, 1000);
  // interval never cleared when worker is "stopped"
}

// ✅ Fix: always clear intervals
function startWorker(data) {
  const interval = setInterval(() => {
    process(data);
  }, 1000);

  return function stop() {
    clearInterval(interval);  // release the closure reference
  };
}

Etapa 4: Análise de Heap Dump com heapdump

npm install heapdump

// In your app — trigger a dump on SIGUSR2
const heapdump = require('heapdump');
process.on('SIGUSR2', () => {
  heapdump.writeSnapshot((err, filename) => {
    console.log('Heap snapshot written to', filename);
  });
});

// Trigger from terminal
kill -USR2 <PID>

Abra o arquivo .heapsnapshot no Chrome DevTools (guia Memória → Carregar → Selecionar arquivo). Filtre por objetos que você suspeita. Procure objetos com alto “Tamanho Retido” – essa é a memória mantida viva por esse objeto.

Perguntas Frequentes

P: Qual é a diferença entre heapUsed e RSS?
A: heapUsed é a memória heap JavaScript V8. RSS (Resident Set Size) é a memória total do processo, incluindo buffers nativos, código e heap. Um RSS crescente sem aumentar o heapUsed sugere um vazamento de módulo nativo.

P: Posso forçar o teste da coleta de lixo?
R: Sim:node --expose-gc app.js então ligueglobal.gc(). Se a memória cair significativamente após a GC manual, mas crescer novamente, você confirmou um vazamento de produção.

P: Como detecto vazamentos na produção?
R: Use ferramentas APM: Datadog, New Relic ou Elastic APM monitoram o crescimento do heap ao longo do tempo. Defina alertas com 80% de uso de heap. Considere também--max-old-space-size=512 para limitar o heap e falhar rapidamente, em vez de degradação lenta.

P: WeakMap/WeakRef é útil para prevenir vazamentos?
R: Sim. WeakMap eWeakSet mantenha referências fracas — se o objeto-chave não tiver outras referências, ele será elegível para GC mesmo que seja uma chave em um WeakMap. Útil para armazenar em cache metadados sobre objetos sem impedir sua coleta.

P: Qual é um bom tamanho máximo de heap para Node.js?
R: O padrão é ~1,5 GB (64 bits). Defina explicitamente com--max-old-space-size=2048 (2GB). Dimensione para 70-80% da RAM disponível, deixando espaço para o sistema operacional e outros processos.

Conclusão

Vazamentos de memória do Node.js são diagnosticáveis e corrigíveis com as ferramentas certas. O fluxo de trabalho:confirme o vazamento com registro de memória → isole com instantâneos de heap do Chrome DevTools → identifique o padrão (ouvinte, cache, fechamento, cronômetro) → corrija e verifique. Os quatro padrões neste guia são responsáveis por 90% dos vazamentos de memória de produção. Em caso de dúvida, clinic.js indicará a direção certa em poucos minutos.

✍️ Leave a Comment

Your email address will not be published. Required fields are marked *

🌐 Read in:🇩🇪 Deutsch🇧🇷 Português🇸🇦 العربية🇮🇳 हिन्दी🇧🇩 বাংলা