This article delves into the critical system design challenge of WebSocket retry storms, which can lead to server-side resource exhaustion. It explains how synchronous client reconnections after a transient network disruption can cripple backend services. The solution proposed involves a multi-tiered defense combining server-side token bucket rate limiting and client-side exponential backoff with jitter to prevent cascading failures.
Read original on Dev.to #architectureWebSocket retry storms, also known as the Thundering Herd Problem at the socket layer, occur when a large number of clients simultaneously attempt to reconnect after a widespread disconnection. This surge of connection attempts, often triggered by transient network issues or load balancer restarts, can overwhelm backend WebSocket servers. Each new connection handshake is resource-intensive, consuming significant CPU for TLS negotiation, performing database lookups for authentication, and allocating runtime resources like file descriptors and goroutines/tasks.
The Cost of Connection Establishment
Establishing a new WebSocket connection is significantly more resource-intensive than maintaining an idle persistent connection. This overhead, including TLS cryptographic handshakes, application-layer authentication (JWT validation, session binding), and runtime resource allocation, makes servers highly vulnerable to retry storms.
To mitigate retry storms, a robust architecture requires a coordinated, multi-tiered defense strategy across both client and server components. This ensures that the system can gracefully handle large-scale disconnections without spiraling into resource exhaustion.
Without jitter, even exponential backoff can lead to synchronized retry waves if all clients experience the same initial delay. Jitter introduces a random component to the backoff delay, spreading out the retries over time and preventing new 'mini-storms' from forming, thus ensuring a smoother recovery for the server.