Lesson 28 / 32

Design a Chat Application

Real-time delivery, presence, and message history at scale.

Requirements

1:1 and group messaging, delivery within ~100ms when online, offline users get messages on reconnect, message history, online/typing indicators. Assume 50M DAU sending 40 messages/day each.

Connection layer

Clients hold a persistent WebSocket to a connection-gateway server. A registry (Redis) maps user_id -> gateway server so any backend can find where to push a message. Sending to an offline user just writes to their inbox for later delivery.

Message flow

Write path: persist the message, then fan out to the recipient's active connection if online.

send(msg):
  db.append(conversation_id, msg)   # source of truth
  gw = registry.lookup(recipient_id)
  if gw: gw.push(msg)               # online
  else: queue.push(offline_inbox)   # deliver on reconnect

Output:

DB write is the durability guarantee; push is best-effort

Order and dedupe with a sequence number

Assign each message a per-conversation sequence number so clients can detect gaps (fetch missing) and dedupe retried sends — network hiccups shouldn't reorder or duplicate what the user sees.