Chaturmind
LearnDSASystem DesignDevOpsEngineering GrowthBlog
Start learning
Chaturmind

Structured learning paths for engineers who want to go deep. Written by practitioners.

Learn

  • Java
  • DSA
  • System Design
  • Spring Boot
  • AI / ML
  • DevOps
  • Engineering Growth

Company

  • Blog
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Chaturmind. All rights reserved.

Built for engineers who want to go deep.

← System Design Interview Playbook

Interview Framework

  • The 6-Step Design Framework
  • HLD Fundamentals Refresher
  • Requirement Gathering Practice
  • Domain Decomposition
  • API Contract Design
  • Data Ownership Model
  • Failure Scenario Walkthroughs
  • Architecture Diagramming
  • Back-of-Envelope Estimation

10 Case Studies

  • Design a URL Shortener
  • Design Twitter / X
  • Design WhatsApp
  • Design Netflix
  • Design a Rate Limiter
  • Design a Search Autocomplete
  • Design a Distributed Cache
  • Design a Notification Service
  • Design Uber / Ride Sharing
  • Design a Distributed File Storage System
  • Design a Distributed Task Scheduler
  • Design a Message Queue System
  • Design an Authentication System at Scale
  • Design a Distributed Logging & Metrics Pipeline
  • Design a Food Delivery Platform
  • Design a Real-Time Analytics Dashboard
  • Design a Monitoring & Alerting System
  • Design Container Orchestration Basics
  • Design a CI/CD Pipeline System
  • Design Service Mesh Basics
  • Design a Centralized Configuration & Secrets System
  • Design a Batch Processing System
  • Design a Data Warehouse / Analytics Storage Layer
  • Design Global Content Delivery
  • Case studies

    🏗️Design a URL Shortener
  • 🏗️Design a Rate Limiter
  • 🏗️Design Twitter / X
  • 🏗️Design WhatsApp
  • 🏗️Design Netflix
  • 🏗️Design a Distributed Cache
  • 🏗️Design a Notification Service
  • 🏗️Design a Search Autocomplete System
  • 🏗️Design Uber / Ride Sharing
  • 🏗️Design a Web Crawler
  • 🏗️Design a Payment System
  • 🏗️Design a Distributed Lock Service
  • 🏗️Design a Video Streaming Platform
  • 🏗️Design a Search Engine
  • 🏗️Design E-Commerce Checkout & Inventory at Scale
Chaturmind
← System Design Interview Playbook

Interview Framework

  • The 6-Step Design Framework
  • HLD Fundamentals Refresher
  • Requirement Gathering Practice
  • Domain Decomposition
  • API Contract Design
  • Data Ownership Model
  • Failure Scenario Walkthroughs
  • Architecture Diagramming
  • Back-of-Envelope Estimation

10 Case Studies

  • Design a URL Shortener
  • Design Twitter / X
  • Design WhatsApp
  • Design Netflix
  • Design a Rate Limiter
  • Design a Search Autocomplete
  • Design a Distributed Cache
  • Design a Notification Service
  • Design Uber / Ride Sharing
  • Design a Distributed File Storage System
  • Design a Distributed Task Scheduler
  • Design a Message Queue System
  • Design an Authentication System at Scale
  • Design a Distributed Logging & Metrics Pipeline
  • Design a Food Delivery Platform
  • Design a Real-Time Analytics Dashboard
  • Design a Monitoring & Alerting System
  • Design Container Orchestration Basics
  • Design a CI/CD Pipeline System
  • Design Service Mesh Basics
  • Design a Centralized Configuration & Secrets System
  • Design a Batch Processing System
  • Design a Data Warehouse / Analytics Storage Layer
  • Design Global Content Delivery
  • Case studies

    🏗️Design a URL Shortener
  • 🏗️Design a Rate Limiter
  • 🏗️Design Twitter / X
  • 🏗️Design WhatsApp
  • 🏗️Design Netflix
  • 🏗️Design a Distributed Cache
  • 🏗️Design a Notification Service
  • 🏗️Design a Search Autocomplete System
  • 🏗️Design Uber / Ride Sharing
  • 🏗️Design a Web Crawler
  • 🏗️Design a Payment System
  • 🏗️Design a Distributed Lock Service
  • 🏗️Design a Video Streaming Platform
  • 🏗️Design a Search Engine
  • 🏗️Design E-Commerce Checkout & Inventory at Scale
HomeLearnSystem Design Interview Playbook10 Case Studies
WhatsApp / Messaging

Design WhatsApp

websocketmessage-queueencryptionreal-time

Problem Statement

Design a messaging app like WhatsApp. Users can send text, images, and videos to individuals or groups. Messages must be delivered in order and receipts (sent/delivered/read) must be tracked.

Requirements

Functional

  • ✓1-to-1 messaging
  • ✓Group messaging (up to 1000 members)
  • ✓Message delivery receipts (sent → delivered → read)
  • ✓Media sharing (images, video, voice notes)
  • ✓Online presence indicator

Non-Functional

  • ✓2B users, 100B messages/day
  • ✓Message delivery latency < 500ms for online users
  • ✓Messages must be delivered exactly once and in order
  • ✓End-to-end encryption
  • ✓99.99% uptime

Capacity Estimation

Capacity Estimation

  • Message rate: 100B messages/day = 1.16M messages/sec
  • Message size: avg 100 bytes text. 100B × 100 bytes = 10 TB/day text storage
  • Media: ~20% messages have media. Stored on S3; metadata only in DB
  • Active connections: 500M concurrent WebSocket connections

High-Level Architecture

Architecture

