Managing Memory

1. Understanding Memory Challenges

SourcePer-Conn Footprint
JS object~2-10 KB
TCP buffers~64-256 KB (kernel)
permessage-deflate state~256 KB / direction
App contextVariable (subs, queues)
Note: 10k connections × 512 KB ≈ 5 GB. Disable per-conn compression context or stream-only if memory is bound.

2. Preventing Memory Leaks

CauseFix
Forgotten listenersAbortController
Closures over wsNull out on close
Unbounded queuesCap size
Maps keyed by wsUse WeakMap
Pending PromisesReject on close

3. Using Weak References

Example: WeakMap context

const ctxs = new WeakMap();
ctxs.set(ws, { subs: new Set(), userId });
// no manual cleanup when ws is GC'd
APIUse
WeakMapObject-key map, auto-evict
WeakSetSet of objects, auto-evict
WeakRefHold without preventing GC
FinalizationRegistryPost-GC cleanup hook

4. Implementing Connection Cleanup

Example: Centralized teardown

function cleanup(ws) {
  ws.removeAllListeners?.();
  clearTimeout(ws.authTimer);
  clearInterval(ws.hbTimer);
  for (const [id, p] of ws.pending) p.reject(new Error("closed"));
  ws.pending.clear();
}

5. Monitoring Memory Usage

ToolUse
process.memoryUsage()Node RSS/heap
--inspect + ChromeHeap snapshots
clinic.js heapprofileAllocation profiling
performance.memoryBrowser (Chromium)

6. Limiting Buffer Sizes

BoundWhere
maxPayloadws server option
App outbox capDrop / reject
Subscription capPer connection
Pending RPCs capAvoid runaway maps

7. Implementing Message Expiration

Example: TTL on queued message

function enqueue(msg, ttlMs = 5000) {
  outbox.push({ msg, deadline: Date.now() + ttlMs });
}
function flush() {
  const now = Date.now();
  for (const it of outbox) if (it.deadline > now) ws.send(it.msg);
  outbox.length = 0;
}

8. Garbage Collection Considerations

PracticeDetail
Avoid huge buffers in closuresNull after use
Avoid string + binary churnReuse Uint8Array pools
Tune V8 heap--max-old-space-size

9. Profiling Memory

StepAction
1Take baseline heap snapshot
2Run scenario (open/close N conns)
3Take second snapshot
4Diff retained sizes
5Track retainer paths → root cause

10. Handling Out of Memory

MitigationDetail
Process exit + restartFast recovery (PM2/systemd)
Soft capReject new conns at 80% memory
Shed loadClose idle subscribers
Health endpointReports degraded → LB drains