Advanced Node.js Interview QuestionsAdvancedConcept
Node.js · Question 72
What causes memory leaks in Node.js applications?
Direct answer
Common leaks: global caches without eviction, orphaned event listeners, closures holding request scope, timers never cleared, unbounded in-memory queues — detect with heap snapshots, process.memoryUsage, and clinic/Chrome DevTools; fix by removing listeners, TTL caches, and streaming large data.
Node processes are long-lived — small per-request leaks compound into OOM kills under PM2/Docker restart loops. Production APIs need observability on heap growth.
Why interviewers ask
| Cause | Example | Fix |
|---|---|---|
| Global array/map growth | cache[key] = res without TTL | LRU cache with max size |
| Event listeners | bus.on in every request (Q57) | off/once, scoped emitters |
| Closures | Handler captures huge req.body forever | Clear refs after response |
| Timers | setInterval never cleared | clearInterval on shutdown |
| Detached buffers | Accumulating chunks without end | Use pipeline, destroy streams |
- process.memoryUsage() — rss, heapUsed, external — log periodically in staging.
- Heap snapshot — node --inspect, compare snapshots before/after load test.
- WeakRef / WeakMap — optional for caches when GC should reclaim entries.
memory-leak-fix.mjs
import { LRUCache } from "lru-cache";
const topicCache = new LRUCache({
max: 500,
ttl: 1000 * 60 * 10, // 10 min
});
function getCachedTopic(slug) {
if (topicCache.has(slug)) return topicCache.get(slug);
const topic = loadTopic(slug);
topicCache.set(slug, topic);
return topic;
}
// Anti-pattern: globalLeaks.push(everyResponsePayload)