Bird
Raised Fist0
Node.jsframework~8 mins

Common memory leak patterns in Node.js - Performance & Optimization

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Performance: Common memory leak patterns
HIGH IMPACT
This affects the server's memory usage over time, leading to slower response times and potential crashes.
Managing event listeners in a Node.js server
Node.js
const EventEmitter = require('events');
const emitter = new EventEmitter();

function onRequest(data) {
  console.log('Request received:', data);
}

// Add listener once outside request handler
emitter.on('request', onRequest);

function handleRequest(data) {
  emitter.emit('request', data);
}

handleRequest('data1');
handleRequest('data2');
Listener is added once, preventing buildup and reducing memory usage.
📈 Performance GainMemory remains stable regardless of number of requests.
Managing event listeners in a Node.js server
Node.js
const EventEmitter = require('events');
const emitter = new EventEmitter();

function onRequest(data) {
  console.log('Request received:', data);
}

// Adding listener on every request without removing
function handleRequest(data) {
  emitter.on('request', onRequest);
  emitter.emit('request', data);
}

// Simulate multiple requests
handleRequest('data1');
handleRequest('data2');
Listeners accumulate on the emitter without removal, causing memory to grow indefinitely.
📉 Performance CostMemory usage grows linearly with requests, leading to high memory consumption and possible crashes.
Performance Comparison
PatternMemory UsageGarbage CollectionServer ResponsivenessVerdict
Adding event listeners repeatedlyGrows with requestsIncreases GC frequencyDegrades over time[X] Bad
Adding event listener onceStableMinimal GC impactConsistent[OK] Good
Unbounded global cacheGrows indefinitelyHigh GC overheadSlows server[X] Bad
Limited cache sizeStableLow GC overheadStable performance[OK] Good
Closure capturing large objectsHigh memory retainedGC delayedSlower event loop[X] Bad
Avoid closure captureMemory freed quicklyEfficient GCResponsive server[OK] Good
Rendering Pipeline
Memory leaks in Node.js do not affect browser rendering but impact server responsiveness and stability by increasing memory pressure and garbage collection time.
Memory Allocation
Garbage Collection
Event Loop Responsiveness
⚠️ BottleneckGarbage Collection slows down due to retained unused objects.
Optimization Tips
1Remove event listeners when no longer needed to prevent buildup.
2Limit cache sizes to avoid unbounded memory growth.
3Avoid capturing large objects in closures to allow garbage collection.
Performance Quiz - 3 Questions
Test your performance knowledge
What is a common cause of memory leaks related to event listeners in Node.js?
AUsing global variables for configuration
BUsing asynchronous functions
CAdding event listeners repeatedly without removing them
DWriting synchronous code
DevTools: Node.js --inspect with Chrome DevTools (Memory panel)
How to check: 1. Run Node.js with --inspect flag. 2. Open Chrome and navigate to chrome://inspect. 3. Connect to your Node.js process. 4. Use the Memory tab to take heap snapshots before and after operations. 5. Compare snapshots to find retained objects and leaks.
What to look for: Look for objects that grow in number or size over time without being released, indicating memory leaks.

Practice

(1/5)
1. Which of the following is a common cause of memory leaks in Node.js applications?
easy
A. Keeping references to objects that are no longer needed
B. Using asynchronous functions
C. Writing synchronous code
D. Using the latest Node.js version

Solution

  1. Step 1: Understand what causes memory leaks

    Memory leaks happen when your program holds onto data it no longer needs, preventing the system from freeing memory.
  2. Step 2: Identify the correct cause among options

    Keeping references to unused objects prevents garbage collection, causing leaks. Other options do not inherently cause leaks.
  3. Final Answer:

    Keeping references to objects that are no longer needed -> Option A
  4. Quick Check:

    Memory leaks = unused references [OK]
Hint: Memory leaks happen when unused data is still referenced [OK]
Common Mistakes:
  • Thinking async code always causes leaks
  • Confusing synchronous code with leaks
  • Assuming Node.js version causes leaks
