Real-Time Features: WebSockets, Server-Sent Events, and WebRTC

A deep dive into choosing the right real-time protocol for your use case—from live dashboards to video conferencing.
Real-time features are table stakes for modern products—users expect live updates, collaborative editing, instant notifications, and sub-second feedback. Three protocols dominate the real-time web: WebSockets, Server-Sent Events (SSE), and WebRTC. Each has a distinct performance profile, implementation complexity, and set of ideal use cases. ## WebSockets: Bidirectional, Low-Latency Communication WebSockets establish a persistent, full-duplex connection over a single TCP connection. Once the WebSocket handshake completes, messages can flow in both directions without HTTP overhead. This makes WebSockets ideal for: - **Chat and messaging**: Messages flow server→client and client→server - **Collaborative editing**: Operational transforms (OT) or CRDT-based conflict resolution requires bidirectional message flow - **Live gaming**: Sub-100ms latency requirements with bidirectional state updates - **Trading and finance**: Real-time price feeds with client-initiated order flow **Server Implementation with Node.js (Socket.io)**: ```javascript import { Server } from 'socket.io'; import { createAdapter } from '@socket.io/redis-adapter'; const io = new Server(httpServer, { cors: { origin: '*' } }); io.adapter(createAdapter(pubClient, subClient)); // Redis adapter for horizontal scaling io.on('connection', (socket) => { socket.on('join-room', (roomId) => { socket.join(roomId); }); socket.on('message', (data) => { // Broadcast to all users in the room except sender socket.to(data.roomId).emit('message', { text: data.text, userId: socket.data.userId, timestamp: Date.now(), }); }); }); ``` **Scaling WebSockets**: WebSocket connections are stateful and tied to a specific server instance. Horizontal scaling requires a pub/sub mechanism (Redis) so that a message received by server A can be broadcast to clients connected to server B. Use Redis's PubSub or Streams as the backplane. Connection limits: a WebSocket server can handle thousands of concurrent connections per CPU core. For high-scale (100k+ concurrent users), use dedicated WebSocket services (Ably, Pusher, Socket.io managed) or architect with connection multiplexing. ## Server-Sent Events: Simple, Efficient Unidirectional Streaming SSE is HTTP-based streaming—the server sends a stream of events over a long-lived HTTP connection. It's unidirectional (server→client only) and reconnects automatically. Simpler than WebSockets, works through HTTP/2, and doesn't require special server infrastructure. SSE is ideal for: - **Live dashboards and analytics**: Metrics updates flowing from server to client - **Notification feeds**: System notifications pushed to users - **Progress updates**: Long-running job progress (file uploads, exports, AI generation) - **Live commentary**: Sports scores, election results, news tickers ```typescript // Next.js API route for SSE export async function GET(request: Request) { const encoder = new TextEncoder(); const stream = new ReadableStream({ start(controller) { const interval = setInterval(() => { const data = JSON.stringify({ price: getLatestPrice(), ts: Date.now() }); controller.enqueue(encoder.encode(`data: ${data}\n\n`)); }, 1000); 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', }, }); } ``` **When to prefer SSE over WebSockets**: If your use case is purely server→client (notifications, live data feeds, AI streaming responses), SSE is simpler, more efficient, and works through existing HTTP infrastructure without special WebSocket support. ## WebRTC: Peer-to-Peer Media and Data WebRTC enables direct peer-to-peer connections between browsers for audio/video and arbitrary data channels. The server's role is signaling—exchanging connection metadata (ICE candidates, SDP offers/answers) to help peers establish a direct connection. Once connected, media and data flow directly between peers without a server relay. **Use cases**: - **Video/audio calling**: Zoom, Google Meet, and similar apps are built on WebRTC - **Screen sharing**: Real-time screen mirroring between users - **P2P file transfer**: Large file transfers that bypass server upload/download bottlenecks - **Multiplayer games**: Low-latency data channels for game state synchronization **Architecture**: A signaling server (WebSocket-based) exchanges ICE candidates between peers. STUN servers help peers discover their public IP addresses. TURN servers relay traffic when direct P2P connection fails (common with symmetric NATs—affects ~15-20% of connections). For production, use a managed TURN service (Twilio TURN, Xirsys) rather than running your own. **WebRTC in React**: ```typescript const peerConnection = new RTCPeerConnection({ iceServers: [ { urls: 'stun:stun.l.google.com:19302' }, { urls: 'turn:your.turn.server', username: 'user', credential: 'pass' }, ], }); // Add local media tracks const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true }); stream.getTracks().forEach(track => peerConnection.addTrack(track, stream)); // Create and send offer through signaling server const offer = await peerConnection.createOffer(); await peerConnection.setLocalDescription(offer); signalingChannel.send({ type: 'offer', sdp: offer.sdp }); ``` ## Choosing the Right Protocol | | WebSockets | SSE | WebRTC | |---|---|---|---| | **Direction** | Bidirectional | Server→Client | Bidirectional (P2P) | | **Latency** | Low (~50ms) | Low (~100ms) | Very Low (~20ms P2P) | | **Scalability** | Moderate (needs backplane) | High (HTTP/2 native) | High (P2P) | | **Complexity** | Medium | Low | High | | **Best for** | Chat, collaborative editing | Dashboards, notifications | Video calls, file transfer |
