# Session: Memory Leak Investigation
**Date:** 2026-01-17
**Started:** 09:00
**Last Updated:** 12:00

---

## Current State

Investigating memory leak in production. Heap growing unbounded over 24h period.

### Completed
- [x] Set up heap snapshots in staging
- [x] Identified leak source: event listeners not being cleaned up
- [x] Fixed leak in WebSocket handler
- [x] Verified fix with 4h soak test

### Root Cause
WebSocket `onMessage` handlers were being added on reconnect but not removed on disconnect. After ~1000 reconnects, memory grew from 200MB to 2GB.

### The Fix
```javascript
// Before (leaking)
socket.on('connect', () => {
  socket.on('message', handleMessage)
})

// After (fixed)
socket.on('connect', () => {
  socket.off('message', handleMessage) // Remove old listener first
  socket.on('message', handleMessage)
})

// Even better - use once or cleanup on disconnect
socket.on('disconnect', () => {
  socket.removeAllListeners('message')
})
```

### Debugging Technique Worth Saving
1. Take heap snapshot at T=0
2. Force garbage collection: `global.gc()`
3. Run suspected operation N times
4. Take heap snapshot at T=1
5. Compare snapshots - look for objects with count = N

### Notes for Next Session
- Add memory monitoring alert at 1GB threshold
- Document this debugging pattern for team

### Context to Load
```
src/services/websocket.js
```
