System Design intermediate LIVE DEMO
πŸ’¬

Chat System Message Lifecycle Visualization

Walk through a horizontally scaled chat system from initial load balancing and heartbeat keepalives through presence registry lookup, cross-gateway Pub/Sub, receipts, offline queueing

websocketssystem designmessage queuespush notificationsredishorizontal scalingload-balancing
Interactive Demo

Continue with the guided workspace

Use the paired workspace to connect this guide's mental model with live component state, visible signals, and the outcome each step or scenario is meant to prove.

Mental Model

Chat delivery is a state-routing problem. The core system architecture has to route messages in real-time across a horizontally scaled gateway tier, handle offline delivery transitions when recipients are disconnected, and recover gracefully when nodes fail or clients reconnect.

The core mental model divides responsibilities clearly:

  • Gateways own connections because WebSockets are long-lived and stateful.
  • Services own decisions because validation, persistence, and routing should scale horizontally.
  • Stores own correctness because Pub/Sub and sockets are fast paths, not durable sources of truth.

For sandbox parameter tuning, you can also use the retained chat system simulator.

Components and Why They Exist

Clients and Load Balancer

Clients represent user devices that establish WebSocket sessions, while the load balancer distributes initial upgrade requests across gateways. Clients dispatch heartbeat signals and chat messages, and the load balancer balances TCP connections and routes reconnecting users. Client status badges flip to online upon connection, and reconnecting devices automatically route to surviving gateways after a node failure.

WebSocket Gateways

WebSocket gateways are stateful edge nodes that maintain open socket connections with online clients. Each gateway manages TCP connections, parses incoming WebSocket frames, writes outbound messages, and tracks heartbeat keepalives. Each gateway card displays its active socket ownership, heartbeat timer state, and outbound frame writes for connected users.

Chat Service and Session Registry

The chat service and session registry form the stateless core application tier and user routing directory. The chat service validates incoming messages and writes them to durable storage, while the session registry holds key-value mappings of online users to their current gateway node. When Alice sends a message, the chat service queries the session registry card to resolve which gateway currently holds Bob’s socket.

Pub/Sub, Message Store, and Offline Queue

Pub/Sub moves fast online events, the message store preserves timelines, and the offline queue tracks messages for disconnected clients. Together, these components transport routing events across gateways, persist message and receipt state, and buffer backlog messages until offline users return. Online messages race across the low-latency Pub/Sub path, whereas disconnected recipients rely on the durable message store and offline queue to replay missed history.

Push Service and Receipt Service

FCM/APNs push channels wake disconnected clients, and receipt processing tracks delivery and read states. The push service wakes sleeping devices when a recipient is offline, while the receipt service registers delivery and read transitions and updates conversation timelines. Push alerts wake offline client cards, and separate delivery and read receipt particles travel back toward the sender.

Edge Cases and Misconceptions

  • Pub/Sub Is Not Message Durability: Redis Pub/Sub is fire-and-forget. It does not buffer messages for disconnected gateways or offline users. A durable database is always required to sync offline history.
  • Presence Registry Drift: If a gateway crashes abruptly, the registry might think the user is still connected to it. Systems use TTL-based lease renewal and heartbeat checks to clean up dead connections.
  • Push Notification Is Only a Wakeup: APNs or FCM push notifications are best-effort delivery mechanisms. Relying on them as the primary message delivery pathway introduces ordering issues; clients should always fetch missed frames from the message store upon wakeup.
  • Read Receipts vs. Delivery Receipts: A delivery receipt indicates the gateway/client received the message packets. A read receipt indicates the user viewed the conversation. These are different user transitions and require separate database and queue handlers.

Common Questions

Why do chat gateways keep WebSocket state?

WebSocket connections are long-lived, so each gateway owns active socket state such as connection identity, heartbeats, and outbound frames. Other services should not assume every gateway can directly reach every connected user without a routing lookup.

Why is a load balancer required at connection entry?

WebSocket connections are long-lived and stateful. A load balancer distributes incoming socket upgrade requests across gateways to prevent session overload and enable gateway pinning.

Why should messages be stored before Pub/Sub delivery?

Pub/Sub is fast but not durable for offline subscribers, so the durable store remains the source of truth for reconnect, sync, retries, and receipt state.

How does a session registry route messages across gateways?

The session registry records which gateway currently owns each online user connection, allowing stateless services to route messages across a horizontally scaled WebSocket tier.

Why are delivery receipts separate from read receipts?

A delivery receipt means the recipient device or gateway accepted the message. A read receipt means the recipient opened or viewed it, so the receipt service treats those as different state transitions.

What happens when a user is offline?

The message remains in durable storage, an offline queue tracks the pending delivery, and push notification can wake the device. When the user reconnects, backlog sync drains missed messages in order.