Message Bus (Live RabbitMQ & WebSocket Broadcast Engine)
- Backend
- Realtime
- Message Bus
- DevOps
Production · NestJS, Node.js, RabbitMQ, WebSockets …
Executive Overview
Core Problem
Broadcasting high-frequency updates (live sports scores and fluctuating betting odds) to thousands of concurrent mobile and web clients cannot be handled by database polling. Direct client connections to the primary ingestion databases cause socket and connection starvation, while unbuffered broadcast bursts can desynchronize clients during game scoring events.
Architectural Solution
Engineered a dedicated message bus service that decouples event ingestion from client delivery. The service listens to topic exchanges on a self-hosted RabbitMQ cluster and fans out serialized binary/JSON frames to connected WebSocket clients with socket room isolation, heartbeat monitoring, and Cronitor health checks.
Measurable Impact
Delivered sub-15ms end-to-end event propagation from RabbitMQ to client devices, supported thousands of concurrent active socket subscriptions with zero message drops, and eliminated 100% of read traffic on underlying transactional databases for live updates.
System Architecture
Component topology, protocol boundaries, and data flow.
Reliability & Production Security
Deployment & Infrastructure
What I Learned
Technical trade-offs, battle-tested discoveries, and operational takeaways from this project.
Decouple Ingestion from Broadcast via Message Brokers
Attempting to push WebSocket frames directly from the data ingestion service creates severe backpressure when client connections spike. Buffering events in RabbitMQ topic exchanges allows consumer nodes to scale independently based on connected client counts.
Pre-Serialize Broadcast Payloads Once for All Clients
Serializing the same JSON payload 5,000 times for 5,000 connected sockets burns CPU cycles unnecessarily. Serializing the message payload once into a shared buffer and dispatching the raw buffer across socket descriptors reduces CPU utilization by 70%.
RabbitMQ Prefetch Limits Prevent Memory Exhaustion
Default RabbitMQ consumers accept unlimited unacknowledged messages, causing worker memory to balloon during high-volume sports match events. Setting an explicit prefetch count (e.g. 50-100) ensures worker nodes process batches safely within memory budgets.
Active Heartbeats Detect Zombie Sockets
Mobile clients on cellular networks frequently disconnect without sending TCP FIN packets, leaving zombie sockets lingering in memory. Implementing 30-second ping/pong heartbeats ensures ghost connections are terminated and socket file descriptors reclaimed promptly.
Future Roadmap & Architectural Evolution
- →Implement selective client delta-patching to broadcast only changed record attributes rather than entire game objects.
- →Benchmark MQTT protocol alongside WebSockets for low-bandwidth mobile environments.