System Design Chat Application: Interview Talk Track
A system design chat application interview talk track is a classic mid/senior prompt: realtime delivery, fan-out, storage, and presence without boiling the ocean. Candidates commonly practice 1:1 messaging first, then group chat, typing indicators, and media as extensions. This guide is a structured script—from clarifying questions through APIs, data model, and tradeoffs—not a claim about any company’s confidential prompt.
Clarify before you draw
Ask and write assumptions:
- 1:1 only, or groups too? Max group size?
- Mobile + web? Offline delivery required?
- Message history retention? Search?
- Media (images/files) in scope?
- Read receipts / typing indicators?
- End-to-end encryption required, or transport TLS + server-side storage OK for this round?
- Scale ballpark (DAU, messages/sec)?
Talk track:
“I’ll start with reliable 1:1 text chat with offline inbox, then extend to small groups. Media via object storage and CDN. Presence and typing as best-effort. I’ll assume TLS in transit and server-stored history unless you want E2E as a constraint.”
Invite correction early. Scope control is part of the grade.
APIs (keep boring)
POST /v1/conversations→ create DM/groupPOST /v1/conversations/{id}/messages{ body, clientMsgId }→{ messageId, ts }GET /v1/conversations/{id}/messages?cursor=→ history page- WebSocket (or SSE):
message.new,message.ack,typing,presence - Optional:
POST /v1/attachments/upload-url
Idempotency: clientMsgId prevents double-send on retries.
Capacity sketch (order of magnitude)
Pick round numbers and show method:
- 50M DAU, 20 messages/user/day → ~10B messages/day peak planning with multipliers
- Average message ~200B metadata + text → storage grows fast; plan retention and cold tier
- Connections: millions of concurrent WebSocket sessions → connection gateway tier + sticky routing notes
Talk track:
“Writes are substantial but fan-out and concurrent connections dominate complexity. I’ll separate connection handling from message persistence.”
Redo arithmetic if they give different scale.
Core architecture
- Client → TLS → API / connection gateway
- Chat service validates, persists, enqueues delivery
- Message store (conversation-keyed)
- Push / gateway fan-out to online recipients; push notifications for offline
- Object store + CDN for media
- Presence service (ephemeral, often Redis-like)
Diagram narrative: ingest path vs delivery path vs history read path.
Fan-out: push vs pull
| Approach | Pros | Cons |
|---|---|---|
| Push fan-out on write | Fast delivery for small groups | Expensive for huge groups |
| Pull on read / inbox | Cheaper writes for large rooms | Higher read complexity |
| Hybrid | Fan-out small; pull for large | More moving parts |
Talk track:
“For 1:1 and small groups I’ll fan-out push to online sockets and write per-user inbox pointers. For very large rooms I’d switch to group-feed pull or hybrid.”
Candidates commonly report interviewers liking an explicit threshold discussion more than a single dogma.
Data model (starting point)
Conversation(id, type, created_at)Membership(conversation_id, user_id, role)Message(conversation_id, message_id, sender_id, body, ts, client_msg_id)- Secondary indexes:
(conversation_id, ts)for history; uniqueness on(sender_id, client_msg_id)
Ordering: server timestamp + tie-breakers; discuss clock skew briefly.
Delivery guarantees
Be precise:
- At-least-once delivery to devices is common; clients dedupe by
messageId/clientMsgId - Read receipts are async and best-effort unless required
- Online path: WebSocket; offline: store + push notification waking the app to sync
Talk track:
“I’ll aim for at-least-once with idempotent clients. Exactly-once end-to-end is rarely free; I’ll say where duplicates can appear and how we dedupe.”
Presence, typing, media
- Presence: heartbeat + TTL keys; do not block message path
- Typing: ephemeral pub/sub; rate-limit
- Media: presigned upload, virus scan async, CDN read; messages store URLs + metadata
Failure modes and tradeoffs
- Hot conversations → partition by conversation_id; cache recent pages
- Gateway restart → reconnect storms; backoff + session resume
- Partial fan-out failure → retry queue; never lose persist-before-ack if you promised durability
- Search → async indexer; not on the hot write path unless asked
Ordering and history pagination
Clients paginate backward with a cursor (ts, messageId). Discuss:
- Why offset pagination breaks under inserts
- How to merge pending local unacked messages with server history
- Retention: hot store for recent N days, cold object/DB tier later if asked
Talk track:
“Timeline keys stay append-friendly; clients sync with cursors, and unacked local messages reconcile via clientMsgId.”
Multi-device sync
Users have phone + desktop. Options:
- Per-user inbox with device sync cursors
- Push each device independently; read state stored server-side
- Conflict: last-writer-wins on edits; deletes are tombstones
Keep this as a short extension after 1:1 delivery works.
Soft practice note
Chat rounds reward structured narration more than buzzwords. If you want timed rehearsal of this system design chat application talk track under pressure, Luna Interview is built for calm practice—not for inventing production war stories or violating interview rules.
Day-of checklist
- [ ] Scope written (1:1 → groups → extras)
- [ ] APIs + idempotency key
- [ ] Persist-then-deliver order clear
- [ ] Fan-out strategy + large-group alternative
- [ ] Offline / push path named
- [ ] Storage keys and history pagination
- [ ] One reliability tradeoff stated aloud
Lead with clarity, then deepen. A clean 1:1 design with honest extensions beats an unfinished “full WhatsApp” sketch.
Rehearse with an AI interview copilot, then browse commonly reported interview questions.