Implementing Horizontal Scaling

1. Understanding Scaling Challenges

ChallengeReason
Stateful socketsTied to a node
Cross-node fan-outPub needs all subs
Sticky sessionsRequired for some auth models
Rolling deploysNeed graceful drain

2. Using Redis Pub/Sub

Example: Redis fan-out

import { createClient } from "redis";
const pub = createClient(); const sub = pub.duplicate();
await Promise.all([pub.connect(), sub.connect()]);
sub.subscribe("ws-broadcast", (raw) => {
  for (const c of wss.clients) if (c.readyState === 1) c.send(raw);
});
function broadcast(msg) { pub.publish("ws-broadcast", JSON.stringify(msg)); }
ToolStrength
Redis Pub/SubSimple, low latency
Redis StreamsPersistent, replay
NATSHigh throughput, subjects
KafkaDurable, ordered, replay

3. Implementing Message Broadcasting

PatternDetail
Fan-out by topicChannel per room
User mailboxChannel per user across devices
Server-targetedChannel per server (rare)

4. Sharing Session State

StoreTrade-off
RedisFast central store
JWTStateless; hard to revoke
DBDurable; slower

5. Implementing Sticky Sessions

LB MethodDetail
IP hashSimple, NAT-prone
CookiePer-session pinning (L7)
Consistent hashingStable assignment

6. Using Message Queue

QueueUse Case
RabbitMQRouting, ACK semantics
KafkaEvent streaming, replay
SQSManaged, FIFO option
NATS JetStreamLightweight + durable

7. Implementing Service Discovery

ToolDetail
Kubernetes Service / DNSBuilt-in
Consul / etcdKV + watch
EurekaJVM ecosystem

8. Handling Server Addition/Removal

Rolling Deploy Drain

  1. Mark node unhealthy in LB (stop new conns)
  2. Broadcast close 1001 to existing clients
  3. Wait for drain or timeout
  4. Stop process
  5. Start new version; readiness probe → traffic

9. Monitoring Cluster Health

MetricUse
Conn count / nodeBalance check
CPU / RAM / FDSaturation
Cross-node msg lagPub/sub delay
Restart countStability

10. Testing Scaling Scenarios

TestGoal
10× connsVertical limits
Node killReconnect storm
Rolling deployZero-downtime drain
Redis failoverPub/sub recovery