Unlike stateless HTTP requests, WebSockets are persistent, stateful TCP connections. A single client maintains an open connection with a specific server instance.
1. OS-Level Socket Limits (File Descriptors)
In Linux, every TCP connection is represented as a File Descriptor (FD). By default, the OS limits FDs per process.
- Increase limits by modifying
/etc/security/limits.conf(nofilelimit to1,000,000). - Optimize port allocations: A single IP can only connect to ~65,000 ports on a target IP. Attach multiple virtual IPs to the load balancer or WebSocket nodes to scale.
2. Load Balancing & Layer 4 Routing
- Use Layer 4 (TCP) HAProxy or Envoy load balancers to minimize CPU overhead compared to Layer 7 HTTP parsing.
- Enable WebSocket HTTP
Upgradeheaders during initial handshakes.
3. Inter-Server Communication (Pub/Sub Backplane)
When Client A (connected to Server 1) sends a message to Client B (connected to Server 2):
- Redis Pub/Sub or Kafka Backplane: Server 1 publishes the message to a central Redis channel.
- All WebSocket servers subscribe to this channel. Server 2 reads the message, identifies that Client B is local to it, and pushes the payload down Client B's TCP socket.
Client → Global CDN / DNS → Layer 4 Load Balancer (HAProxy) → WebSocket Nodes (Go / Node / Java) ↔ Redis Cluster Pub/Sub.
Key Architectural Comparison
| Scaling Layer | Component | Architecture Responsibility | Production Technology |
|---|---|---|---|
| Edge Routing | Layer 7 Load Balancer | TLS termination, WebSocket handshake upgrade, sticky sessions. | Cloudflare, AWS ALB, Nginx. |
| Connection Tier | Gateway Socket Pods | Maintains open TCP sockets (epoll/kqueue), 100k+ connections per node. | Node.js (ws), Go (Gorilla), Netty. |
| Message Backplane | Distributed Pub/Sub | Inter-server message fanout across disparate gateway nodes. | Redis Pub/Sub, Redis Streams, Kafka. |
| Presence Store | Distributed In-Memory Store | Tracks mapping of user_id -> gateway_node_id. | Redis Cluster, Apache Cassandra. |