System Design Interview Roadmap

System Design Interview Roadmap

System Design Walkthrough

Design Slack — Walkthrough

Aug 04, 2026
∙ Paid

The probe

Slack is WhatsApp + channels + threads + search.

The messaging core is identical to WhatsApp (WebSocket, Cassandra, delivery semantics). The probes unique to Slack: channel message fan-out (a channel with 10,000 members means one message = 10,000 deliveries), message threading (replies live in a separate namespace from channel messages), and full-text search over message history.

Step 1 — Clarify

- Direct messages only, or channels + DMs + threads? (Scope to channels + DMs) - Search over message history? (Yes — search is a major Slack differentiator) - Max members per channel? (Slack allows ~10K for standard, unlimited for Enterprise Grid)

- File sharing? (Yes — same object storage pattern as WhatsApp media) - SLO: message delivery < 200ms p99 within same workspace

Step 2 — Estimate

- 20M DAU × 200 messages/day = 4B messages/day = ~46K messages/sec - Average channel size: 50 members → fan-out 50 deliveries per message - Large channels (10K members): 1 message = 10K WebSocket pushes - Message retention: Slack keeps all history (unlimited on paid plans) → ~500 bytes/msg × 4B msgs/day × 365 days = ~730 TB/year

Get Access to GitHub Repo

Step 3 — API Design

WebSocket: wss://slack.com/connect (per workspace per device)

POST /v1/messages

Body: { channel_id, text, thread_ts (optional — reply), blocks[], files[] }

Idempotency-Key: header

Response: { ts (message timestamp, also its ID), channel_id }

GET /v1/channels/:channel_id/messages

Query: cursor, limit, oldest, latest (time range)

Response: { messages[], has_more, next_cursor }

POST /v1/search

Body: { query, channel_ids[], from_user, date_range }

Response: { messages: [{ts, channel_id, text, permalink}], total }

ts (timestamp) is Slack’s actual message ID — a Unix timestamp with microsecond precision, unique per channel.

Step 4 — Data Model

- messages (Cassandra): PARTITION BY channel_id, CLUSTER BY ts DESC — identical pattern to WhatsApp but scoped to channel

- threads: thread_ts (FK to parent message ts), reply messages in same table with thread_ts as additional cluster key

- channel_members: channel_id, user_id, joined_at — indexed both ways (channel→members for fan-out, user→channels for sidebar)

- search_index (Elasticsearch): message ts, channel_id, text, user_id, timestamp — updated async via Kafka consumer

- unread_counts (Redis): user_id:channel_id → {unread_count, last_read_ts} — updated on every message and read event

User's avatar

Continue reading this post for free, courtesy of System Design Roadmap.

Or purchase a paid subscription.
© 2026 SystemDR Inc · Privacy ∙ Terms ∙ Collection notice
Start your SubstackGet the app
Substack is the home for great culture