skip to content
logo
Table of Contents

Why WebSockets?

HTTP is stateless, making real-time updates inefficient. WebSockets provide persistent, bi-directional communication between the client and server.


WebSocket Server in Node.js

A basic WebSocket server using ws:

import { WebSocketServer } from "ws";
const wss = new WebSocketServer({ port: 8080 });
wss.on("connection", (ws) => {
ws.on("message", (message) => {
console.log(`Received: ${message}`);
ws.send(`Echo: ${message}`);
});
});

WebSocket Client Example

A simple client to test our WebSocket server:

const ws = new WebSocket("ws://localhost:8080");
ws.onmessage = (event) => console.log(`Server: ${event.data}`);
ws.onopen = () => ws.send("Hello WebSocket");

Scaling WebSockets

A single WebSocket server is limited by CPU and connections. Solutions:

Load Balancing with NGINX

map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream websocket_servers {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
}
server {
listen 80;
location / {
proxy_pass http://websocket_servers;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}

Using Redis Pub/Sub for Multi-Instance Communication

When running multiple WebSocket servers, messages must be shared between them. Redis Pub/Sub can solve this.

Redis Pub/Sub WebSocket Integration

import { WebSocketServer } from "ws";
import { createClient } from "redis";
const wss = new WebSocketServer({ port: 8080 });
const pub = createClient();
const sub = createClient();
await Promise.all([pub.connect(), sub.connect()]);
sub.subscribe("broadcast", (message) => {
wss.clients.forEach((client) => client.send(message));
});
wss.on("connection", (ws) => {
ws.on("message", (message) => {
pub.publish("broadcast", message.toString());
});
});

Handling Connection Drops

WebSocket connections may disconnect due to network issues. A ping-pong heartbeat keeps connections alive.

setInterval(() => {
wss.clients.forEach((client) => {
if (!client.isAlive) return client.terminate();
client.isAlive = false;
client.ping();
});
}, 30000);

Conclusion

  • WebSockets enable real-time bidirectional communication.
  • Scaling requires load balancing + Redis Pub/Sub.
  • Use heartbeat pings to detect and handle disconnects.

For production, consider WebRTC for peer-to-peer cases or GraphQL subscriptions for structured real-time data updates.