# Chat Service Low-Level Design: Message Storage, Delivery Guarantees, and Read Receipts

Source: https://www.techinterview.org/post/3233469738/lld-chat-service/
Updated: 2026-06-30 · techinterview.org

## Message Schema

Every message is a structured record stored durably before any delivery is attempted:

- **message_id:** Snowflake ID — 64-bit integer encoding timestamp, datacenter ID, and sequence number. Time-sortable without a secondary sort key.

- **conversation_id:** identifies the 1:1 or group conversation thread

- **sender_id:** authenticated user who created the message

- **content:** text payload or reference to media object in blob storage

- **type:** text | image | file | voice | system

- **status:** SENT | DELIVERED | READ (updated as delivery progresses)

- **created_at, deleted_at:** soft delete via `deleted_at` timestamp

## Message Storage

Cassandra is well-suited for chat message storage:

- Partition key: `conversation_id` — all messages for a conversation land on the same partition

- Clustering key: `message_id DESC` — messages stored in reverse chronological order within the partition

- Append-only writes: chat messages are never updated in place (edits create new versions), so Cassandra's write-optimized SSTable structure is ideal

- Time-range queries: fetch last N messages with `WHERE conversation_id = ? AND message_id < ? LIMIT 50` — efficient with the clustering key

## Delivery Flow

The sequence from send to delivery:

- Sender submits message to chat server over WebSocket or HTTP

- Chat server persists message to Cassandra with status SENT

- ACK sent back to sender — sender's UI updates message to SENT state

- Chat server looks up recipient(s)' connection routing table to find their WebSocket server

- Message forwarded to recipient's WebSocket server → pushed to recipient's connected client

- Recipient's client ACKs delivery → server updates status to DELIVERED

## Online Delivery via WebSocket

WebSocket provides a persistent, full-duplex connection between client and chat server. When the recipient is connected:

- The chat server pushes the message over the open WebSocket connection immediately

- No polling required — sub-100ms delivery latency is achievable

- Connection routing: a distributed hash table (Redis) maps user_id → WebSocket server address, allowing any chat server to forward to the correct server holding the recipient's connection

## Offline Queuing

When the recipient is disconnected, the message is persisted with status SENT and delivery deferred:

- On reconnect, the client sends its `last_seen_message_id`

- The server queries Cassandra for all messages in the conversation with `message_id > last_seen_message_id`

- Missed messages are replayed in order over the newly established WebSocket connection

## Message Ordering

Snowflake IDs provide total ordering without distributed coordination:

- The timestamp component (41 bits) ensures messages from different senders are ordered by wall clock time

- The sequence number component resolves ties within the same millisecond on the same generator node

- Clients sort received messages by message_id — lexicographic sort equals chronological sort

## At-Least-Once Delivery

The sender retries if it does not receive an ACK within a timeout (e.g., 5 seconds):

- Each message carries a unique `message_id` (client-generated or server-assigned)

- The server applies a unique constraint on `message_id` at the storage layer — duplicate submits are idempotent: the existing record is returned, not a new one created

- This guarantees at-least-once delivery without risk of duplicate messages appearing in the conversation

## Read Receipts

Read receipts allow senders to know when their message has been seen:

- When the recipient's client renders a message, it sends a read event: `{ conversation_id, last_read_message_id }`

- The server updates the recipient's `last_read_message_id` in a `conversation_members` table

- The server broadcasts the read event to other conversation members so their UIs can display read receipts

- Batch reads: clients batch read events into a single update rather than sending one per message to reduce write amplification

## Group Chat Fan-Out

In 1:1 chat, delivery is simple. Group chat requires delivering one message to N members:

- **Fan-out-on-write (small groups, <500 members):** write one copy of the message to each member's delivery queue immediately. Simple, low read latency.

- **Fan-out-on-read (large groups, >500 members):** store one copy of the message, members fetch it when they open the conversation. Avoids write amplification for very large groups (e.g., broadcast channels).

## Message Editing, Deletion, Push Notifications, and E2E Encryption

**Editing:** store a new version of the message content with an `edited_at` timestamp. Keep edit history for audit purposes. Clients display the latest version with an "edited" indicator.

**Soft deletion:** set `deleted_at` on the message record. Clients display "This message was deleted." No content is transmitted after deletion.

**Push notifications:** for offline users, send an APNs (iOS) or FCM (Android) push notification with a truncated message preview. The notification wakes the app, which then fetches the full message history via the offline queue mechanism.

**End-to-end encryption:** the sender encrypts message content with the recipient's public key before transmitting to the server. The server stores only ciphertext — it cannot read message content. Key exchange uses the Signal protocol (double ratchet algorithm) for forward secrecy.

See also: [Meta Interview Guide 2026: Facebook, Instagram, WhatsApp Engineering](https://www.techinterview.org/post/3233460272/meta-interview-guide-2026-facebook-instagram-whatsapp-engineering/)

See also: [Atlassian Interview Guide](https://www.techinterview.org/post/3233459919/atlassian-interview/)

See also: [Scale AI Interview Guide 2026: Data Infrastructure, RLHF Pipelines, and ML Engineering](https://www.techinterview.org/post/3233460275/scale-ai-interview-guide-2026-data-infrastructure-rlhf-pipelines-and-ml-engineering/)

See also: [Snap Interview Guide](https://www.techinterview.org/post/3233459923/snap-interview/)

See also: [Airbnb Interview Guide 2026: Search Systems, Trust and Safety, and Full-Stack Engineering](https://www.techinterview.org/post/3233460279/airbnb-interview-guide-2026-search-systems-trust-and-safety-and-full-stack-engineering/)
