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: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
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
1. Client requests upload URL β /media/upload-url (pre-signed S3 URL)
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
4.5 Presence System: Online/Last Seen
Redis: {userId} β {chatServerId, lastSeen: timestamp}
TTL: 30 seconds (heartbeat every 10s from client)
lastSeen timestamp extracted when user disconnectsStep 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.