WebSockets
Real-time
Web Development
Backend
Node.js
Ask anything about this article
Hi! I've read this article.
What would you like to know?
@farhan
Real-time features are no longer nice-to-have — they're expected. Users want live updates, instant messaging, and collaborative experiences. Here's how to build them.
| Feature | WebSocket | SSE | WebRTC | HTTP Polling |
|---|---|---|---|---|
| Direction | Bidirectional | Server → Client | P2P | Client → Server |
| Latency | ~50ms | ~100ms | ~10ms | ~1000ms |
| Complexity | Medium | Low | High | Low |
| Use Case | Chat, gaming | Notifications, feeds | Video, audio | Fallback |
| Browser Support | 98%+ | 97%+ | 96%+ | 100% |
typescriptimport { WebSocketServer, WebSocket } from 'ws';
const wss = new WebSocketServer({ port: 8080 });
const rooms = new Map<string, Set<WebSocket>>();
wss.on('connection', (ws) => {
ws.on('message', (data) => {
const msg = JSON.parse(data.toString());
switch (msg.type) {
case 'join':
if (!rooms.has(msg.room)) rooms.set(msg.room, new Set());
rooms.get(msg.room)!.add(ws);
break;
case 'message':
const room = rooms.get(msg.room);
room?.forEach(client => {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify({
type: 'message',
user: msg.user,
text: msg.text,
timestamp: Date.now()
}));
}
});
break;
}
});
});
typescriptfunction useWebSocket(url: string) {
const [messages, setMessages] = useState<Message[]>([]);
const wsRef = useRef<WebSocket | null>(null);
useEffect(() => {
const ws = new WebSocket(url);
wsRef.current = ws;
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
setMessages(prev => [...prev, msg]);
};
ws.onclose = () => {
// Auto-reconnect after 3 seconds
setTimeout(() => {
wsRef.current = new WebSocket(url);
}, 3000);
};
return () => ws.close();
}, [url]);
const send = (data: any) => {
wsRef.current?.send(JSON.stringify(data));
};
return { messages, send };
}
typescript// Next.js API Route
export async function GET(request: Request) {
const stream = new ReadableStream({
start(controller) {
const encoder = new TextEncoder();
const interval = setInterval(() => {
const data = JSON.stringify({
type: 'notification',
message: 'New update available',
timestamp: Date.now()
});
controller.enqueue(encoder.encode(`data: ${data}\n\n`));
}, 5000);
request.signal.addEventListener('abort', () => {
clearInterval(interval);
controller.close();
});
}
});
return new Response(stream, {
headers: {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
},
});
}
┌─────────────┐
│ Load │
│ Balancer │
└──────┬──────┘
│
┌────────────┼────────────┐
│ │ │
┌─────┴─────┐ ┌───┴───┐ ┌─────┴─────┐
│ WS Node │ │ WS │ │ WS Node │
│ 1 │ │ Node 2│ │ 3 │
└─────┬─────┘ └───┬───┘ └─────┬─────┘
│ │ │
└────────────┼────────────┘
│
┌──────┴──────┐
│ Redis │
│ Pub/Sub │
└─────────────┘
Use Redis Pub/Sub to broadcast messages across WebSocket server instances. Each server handles ~50K connections.
Real-time features transform good apps into great ones. Choose the right protocol and scale smartly.