04QuestionsSlack
04 · Worked prompt
Slack
Design conversations, ordered delivery, offline sync, presence, search, and attachment storage.What a passing answer must show
100 points · 45 minutes
- 20pts
Scope the problem
0–5 minPrioritize the core flows, state the scale, and name the non-goals.
- 15pts
Define contracts
5–10 minIdentify durable entities, APIs, idempotency, and the source of truth.
- 30pts
Complete the diagram
10–25 minTrace one write path and one read path. Label the commit boundary and async work.
- 20pts
Lead one deep dive
25–38 minChoose the highest-risk trade-off and explain the mechanism, alternative, and cost.
- 15pts
Prove reliability
38–45 minWalk a failure, recovery, metric, bottleneck, and evolution path.
One complete box-and-arrow design
Design conversations, ordered delivery, offline sync, presence, search, and attachment storage.

Write
Desktop/mobile clients enters through Realtime/API edge. Conversation service owns validation and commits the durable record to Message log.
Propagate
Conversation topics separates the committed write from background work. Fan-out + indexers can retry safely while it builds Search/sync indexes.
Read
Sync/search API serves from Search/sync indexes, then checks authoritative state whenever freshness, policy, or correctness requires it. It also consults Object storage as an explicit dependency.
Say this first: Conversation owners assign sequence numbers; durable sync repairs every best-effort realtime delivery gap.
Open the full whiteboard ↗Explain every boundary before adding more boxes.
Conversation owners assign sequence numbers; durable sync repairs every best-effort realtime delivery gap.
Design conversations, ordered delivery, offline sync, presence, search, and attachment storage.
Concurrent connections · modest room rate · strict membership · offline retention. State average and peak load, stored bytes, bandwidth or open connections, and the growth horizon before choosing a partitioning strategy.
End-to-end walkthrough
Trace the architecture in this order.
- 01
Enter and classify the request
Desktop/mobile clients → Realtime/API edgeSend, sync, search enters over HTTPS / RPC. Realtime/API edge handles identity, admission, routing, and request context; it deliberately does not own domain truth.
- 02
Validate, then cross the commit boundary
Realtime/API edge → Conversation service → Message logConversation service receives the command, checks invariants and retry identity, then uses append seq N to update Message log. The user-visible mutation is accepted only after this boundary succeeds.
- 03
Move replayable work off the request path
Conversation service → Conversation topics → Fan-out + indexers → Search/sync indexesConversation service emits publish after commit; Fan-out + indexers uses consume and project / update to build Search/sync indexes. Consumers must tolerate duplicate delivery and stale retries because this path is asynchronous.
- 04
Serve reads from the right authority
Realtime/API edge → Sync/search API → Search/sync indexes / Message logSync/search API uses optimized read for the common, read-optimized path and strong read when correctness or repair requires authoritative state. The API must state the freshness promise instead of hiding it.
- 05
Contain the dependency boundary
Conversation service → Object storagedirect upload crosses into Object storage. Treat timeouts as ambiguous, use a deadline and idempotent retry or reconciliation, and keep the core state recoverable when the dependency is unavailable.
- 06
Deliver without changing the source of truth
Fan-out + indexers → Connection gateways → Desktop/mobile clientsFan-out + indexers uses fan-out; Connection gateways returns updates over WebSocket. Sequence IDs, reconnect cursors, and backpressure make delivery resumable without turning a socket into durable state.
Ownership ledger
Why each box exists—and what it must defend.
| Component | Owns | Why it exists | Interviewer probe |
|---|---|---|---|
| Realtime/API edgeAuth + connection ownership | Identity, admission, routing | Protects the system edge and attaches trusted context before domain work begins. | Timeout budgets, quotas, regional routing |
| Conversation serviceDedupe + allocate sequence | Write invariants and retry identity | Serializes or conditionally applies state changes before acknowledging success. | Concurrent writes, deduplication, hot ownership |
| Message logOrdered messages + edits | Authoritative durable state | Provides the one record used to resolve disputes, recover, and rebuild projections. | Partition key, replication, consistency |
| Conversation topicsCommitted message events | Durable asynchronous handoff | Absorbs bursts and lets slow or optional work retry independently of the request. | Ordering key, lag, retention, dead letters |
| Fan-out + indexersDeliver, notify, index | Replayable processing | Runs expensive, fan-out, or side-effecting work with leases and bounded retries. | Idempotency, poison work, autoscaling |
| Search/sync indexesAuthorized query views | Rebuildable query state | Shapes data for the dominant reads without weakening the write-side invariant. | Freshness, versioning, rebuild time |
| Sync/search APIRanges + authorized results | Read composition and freshness policy | Chooses authoritative or derived state and returns a stable client contract. | Fan-out, cache policy, partial results |
| Object storageAttachments + signed access | External capability, not local truth | Keeps a specialized or third-party concern behind a replaceable contract. | Ambiguous timeout, circuit breaking, fallback |
| Connection gatewaysLive events + receipts | Connection and delivery state | Separates open connections and fan-out pressure from durable domain state. | Reconnect, ordering, slow consumers |
Physical design
Name the database, shard key, indexes, and guarantees.
- Database + storage
- Cassandra/Scylla stores channel history; PostgreSQL stores workspace/membership metadata; object storage holds attachments; Redis holds presence.
- Partitioning / sharding
- Partition messages by channel_id + time bucket with one channel sequencer. Partition membership by workspace/user.
- Indexes
- Messages cluster by sequence/time; unique client_message_id; unread by user/channel cursor; search is a separate index.
- Replication + consistency
- Order is strong within a channel. Presence, search, unread counts, and remote fan-out are eventual and repair from sequence cursors.
- Cache, queue + recovery
- Channel-keyed pub/sub fans committed events to gateways; notification/search/analytics groups retry independently.
- Capacity math
- Estimate messages/sec, active sockets, channel-size distribution, largest fan-out, history bytes/day, and attachment egress.
- Alternative rejected
- SQL messages are fine initially; unbounded hot-channel history and retention favor time-bucketed wide-column storage at scale.
Deep-dive candidates
Pick one risk and explain the mechanism, alternative, and cost.
Ordering
Use one logical sequencer per conversation and no global order
Users care about room order, not worldwide serializationOffline sync
Return sequence gaps from durable history and use live delivery only as an optimization
Push notifications are not a message storeLarge channels
Fan out lightweight event IDs to gateway groups and hydrate from shared storage
Copying full messages per recipient wastes storage and complicates deletionFailure pressure test
Show detection, containment, recovery, and evidence.
Gateway disconnect
Reconnect and request after last durable sequence
gap repair volumeDuplicate send
Return existing message for client message ID
dedupe rateMembership revoked
Enforce current membership on history and attachment reads
denied stale-session reads- Functional requirements and non-goals
- Peak traffic, storage, bandwidth, and growth
- Entities, APIs, idempotency, and pagination
- Source of truth and consistency promise
- Partition key, replicas, caches, and hot spots
- Retries, backpressure, failover, and reconciliation
- Latency, saturation, correctness, and recovery metrics
- Security, migration, cost, and multi-region evolution
A four-part talk track
- Scope
“I’ll prioritize send messages and attachments and deliver in conversation order.”
- Scale
“The design changes around concurrent connections · modest room rate · strict membership · offline retention.”
- Decision
“Per-conversation order is sufficient; global order is unnecessary.”
- Risk
“The first failure I want to pressure-test is: Reconnect, duplicates, and membership changes can create gaps or unauthorized history.”
Reference details
Open these only after you can explain the diagram above without reading.
01Requirements and state lifecycle4 requirements
- Send messages and attachments
- Deliver in conversation order
- Support offline sync and multi-device read state
- Handle membership, search, presence, and large channels
Each transition must be durable, observable, and safe to retry.
02Data model and APIs4 entities · 3 interfaces
Core entities
conversation_id, membership_version, sequenceOwner: Conversation serviceconversation_id, sequence, message_id, sender, body_refOwner: Message loguser_id, conversation_id, read_through_sequenceOwner: Receipt storeattachment_id, digest, policy, stateOwner: Blob serviceExternal interfaces
/v1/conversations/{id}/messagesAppend an idempotent message
/v1/conversations/{id}/messages?after={sequence}Repair an ordered range
/v1/conversations/{id}/read_receiptsAdvance read cursor monotonically
03Deep dives and trade-offsChoose one
Ordering
Use one logical sequencer per conversation and no global order
Users care about room order, not worldwide serializationOffline sync
Return sequence gaps from durable history and use live delivery only as an optimization
Push notifications are not a message storeLarge channels
Fan out lightweight event IDs to gateway groups and hydrate from shared storage
Copying full messages per recipient wastes storage and complicates deletion04Failures, recovery, and evidence3 scenarios
Gateway disconnect
Reconnect and request after last durable sequence
gap repair volumeDuplicate send
Return existing message for client message ID
dedupe rateMembership revoked
Enforce current membership on history and attachment reads
denied stale-session reads05What makes the answer seniorInterviewer signals
- The acknowledgement point should be after durable append, not after every recipient receives it
- Presence is ephemeral; history is durable
- Sequence cursors unify ordering, pagination, and reconnect recovery
- Primary trade-off: Per-conversation order is sufficient; global order is unnecessary.
Can you redraw it from memory?
- Name the source of truth.
- Trace the write and read paths.
- Defend one trade-off.
- Recover from one failure.