Design a Chat System — WhatsApp/Messenger Architecture
Designing a real-time chat system is one of the most common system design interview questions. You need to handle message delivery, online presence, read receipts, and scale to billions of messages daily.
What You’ll Learn
You’ll master client-server vs P2P architectures, message storage strategies, WebSocket for real-time delivery, read receipts, and last seen tracking. You’ll build a complete chat system architecture.
Why This Problem Matters
Chat systems are the backbone of modern communication — WhatsApp sends 100 billion messages daily. Understanding their architecture teaches you real-time systems, message queues, and conflict resolution. At DodaTech, similar real-time messaging patterns power collaboration in DodaZIP.
Chat System Learning Path
flowchart LR
A[URL Shortener] --> B[Chat System]
B --> C{You Are Here}
C --> D[Design Uber]
C --> E[Rate Limiter]
style C fill:#f90,color:#fff
Client-Server vs Peer-to-Peer
| Aspect | Client-Server | P2P |
|---|---|---|
| Message delivery | Server routes all messages | Direct between peers |
| Offline messages | Stored on server | Not available |
| Group chats | Trivial (server broadcasts) | Complex (mesh/relay) |
| Scalability | Server bandwidth is bottleneck | Bandwidth scales with peers |
| Example | WhatsApp, Telegram | Signal (partially) |
Most chat systems use client-server. P2P is limited to small groups and both parties online.
WebSocket Flow for Real-Time Messaging
sequenceDiagram
participant A as User A (Client)
participant B as User B (Client)
participant S as Chat Server
participant Q as Message Queue
participant DB as Database
A->>S: WebSocket connect (auth token)
S->>A: Connection acknowledged
B->>S: WebSocket connect (auth token)
S->>B: Connection acknowledged
A->>S: Send message to B
S->>Q: Queue message
Q->>DB: Persist message
Q->>S: Confirm saved
S->>A: Message delivered (server ack)
S->>B: Forward message via WebSocket
B->>S: Read receipt
S->>A: Receipt forwarded
Message Storage
Messages are the most critical data. Storage strategy:
CREATE TABLE messages (
id BIGINT PRIMARY KEY,
sender_id BIGINT NOT NULL,
conversation_id BIGINT NOT NULL,
content TEXT NOT NULL,
msg_type VARCHAR(20) DEFAULT 'text', -- text, image, video
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_conversation (conversation_id, created_at)
);
CREATE TABLE conversations (
id BIGINT PRIMARY KEY,
type VARCHAR(10) DEFAULT 'one-to-one', -- or 'group'
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE conversation_participants (
conversation_id BIGINT,
user_id BIGINT,
last_read_message_id BIGINT,
PRIMARY KEY (conversation_id, user_id)
);For WhatsApp scale (100B messages/day), use cassandra-like time-series storage — partition by conversation_id and order by created_at for fast retrieval.
Read Receipts and Last Seen
Read receipts: When recipient opens the conversation, send a read receipt. The sender sees double-check marks (WhatsApp) or read indicators.
Last seen: Each user has a last_seen_at timestamp. Update on WebSocket disconnect or periodic pings.
# Last seen update on disconnect
async def on_disconnect(user_id: str):
await redis.set(f"last_seen:{user_id}", int(time.time()))
await broadcast_presence(user_id, "offline")
# Read receipt
async def mark_as_read(user_id: str, conversation_id: str, message_id: str):
await db.execute("""
UPDATE conversation_participants
SET last_read_message_id = $1
WHERE conversation_id = $2 AND user_id = $3
""", message_id, conversation_id, user_id)Common Mistakes
1. Blocking on Message Persistence
Never make the user wait for database writes. Use a message queue: the sender gets a “sent” confirmation when the message reaches the queue, not the DB.
2. Single WebSocket Server
One WebSocket server handles limited concurrent connections. Use a WebSocket gateway layer that fans out to multiple nodes. Use Redis Pub/Sub to broadcast across nodes.
3. No Offline Message Queue
If the recipient is offline, store messages and deliver them on reconnection. Track the last_read_message_id per user.
4. Ignoring Message Ordering
Messages can arrive out of order. Use created_at as a client-generated timestamp with a logical clock (Lamport timestamp) for ordering.
5. Leaking Online Status
Don’t broadcast exact online/offline transitions publicly. WhatsApp shows “last seen recently” to non-contacts. Respect privacy settings.
6. No Media Compression
Images and videos consume bandwidth. Compress on the server side. Use CDN for delivery and generate thumbnails.
7. Missing End-to-End Encryption
WhatsApp uses the Signal Protocol. For production chat, implement E2EE or document its absence clearly in privacy terms.
Practice Questions
1. Why use WebSocket instead of HTTP polling?
WebSocket maintains a persistent connection for instant delivery. HTTP polling wastes bandwidth and has higher latency.
2. How does WhatsApp handle message delivery for offline users?
Messages are queued in the server. When the recipient reconnects, the server sends all undelivered messages.
3. What’s the purpose of the message queue between server and database?
It decouples message acceptance from persistence. The sender gets an immediate acknowledgement; the database writes happen asynchronously.
4. How do you scale WebSocket connections across multiple servers?
Use a load balancer with sticky sessions. Use Redis Pub/Sub to broadcast messages to the correct server instance.
5. Challenge: Add typing indicators.
When User A types, send a WebSocket message {type: "typing", conversation_id}. Broadcast to all participants. Stop after 3 seconds of inactivity.
Mini Project: Simple WebSocket Chat
Build a real-time chat with Node.js:
- WebSocket server with
wslibrary - JSON messages:
{type: "message", sender, content, timestamp} - Broadcast to all connected clients (simple room)
- Store last 50 messages in memory
- Show “User is typing” indicators
- Add a simple REST API for fetching message history
What’s Next
Congratulations on completing this Chat System design! Here’s where to go from here:
- Practice daily — Design one system component per day
- Build a project — Implement a working WebSocket chat
- Explore related topics — E2E encryption, message queues
- Join the community — Share your designs and get feedback
Remember: every expert was once a beginner. Keep designing!
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro