Skip to content
Design a Chat System — WhatsApp/Messenger Architecture

Design a Chat System — WhatsApp/Messenger Architecture

DodaTech Updated Jun 15, 2026 5 min read

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

AspectClient-ServerP2P
Message deliveryServer routes all messagesDirect between peers
Offline messagesStored on serverNot available
Group chatsTrivial (server broadcasts)Complex (mesh/relay)
ScalabilityServer bandwidth is bottleneckBandwidth scales with peers
ExampleWhatsApp, TelegramSignal (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:

  1. WebSocket server with ws library
  2. JSON messages: {type: "message", sender, content, timestamp}
  3. Broadcast to all connected clients (simple room)
  4. Store last 50 messages in memory
  5. Show “User is typing” indicators
  6. 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