Real-Time Web Apps with WebSockets
/ 2 min read
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.