[Client A] ──── WebSocket ────▶ [Chat Server]
                                      │
                              [Message Queue (Kafka)]
                                      │
                            ┌─────────┴──────────┐
                     [Delivery Worker]    [Push Notification Service]
                            │                         │
                    [Client B online?]         [APNs / FCM]
                         Yes │
                    [Client B WebSocket]

Each chat server maintains WebSocket connections. A user might connect to any server — a routing layer (via consistent hashing on userId) directs messages to the right server.

Real-time delivery: WebSocket vs long-polling vs Server-Sent Events

  • WebSocket (what this design uses): a persistent, full-duplex connection — server can push to the client the instant a message arrives, client can send with no per-message connection setup. Best latency, but requires holding one open connection per online user (real but manageable cost at scale with connection-oriented load balancing).
  • Long-polling: client sends a request that the server holds open until a message arrives (or a timeout), then the client immediately re-requests. Works through any standard HTTP infrastructure with no special protocol support, but adds request-response overhead per message and slightly higher latency than a truly persistent connection.
  • Server-Sent Events (SSE): server-to-client push over a standard HTTP connection, but one-directional only — the client would still need a separate channel (regular HTTP POST) to send messages. Simpler than WebSocket where only server-to-client push is needed, but doesn't fit a bidirectional chat protocol as cleanly.

WebSocket wins here specifically because chat is genuinely bidirectional and latency-sensitive — the other two are better fits for one-directional or latency-tolerant push (e.g. SSE for a live dashboard, long-polling as a WebSocket-unsupported fallback).

Message delivery semantics: at-least-once vs exactly-once

Chat systems in practice target at-least-once delivery, not exactly-once — a message might be delivered twice under retry (e.g. the client's ack was lost even though the server delivered successfully), which is why every message needs a client-generated unique ID: the receiving client de-duplicates by that ID, turning at-least-once delivery (cheap, achievable with retries) into effectively-exactly-once observed behavior (the hard part is pushed to idempotent de-duplication at the edge, not to the delivery guarantee itself, which is far simpler to build reliably).

API Design

API Design

WebSocket messages (not HTTP):

// Send message
{ "type": "MESSAGE", "to": "userId", "content": "Hello", "clientMsgId": "uuid" }

// Delivery receipt (from server)
{ "type": "DELIVERED", "msgId": "...", "to": "userId" }

// Read receipt
{ "type": "READ", "msgId": "...", "by": "userId" }

REST API for non-real-time:

GET /messages/{conversationId}?before=cursor&limit=50
POST /media/upload → presigned S3 URL
GET /users/{userId}/presence

Database Design

Database Design

Messages (Cassandra — write-heavy, time-series)

messages
  conversation_id UUID    (PK partition key)
  message_id      TIMEUUID (PK clustering key, newest first)
  sender_id       UUID
  content         TEXT
  media_url       TEXT    nullable
  status          ENUM    (SENT, DELIVERED, READ)
  created_at      TIMESTAMP

Why TIMEUUID for clustering? Guarantees ordering by time AND uniqueness — no two messages have the same ID even if created at the same millisecond.

Conversation metadata (PostgreSQL)

conversations: id, type (1:1 | GROUP), created_at
participants: conversation_id, user_id, joined_at

Presence (Redis, TTL-based)

SETEX presence:userId 30 "ONLINE"  # refreshed every 20s by heartbeat

Scaling Strategy

Scaling

WebSocket connection scaling

500M concurrent WebSockets cannot live on one server. Each chat server handles ~50K connections. We need ~10,000 chat servers.

A routing service (Redis pub/sub or a service mesh) tracks which server each user is connected to:

REDIS: user:{userId}:server → "chatserver-047"

When Server A needs to deliver to a user on Server B, it publishes to Redis pub/sub channel for that user, and Server B picks it up.

Message ordering

Use Cassandra TIMEUUID + per-conversation sequence numbers. The client reorders on display.

Fan-out strategy for group chats

  • Fan-out-on-write: when a message is sent to a group, immediately write it into every member's message queue/inbox. Fast reads (each user's inbox is precomputed), but a message to a 500-person group means 500 writes — expensive for very large groups.
  • Fan-out-on-read: store the message once against the group; each member's client queries the group's message log directly when reading. Cheap writes regardless of group size, but reads require merging across the group's shared log rather than a precomputed per-user inbox.

Most chat systems fan out on write for typical group sizes (tens to low hundreds of members, where the per-message write cost is trivial) and fall back toward fan-out-on-read behavior for very large broadcast-style channels — the same push-vs-pull tradeoff as a news feed system (see the News Feed System case for the same pattern at a different scale).

Trade-offs

  • WebSocket vs long-polling: WebSocket is bidirectional and low-latency. Long-polling is simpler but wasteful.
  • Cassandra vs PostgreSQL for messages: Cassandra scales writes horizontally; PostgreSQL is easier but harder to shard for 100B msgs/day.
  • Fan-out vs pull for group messages: Fan-out to each member (1000 copies) is expensive for large groups. For 1000-member groups, fetch-on-read is more practical.

Bottlenecks

  • Hot conversations — rate-limit message sending per conversation
  • Media upload — use presigned S3 URLs; don't proxy media through chat servers
  • Notification fan-out — for large groups, batch and de-duplicate push notifications

Failure Scenarios

  • Chat server crash: client reconnects via WebSocket to any server. Messages queued in Kafka until delivery.
  • Kafka lag: delivery delayed but not lost — Kafka retains messages for 7 days.
  • DB unavailable: writes buffered in Kafka, processed when DB recovers.

Previous · Case study

Design Twitter / X

Next · Case study

Design Netflix