Design: Real-Time Chat Flashcards
ADVANCED › System Design
- Why is WebSocket the usual primary transport for a chat app, and what backs it up?
- WebSocket gives a single persistent, full-duplex connection with low per-message overhead and server-push, ideal for foreground real-time chat. It is backed up by FCM push to deliver/wake the app when the socket is closed (backgrounded or killed).
- How does optimistic send work without creating duplicate messages on retry?
- The client generates a stable clientMessageId, inserts the message locally as 'pending', and renders it immediately. The same id is sent on every retry; the server treats it as an idempotency key and dedupes, then echoes back the canonical server id/sequence.
- What should be authoritative for message ordering, and why not the device clock?
- A server-assigned sequence number (or server timestamp) is authoritative. Client wall-clocks drift and can be wrong, so they cannot be trusted for global ordering across participants and devices; the client reorders to match the server sequence.
- Distinguish the delivery states and who sets each.
- pending (queued locally), sent (server ACKed receipt), delivered (recipient's device received it), read (recipient opened/viewed it). The sender sets pending; server ACK drives sent; recipient device emits delivered and read receipts back through the channel.
- How do you build a reliable offline send queue on Android?
- Persist unsent messages in Room with a pending status, attempt send over the live socket, and on failure retry with exponential backoff. Use WorkManager (or a reconnect handler) to flush the queue when connectivity returns; idempotency keys make replays safe.
- Why use cursor/keyset pagination instead of OFFSET for chat history?
- Cursor pagination requests messages before/after a stable boundary (message id or timestamp), so newly inserted messages don't cause page drift or duplicates/skips. OFFSET shifts as rows are added and gets slower for deep pages.
- Per Android's architecture guidance, what is the single source of truth for the message list?
- The local persistent database (Room) is the SSOT. The repository writes network/socket events into the DB, and the UI observes it via Flow/StateFlow, so the screen renders identically online or offline (offline-first, unidirectional data flow).
- How do you keep typing indicators and presence cheap on battery and bandwidth?
- Throttle/debounce them, batch with other low-priority signals, and auto-expire typing after a few seconds of inactivity. They are best-effort QoS-low events, sent below message traffic, never one network call per keystroke.
- Why can't you just keep a WebSocket open to receive messages in the background?
- Doze and App Standby suspend network and background work when the app isn't foreground, and the OS reclaims processes, so the socket dies. A high-priority FCM data message is the sanctioned way to wake the app and fetch/show the new message.