Verified by Garnet Grid

WebSocket & Real-Time Architecture

Build real-time applications. Covers WebSocket architecture, SSE, long polling, real-time database patterns, connection scaling, and choosing the right real-time protocol.

HTTP is request-response: the client asks, the server answers. But many applications need the server to push data to the client without being asked — live scores, chat messages, stock prices, collaborative editing. Real-time architecture flips the communication model from pull to push.


Protocol Comparison

ProtocolDirectionLatencyComplexityBest For
WebSocketBidirectionalVery lowMediumChat, gaming, collaboration
Server-Sent Events (SSE)Server → ClientLowLowLive feeds, notifications
Long PollingSimulated pushMediumLowLegacy browser support
WebTransportBidirectional (QUIC)Very lowHighLow-latency, unreliable delivery OK
gRPC StreamingBidirectionalLowMediumMicroservice communication

WebSocket Architecture

                    Load Balancer (sticky sessions or shared state)
                   ┌──────────┴──────────┐
              ┌────▼────┐           ┌────▼────┐
              │ App     │           │ App     │
              │ Server 1│◀── pub ──│ Server 2│
              │         │── sub ──▶│         │
              └────┬────┘           └────┬────┘
                   │                     │
              ┌────▼─────────────────────▼────┐
              │        Redis Pub/Sub          │
              │   (message broadcast layer)    │
              └───────────────────────────────┘

Connection Management

import asyncio
import websockets
import json

connected_clients = set()

async def handler(websocket, path):
    # Register
    connected_clients.add(websocket)
    try:
        async for message in websocket:
            data = json.loads(message)
            
            # Broadcast to all connected clients
            if data["type"] == "chat":
                await broadcast(json.dumps({
                    "type": "chat",
                    "user": data["user"],
                    "message": data["message"],
                    "timestamp": time.time()
                }))
    finally:
        # Unregister on disconnect
        connected_clients.discard(websocket)

async def broadcast(message):
    if connected_clients:
        await asyncio.gather(
            *[client.send(message) for client in connected_clients]
        )

Server-Sent Events (SSE)

from fastapi import FastAPI
from fastapi.responses import StreamingResponse

app = FastAPI()

@app.get("/events")
async def event_stream():
    """Server-Sent Events endpoint."""
    async def generate():
        while True:
            data = await get_latest_update()
            yield f"event: update\ndata: {json.dumps(data)}\n\n"
            await asyncio.sleep(1)
    
    return StreamingResponse(
        generate(),
        media_type="text/event-stream",
        headers={
            "Cache-Control": "no-cache",
            "Connection": "keep-alive"
        }
    )
// Client-side SSE (auto-reconnect built in!)
const source = new EventSource('/events');
source.addEventListener('update', (event) => {
    const data = JSON.parse(event.data);
    updateUI(data);
});

Anti-Patterns

Anti-PatternProblemFix
Polling every secondWastes bandwidth, battery, server CPUSSE or WebSocket for server-push
WebSocket for one-way dataOver-engineeringSSE for server→client only
No heartbeat/pingDead connections held openPeriodic ping/pong, timeout detection
All data through WebSocketLarge payloads block real-time messagesWebSocket for events, HTTP for data fetches
No reconnection logicDropped connections = broken appAuto-reconnect with backoff

Checklist

  • Protocol selected based on use case (WebSocket vs SSE vs polling)
  • Connection scaling: Redis pub/sub or similar for multi-instance
  • Load balancer: sticky sessions or connection-aware routing
  • Heartbeat: ping/pong to detect dead connections
  • Reconnection: client auto-reconnects with backoff
  • Authentication: validated on initial connection
  • Rate limiting: per-connection message rate limits
  • Monitoring: active connections, message throughput

:::note[Source] This guide is derived from operational intelligence at Garnet Grid Consulting. For real-time architecture consulting, visit garnetgrid.com. :::

Jakub Dimitri Rezayev
Jakub Dimitri Rezayev
Founder & Chief Architect • Garnet Grid Consulting

Jakub holds an M.S. in Customer Intelligence & Analytics and a B.S. in Finance & Computer Science from Pace University. With deep expertise spanning D365 F&O, Azure, Power BI, and AI/ML systems, he architects enterprise solutions that bridge legacy systems and modern technology — and has led multi-million dollar ERP implementations for Fortune 500 supply chains.

View Full Profile →