Question #4 of 60•Protocols•Hard• ~3 min read

How do you scale WebSockets to support millions of concurrent, stateful connections?

Executive Takeaway

Deconstruct connection-state storage, load-balancer configurations, pub/sub communication backplanes, and server socket limits (ports & file descriptors).

Architectural Breakdown & AnalysisFAANG Aligned

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 (nofile limit to 1,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 Upgrade headers 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.
NOTE — Architecture Pattern

Client → Global CDN / DNS → Layer 4 Load Balancer (HAProxy) → WebSocket Nodes (Go / Node / Java) ↔ Redis Cluster Pub/Sub.

Key Architectural Comparison

Scaling LayerComponentArchitecture ResponsibilityProduction Technology
Edge RoutingLayer 7 Load BalancerTLS termination, WebSocket handshake upgrade, sticky sessions.Cloudflare, AWS ALB, Nginx.
Connection TierGateway Socket PodsMaintains open TCP sockets (epoll/kqueue), 100k+ connections per node.Node.js (ws), Go (Gorilla), Netty.
Message BackplaneDistributed Pub/SubInter-server message fanout across disparate gateway nodes.Redis Pub/Sub, Redis Streams, Kafka.
Presence StoreDistributed In-Memory StoreTracks mapping of user_id -> gateway_node_id.Redis Cluster, Apache Cassandra.
Previous QuestionWhat is the difference between Database Sharding, Partitioning, and Indexing?Next Question Which authorization and session mechanisms are required in distributed microservices?

Continue Learning on Being SDE

Explore deep-dive system architecture modules, low-level object-oriented designs, and interview cheat sheets.