System design interviews are the gatekeeping round for senior software engineering roles. "Design a chat application" is asked at Google, Meta, Amazon, Swiggy, and Razorpay. This guide gives you a production-grade answer in 45 minutes.
๐ฏ Interview Framework: How to Structure Your Answer
Follow this 45-minute framework in every system design interview:
1. Clarify Requirements (5 min)
Estimate Scale (5 min)
High-Level Design (10 min)
Deep Dive on Components (15 min)
Handle Edge Cases (5 min)
Discuss Trade-offs (5 min)
Step 1: Clarify Requirements (5 min)
Always ask โ never assume. For a chat app, key questions:
- Functional Requirements:
- 1-1 messaging? Group chats? (max group size?)
- Text only, or media (images, voice, video)?
- Message delivery receipts (sent โ, delivered โโ, read ๐ต)?
- Online presence (last seen)?
- Push notifications for offline users?
- Non-Functional Requirements:
- How many daily active users?
- Message latency? (< 100ms for 1-1 chat)
- Data retention? (messages stored for how long?)
- Availability vs. Consistency trade-off?
- For this design: WhatsApp-scale
- 2 billion users, 100 million daily actives
- 1-1 and group chats (max 1000 members)
- Text + media (images, voice)
- Real-time delivery receipts
- 7-day message retention on server (E2E encrypted)
Step 2: Estimate Scale (5 min)
Users: 100M DAU
Messages: 40 messages/user/day = 4 Billion messages/day
Read:Write ratio = 1:1 (each message read by ~1 person on avg)
QPS (peak): 4B / (86,400s ร 0.2 peak factor) = ~230,000 msg/sec
Storage:
- Avg message: 1 KB (text) โ 4 TB/day (text only)
- With media (50% users send 1 image/day):
50M ร 100KB = 5 TB/day images
- Total: ~10 TB/day โ 3.6 PB/year
Connections: 100M concurrent WebSocket connections
Step 3: High-Level Architecture
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ CLIENTS โ
โ Mobile (iOS/Android) Web Browser Desktop App โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
Load Balancer (L7)
โ
โโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโ
โ โ โ
โโโโโโโโผโโโโโโโ โโโโโโโโโผโโโโโโโ โโโโโโโโผโโโโโโโ
โ Chat Server โ โ Chat Server โ โ Chat Server โ
โ (WS + HTTP)โ โ (WS + HTTP)โ โ (WS + HTTP)โ
โโโโโโโโฌโโโโโโโ โโโโโโโโโฌโโโโโโโ โโโโโโโโฌโโโโโโโ
โ โ โ
โโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโ
โ
Message Broker (Kafka)
โ
โโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโ
โ โ โ
โโโโโโโโผโโโโโโโ โโโโโโโโโผโโโโโโโ โโโโโโโโผโโโโโโโ
โ Message DB โ โ Presence DB โ โ Media Store โ
โ (Cassandra)โ โ (Redis) โ โ (S3/CDN) โ
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ
Step 4: Deep Dive โ Key Components
4.1 Real-Time Messaging: WebSockets vs. Long Polling vs. SSE
For real-time bidirectional communication, WebSockets win:
| Protocol | Direction | Latency | Overhead |
|---|---|---|---|
| WebSocket | Bidirectional | ~20ms | Low (after handshake) |
| Long Polling | Server โ Client | ~200ms | High (repeated HTTP) |
| SSE | Server โ Client only | ~50ms | Medium |
Client โโโโ HTTP Upgrade โโโโโ WebSocket Server
Client โโโโโ ACK โโโโโโโโโโโโโโ WebSocket Server
Client โโโโโ Message Frame โโโโโ WebSocket Server
Client โโโโ Message Frame โโโโโ WebSocket Server
Challenge at scale: 100M concurrent WebSocket connections. Each connection holds ~2MB memory โ 200 TB RAM needed if single-server. Solution: Connection Routing via Consistent Hashing.
Each user's WebSocket is maintained by a specific Chat Server. The Presence Service (Redis) maintains a {userId โ chatServerId} mapping. When Server A wants to send a message to a user on Server B, it routes through Kafka.
4.2 Message Flow: Alice Sends to Bob
1. Alice's app sends message over WebSocket to Chat Server A
Chat Server A:
a. Persists message to Cassandra (async)
b. Publishes to Kafka topic: user-bob-inbox
c. Sends ack back to Alice (โ sent)
Kafka delivers to Chat Server B (where Bob's WS lives)
Chat Server B:
a. Pushes message to Bob over WebSocket
b. Bob's app sends delivery receipt (โโ delivered)
If Bob is offline:
a. Kafka holds message (retention: 7 days)
b. Push Notification Service (FCM/APNs) wakes Bob's device
4.3 Database: Why Cassandra for Messages?
- Messages have specific access patterns:
- Write-heavy: Billions of writes/day
- Read pattern: Always by conversation: "get last N messages for conversation X"
- No complex joins: Chat apps don't do SQL JOINs
- Horizontal scalability: Must scale beyond single machine
Cassandra schema:
CODE
PREPHIT TRENDS LAB
messagesbyconversation (
conversation_id UUID, // Partition key
message_id TIMEUUID, // Clustering key (time-ordered)
sender_id UUID,
content TEXT,
message_type TEXT,
status TEXT,
created_at TIMESTAMP,
PRIMARY KEY ((conversationid), messageid)
) WITH CLUSTERING ORDER BY (message_id DESC);This design ensures all messages for a conversation are co-located on the same Cassandra node โ giving O(1) reads.
4.4 Media Storage: Images, Voice, Video
- Never store media in your chat database. Use:
- S3 (or GCS) for durable object storage
- CloudFront / Cloudflare CDN for global fast delivery
- Flow:
- Client uploads directly to S3 (bypasses your servers)
- Client sends message with mediaUrl in payload
- S3 triggers Lambda โ generates thumbnail โ stores in S3
- CDN caches thumbnail edge-side globally
1. Client requests upload URL โ /media/upload-url (pre-signed S3 URL)
4.5 Presence System: Online/Last Seen
Redis: {userId} โ {chatServerId, lastSeen: timestamp}
TTL: 30 seconds (heartbeat every 10s from client)
- If Redis has no key โ user is offline (TTL expired)
lastSeentimestamp extracted when user disconnects
Step 5: Edge Cases
| Problem | Solution |
|---|---|
| Chat Server crashes mid-message | Kafka ensures at-least-once delivery. Client de-duplicates by messageId |
| Message ordering in group chat | Use Cassandra TIMEUUID as message_id (includes timestamp) |
| Spam/abuse | Rate limit: 100 messages/min per user via Redis token bucket |
| E2E Encryption | Signal Protocol (same as WhatsApp). Keys exchanged client-side, server never sees plaintext |
| Slow consumers | Kafka consumer groups; each Chat Server reads its partition independently |
Step 6: Trade-offs to Discuss
Consistency vs. Availability:
"We choose AP (Availability + Partition Tolerance) over strong consistency. Message ordering is best-effort within a conversation โ acceptable for chat. We'd use stronger consistency only for financial transactions."
Push vs. Pull for offline messages:
"We use Kafka (push) because it scales better than polling. If we used pull, 100M offline users polling every 30s = 3.3M req/s just for empty responses."
๐ฏ Practice Makes Perfect
Record your answer to this question out loud in 45 minutes. You'll be surprised how often you skip important components.
Want to practice with AI feedback? PrepHit AI's mock interview feature evaluates your system design answers on Clarity, Technical Depth, and Structure โ just like a real interviewer.
Stop Getting Filtered. Fix Your Resume in 2 Minutes.
Don't apply with an unparsed resume. PrepHit scans your document against real 2026 recruiter ATS filters, highlights missing keywords, and gives you single-column ATS templates for instant export.