patterntypescriptMajor
Backpressure Handling Prevents WebSocket Server Memory Exhaustion
Viewed 0 times
backpressurebufferedAmountslow clientWebSocket servermemory exhaustionflow controlmessage drop
Problem
A WebSocket server broadcasting high-frequency data to a slow client buffers unsent messages in memory. With hundreds of slow clients, the server runs out of memory and crashes.
Solution
Check ws.bufferedAmount before sending. If the send buffer is too large, drop the message or close the slow client rather than queueing more data.
import { WebSocketServer, WebSocket } from 'ws';
const MAX_BUFFER = 1024 * 1024; // 1MB
function broadcast(wss: WebSocketServer, data: string) {
for (const client of wss.clients) {
if (client.readyState !== WebSocket.OPEN) continue;
// Drop message for slow clients rather than buffering
if ((client as any).bufferedAmount > MAX_BUFFER) {
console.warn('Dropping message for slow client');
continue;
}
client.send(data);
}
}
// Alternative: close clients that fall too far behind
function strictBroadcast(wss: WebSocketServer, data: string) {
for (const client of wss.clients) {
if ((client as any).bufferedAmount > MAX_BUFFER) {
client.close(1008, 'Too slow');
continue;
}
if (client.readyState === WebSocket.OPEN) client.send(data);
}
}Why
TCP's send buffer provides flow control within a connection, but the application layer can still queue data faster than TCP drains it. The ws library buffers unsent frames in JavaScript heap memory with no built-in limit.
Gotchas
- bufferedAmount is a property of the ws WebSocket object — it tracks bytes queued but not yet sent.
- Dropping messages is the correct behavior for real-time data (price feeds, telemetry) — latest value matters, not history.
- For ordered delivery streams, closing the slow client and forcing reconnect is safer than dropping.
- Monitor bufferedAmount per client with a setInterval watchdog to detect chronic slow clients.
Revisions (0)
No revisions yet.