WebSocket server design + heartbeats
A production-ready WebSocket server architecture with bidirectional heartbeats, exponential backoff reconnection, and graceful shutdown semantics.
Core loop
for {
select {
case <-ctx.Done():
return
case msg := <-inbound:
dispatch(msg)
case <-ticker.C:
writePing()
case <-pongDeadline.C:
reconnect()
}
}Heartbeat contract
- Ping interval: 15s, sent by server when idle.
- Pong deadline: 10s after ping; missed pong triggers reconnect.
- Client-initiated: client may ping; server must pong within 5s.
Reconnection strategy
| Attempt | Delay | Jitter |
|---|---|---|
| 1 | 1s | ±200ms |
| 2 | 2s | ±400ms |
| 3 | 4s | ±800ms |
| 4+ | 30s cap | ±2s |
Graceful shutdown
On SIGTERM, drain the write buffer (5s deadline), send a close frame with code 1001, then terminate the TCP connection. In-flight messages are acknowledged before the socket is released.