Memory Management & Debugging
Understand Node.js memory management, garbage collection, memory leak prevention, and advanced debugging techniques for production applications. This is a foundational concept in server-side JavaScript development that professional developers rely on daily. The explanations below are written to be beginner-friendly while covering the depth and nuance that comes from real-world Node.js experience. Take your time with each section and practice the examples
Memory Management Basics
Node.js uses V8's garbage collector to manage memory. Understanding heap vs stack, memory leaks, and how to profile memory usage is critical for building stable production applications.. This is an essential concept that every Node.js developer must understand thoroughly. In professional development environments, getting this right can mean the difference between code that works reliably and code that breaks in production. The following sections break this down into clear, digestible pieces with practical examples you can try immediately
Common Memory Leak Sources
- Global variables: Unintentional global scope pollution
- Event listeners: Not removing listeners when done
- Closures: Holding references to large objects
- Timers: setInterval without clearInterval
- Circular references: Objects referencing each other
- Caches: Unbounded cache growth
Memory Leak Prevention
// Memory Leak Examples and Fixes
// BAD: Event listener leak
class BadServer {
constructor() {
this.connections = [];
}
addConnection(socket) {
this.connections.push(socket);
// Listener never removed!
socket.on('data', (data) => this.handleData(data));
}
}
// GOOD: Proper cleanup
class GoodServer {
constructor() {
this.connections = new Map();
}
addConnection(socket) {
const handler = (data) => this.handleData(data);
socket.on('data', handler);
this.connections.set(socket, handler);
socket.on('close', () => {
// Clean up listener on disconnect
socket.off('data', handler);
this.connections.delete(socket);
console.log('Connection cleaned up');
});
}
}
// BAD: Unbounded cache
const cache = {};
function badCache(key, value) {
cache[key] = value; // Grows forever!
}
// GOOD: LRU Cache with size limit
class LRUCache {
constructor(maxSize = 100) {
this.cache = new Map();
this.maxSize = maxSize;
}
get(key) {
if (!this.cache.has(key)) return null;
const value = this.cache.get(key);
// Move to end (most recently used)
this.cache.delete(key);
this.cache.set(key, value);
return value;
}
set(key, value) {
if (this.cache.has(key)) {
this.cache.delete(key);
} else if (this.cache.size >= this.maxSize) {
// Delete least recently used (first item)
const firstKey = this.cache.keys().next().value;
this.cache.delete(firstKey);
}
this.cache.set(key, value);
}
}
// Monitor memory usage
function monitorMemory() {
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(monitorMemory, 5000);Try It Yourself — Node.js Patterns Playground
Line 159: Malformed tag: "< 1000; i++) { allocatedObjects.push({ id: i, data: new Array(100).fill(Math.random()) }); } objCount += 1000; updateMetrics(); } function freeMemory() { allocatedObjects = []; objCount = 0; updateMetrics(); } function updateMetrics() { document.getElementById('objCount').textContent = objCount.toLocaleString(); document.getElementById('evtCount').textContent = evtCount; document.getElementById('heapUsed').textContent = Math.round(objCount * 0.8 / 1000) + ' KB (est)'; } updateMetrics(); </script>"
Tip: Tags must use valid HTML names and be properly formed. Example: <div>, <p class="text">
Line 176: Wrong closing tag: </body> found, expected </script> (line 176)
Tip: Close <script> (opened on line 59) with </script> before closing </body>.
Line 177: Wrong closing tag: </html> found, expected </script> (line 177)
Tip: Close <script> (opened on line 59) with </script> before closing </html>.
Line 2: Unclosed <html> (opened on line 2)
Tip: Add </html> to properly close this element.
Line 18: Unclosed <body> (opened on line 18)
Tip: Add </body> to properly close this element.
Line 59: Unclosed <script> (opened on line 59)
Tip: Add </script> to properly close this element.