Back to 20 Concepts
foundations • Intermediate
EventEmitter Internals & MaxListenersExceeded Warnings
EventEmitter is the cornerstone of Node.js networking and streams. Registering listeners without cleanup leads to silent memory leaks when objects retain closure references.
Intuitive Mental Model
The Megaphone & Crowd: If 50 people register to listen to the megaphone and never leave when the announcement ends, the room becomes dangerously crowded (memory leak).
Node.js ESM / CJS ImplementationNode.js v22 LTS
import { EventEmitter } from 'events';
const emitter = new EventEmitter();
// Default warning limit is 10 listeners:
emitter.setMaxListeners(20);
function onUserLogin(user: { id: string }) {
console.log('User logged in:', user.id);
}
// Subscribe:
emitter.on('login', onUserLogin);
// Always unsubscribe when teardown occurs to prevent leaks:
emitter.off('login', onUserLogin);
// Modern AbortSignal cleanup:
const controller = new AbortController();
emitter.on('data', () => {}, { signal: controller.signal });
controller.abort(); // Automatically removes listener!Key Architectural Takeaways
- •MaxListenersExceededWarning indicates potential memory leak from unremoved event listeners.
- •Use EventEmitter once() for single-use events to auto-remove the listener.
- •Node.js v16+ supports AbortSignal in emitter.on(event, fn, { signal }) for declarative teardown.
Common Production Mistake
Adding anonymous callback listeners inside request handlers without removing them: req.on("close", () => ...), leaking 1 closure per HTTP request.
Recommended Solution
Use once("close") or extract to named functions and remove with emitter.off().