2. Which syntax correctly removes an event listener in Node.js to help prevent memory leaks?
easy
A. emitter.deleteListener('event', callback);
B. emitter.off('event');
C. emitter.remove('event', callback);
D. emitter.removeListener('event', callback);

Solution

  1. Step 1: Recall Node.js event listener removal syntax

    The correct method to remove a specific listener is removeListener(event, callback).
  2. Step 2: Check each option's validity

    emitter.removeListener('event', callback); uses the correct method. emitter.off('event'); removes all listeners but omits the specific callback. Options A and C are not valid methods.
  3. Final Answer:

    emitter.removeListener('event', callback); -> Option D
  4. Quick Check:

    Correct method = removeListener(event, callback) [OK]
Hint: Use removeListener with event and callback to remove listeners [OK]
Common Mistakes:
  • Using emitter.off without callback
  • Using non-existent methods like remove or deleteListener
  • Omitting the callback function
3. Consider this code snippet:
const cache = {};
function addToCache(key, value) {
  cache[key] = value;
}
addToCache('user1', {name: 'Alice'});
addToCache('user2', {name: 'Bob'});
console.log(Object.keys(cache).length);

What will be the output and what memory issue might this cause if keys are never removed?
medium
A. 0; No memory leak because cache is empty
B. 2; Memory leak due to unbounded cache growth
C. Error; Syntax error in code
D. Undefined; cache is not defined

Solution

  1. Step 1: Analyze the code output

    The cache object stores two keys: 'user1' and 'user2'. Object.keys(cache).length returns 2.
  2. Step 2: Identify memory issue

    Since keys are never removed, cache grows indefinitely, causing a memory leak.
  3. Final Answer:

    2; Memory leak due to unbounded cache growth -> Option B
  4. Quick Check:

    Cache size = 2, leak if keys never removed [OK]
Hint: Uncleared caches cause leaks; count keys to check size [OK]
Common Mistakes:
  • Thinking cache is empty initially
  • Assuming syntax error without checking code
  • Confusing undefined with empty object
4. You have this code causing a memory leak:
const listeners = [];
function addListener(emitter, callback) {
  emitter.on('data', callback);
  listeners.push({emitter, callback});
}
// Later you forget to remove listeners

What is the best fix to prevent the leak?
medium
A. Remove listeners with emitter.removeListener and clear the listeners array
B. Do nothing; Node.js cleans up automatically
C. Replace emitter.on with emitter.once
D. Use global variables instead of arrays

Solution

  1. Step 1: Identify cause of leak

    Listeners are added and stored in an array but never removed, causing memory to stay used.
  2. Step 2: Apply fix to remove listeners and clear references

    Use emitter.removeListener with stored callbacks and clear the listeners array to free memory.
  3. Final Answer:

    Remove listeners with emitter.removeListener and clear the listeners array -> Option A
  4. Quick Check:

    Remove listeners + clear refs = fix leak [OK]
Hint: Always remove event listeners and clear stored references [OK]
Common Mistakes:
  • Assuming Node.js auto-cleans listeners
  • Using emitter.once without removing listeners
  • Using global variables increases leaks
5. You have a Node.js app caching user sessions in a global object. Over time, memory usage grows unexpectedly. Which combined approach best prevents this memory leak?
hard
A. Use global variables for caching without cleanup
B. Store all sessions indefinitely to avoid losing data
C. Implement session expiration and remove expired sessions from cache regularly
D. Avoid using any caching to prevent leaks

Solution

  1. Step 1: Understand the problem with indefinite caching

    Storing sessions forever causes the cache to grow without limit, leading to memory leaks.
  2. Step 2: Apply session expiration and cleanup

    Removing expired sessions regularly frees memory and prevents leaks while keeping useful data.
  3. Final Answer:

    Implement session expiration and remove expired sessions from cache regularly -> Option C
  4. Quick Check:

    Expire and clean cache to prevent leaks [OK]
Hint: Expire and clear cached data regularly to avoid leaks [OK]
Common Mistakes:
  • Keeping all data forever causes leaks
  • Avoiding caching is not practical
  • Using globals without cleanup worsens leaks