Topics
v6.0.0
On this page · sections

04. Design a Real-time Chat

Difficulty: Hard
Interview Focus: WebSockets · Message Ordering · Offline Sync · Presence

Interview Question

Design a real-time chat application that delivers messages instantly, handles reconnects, and keeps conversations consistent.

Requirements

Functional

  • 1:1 and group conversations
  • Send / receive messages in real time
  • Typing indicators and online presence
  • Delivery / read receipts (optional depth)
  • Load older messages (pagination)
  • Handle reconnect and offline send queue

Non-Functional

  • Low latency delivery
  • Correct ordering under concurrency
  • Resilient reconnect
  • Accessible message list and composer
  • Scalable fan-out to many clients

Solution

1. High-Level Architecture

Chat UI ↓ Message Store ↓ Connection Manager (WS) ↓ Chat Gateway ↓ Message Service + Fan-out

HTTP for history / auth; WebSocket (or SSE) for live events.

2. Component Design

ChatApp ├── ConversationList ├── ChatThread │ ├── MessageList (virtualized) │ ├── TypingIndicator │ └── Composer └── ConnectionBanner

3. Connection Lifecycle

Connect WS ↓ Authenticate ↓ Subscribe to inbox / rooms ↓ Receive events ↓ On drop → backoff reconnect ↓ Resume from last event / cursor

Show a clear connection state in the UI (online / reconnecting / offline).

4. Send Path

User sends ↓ Optimistic local message (clientId) ↓ WS send / HTTP fallback ↓ Ack with serverId + timestamp ↓ Reconcile local → server message

5. Ordering & Duplicates

Msg A (t=1) ──→ Msg B (t=2) ──→ (B arrives first)

Use:

  • Server timestamp / sequence per room
  • Idempotent upsert by clientId / serverId
  • Sort key in the store, not arrival order alone

6. Offline & Reconnect

  • Queue outbound messages while offline
  • On reconnect: flush queue, then sync gap (since=cursor)
  • Deduplicate events already applied

7. Presence & Typing

  • Ephemeral events; throttle typing sends (~1–2s)
  • Expire typing locally with a timeout
  • Presence via heartbeat or last-seen channel

8. Performance & Scale

Client: virtualize long threads · paginate history · debounce typing · batch receipts.

Backend path:

Clients ↓ WS Gateway (sticky / room routing) ↓ Chat Service ↓ Pub/Sub + Message Store

Key Decisions

ProblemSolution
Live deliveryWebSocket (+ HTTP history)
Reconnect stormsExponential backoff + jitter
Wrong orderPer-room sequence / sort key
Duplicate messagesIdempotent ids
Offline sendOutbox queue
Typing spamThrottle ephemeral events
Huge threadsVirtualization + cursor history

Interview Q&A

Q1. Why not poll?
Polling adds latency and load. WebSockets push events; keep HTTP for history and fallback.

Q2. How do you resume after disconnect?
Store last applied event cursor; on reconnect request since=cursor and merge idempotently.

Q3. Optimistic send — what if it fails?
Keep message in pending / failed; allow retry; never lose the outbox entry until acked.

Q4. How do read receipts scale?
Aggregate or sample at high fan-out; don’t broadcast every receipt to every member of huge rooms.

Q5. Group chat fan-out?
Gateway + pub/sub. Client still upserts by id so duplicate deliveries are safe.

Q6. Accessibility?
Live region for new messages (carefully), focus management in composer, keyboard navigation in conversation list.

Interviewer Checklist

Transport choice · Ordering · Idempotency · Reconnect · Optimistic send · Presence · Performance · Trade-offs

← E-commerce · Next: Collaborative Editor →

Last updated on