Introduction

Node.js EventEmitters warn when more than 10 listeners are attached to a single event. This default limit catches a common memory leak pattern where listeners are added repeatedly (e.g., inside a loop or on every request) without being removed, causing the emitter to hold references that prevent garbage collection.

This warning often indicates a design issue where event listeners are being registered in the wrong scope or lifecycle.

Symptoms

  • Console shows "(node:1234) MaxListenersExceededWarning: Possible EventEmitter memory leak detected"
  • "11 listeners added to [emitter]. Use emitter.setMaxListeners() to increase limit"
  • Memory usage grows over time as listeners accumulate

Common Causes

  • Adding event listener inside a loop or request handler without removing it
  • Re-subscribing to events on reconnection without cleaning up old listeners
  • Global or singleton EventEmitter accumulating listeners from multiple modules

Step-by-Step Fix

  1. 1.Remove listeners when they are no longer needed: Clean up after yourself.
  2. 2.```javascript
  3. 3.const EventEmitter = require('events');
  4. 4.const emitter = new EventEmitter();

// BAD: listener added every time, never removed function handleRequest(req) { emitter.on('data', (data) => { res.write(data); // Accumulates on every request }); }

// GOOD: listener removed after use function handleRequest(req) { const handler = (data) => res.write(data); emitter.on('data', handler); res.on('end', () => { emitter.off('data', handler); }); } ```

  1. 1.Use once() for single-fire events: Automatically removes the listener after firing.
  2. 2.```javascript
  3. 3.const EventEmitter = require('events');
  4. 4.const emitter = new EventEmitter();

// BAD: emitter.on('ready', () => { console.log('Ready!'); // This listener stays forever even though it fired once });

// GOOD: emitter.once('ready', () => { console.log('Ready!'); // Listener automatically removed after first fire }); ```

  1. 1.Find and fix the leaking listener: Use emitter.listeners() to debug.
  2. 2.```javascript
  3. 3.const EventEmitter = require('events');

// Track listener additions: const emitter = new EventEmitter(); emitter.on('newListener', (event, listener) => { const count = emitter.listenerCount(event); if (count > 5) { console.warn(Warning: ${count} listeners on event '${event}'); console.trace('Listener added from:'); } });

// List all listeners for an event: console.log(emitter.listeners('data')); ```

Prevention

  • Use once() instead of on() for events that only need to fire once
  • Always pair listener addition with removal in cleanup code
  • Monitor emitter.listenerCount() in production for key events
  • Consider using AbortController signals for automatic listener cleanup