DEV Community

Atlas Whoff
Atlas Whoff

Posted on

Node.js Performance: Profiling and Fixing Memory Leaks

Node.js Performance: Profiling and Fixing Memory Leaks

Memory leaks in Node.js are insidious. The process memory grows slowly until it crashes, usually at 3am.

Common Causes

  1. Global variables accumulating data — caches without eviction
  2. Event listeners not removed — registering without cleanup
  3. Closures holding references — callbacks capturing scope
  4. Timers not cleared — setInterval never cancelled

Diagnosing With --inspect

node --inspect dist/server.js
# Open Chrome DevTools → chrome://inspect → Memory tab
# Take heap snapshots before/after load to find growing objects
Enter fullscreen mode Exit fullscreen mode

The Most Common Leak: Unbounded Cache

// Leaking: grows forever
const cache = new Map<string, Data>();
function getData(key: string) {
  if (!cache.has(key)) cache.set(key, fetchData(key));
  return cache.get(key);
}

// Fixed: bounded with LRU eviction
import LRU from 'lru-cache';
const cache = new LRU<string, Data>({ max: 500, ttl: 1000 * 60 * 5 });
Enter fullscreen mode Exit fullscreen mode

Event Listener Cleanup

// Leaking: new listener added on every request
app.get('/stream', (req, res) => {
  process.on('SIGTERM', () => res.end()); // Never cleaned up!
});

// Fixed: cleanup on connection close
app.get('/stream', (req, res) => {
  const cleanup = () => res.end();
  process.on('SIGTERM', cleanup);
  req.on('close', () => process.off('SIGTERM', cleanup));
});
Enter fullscreen mode Exit fullscreen mode

Memory Monitoring in Production

setInterval(() => {
  const mem = process.memoryUsage();
  metrics.gauge('memory.heap_used', mem.heapUsed);
  metrics.gauge('memory.heap_total', mem.heapTotal);
  metrics.gauge('memory.rss', mem.rss);

  // Alert if heap is growing consistently
  if (mem.heapUsed / mem.heapTotal > 0.85) {
    alerts.warn('High heap usage', { usage: mem.heapUsed });
  }
}, 30000);
Enter fullscreen mode Exit fullscreen mode

Automatic Heap Dumps on OOM

node --max-old-space-size=512 \
     --heapsnapshot-signal=SIGUSR2 \
     dist/server.js
# Send SIGUSR2 to get a heap snapshot without crashing
Enter fullscreen mode Exit fullscreen mode

Production monitoring, memory alerting, and observability tooling are baked into the AI SaaS Starter Kit — ship with visibility from day one.

Top comments (0)