Problem Statement & Context
How Problem Statement & Context shapes architecture and interviewer follow-ups for Design Message Search.
Design Message Search — product and retrieval context
Design full-text search across chat history for a Slack/Discord/WhatsApp-class product: users query keywords, phrases, filters (channel, author, date, attachments), and receive ranked hits with snippets within seconds—even when history spans billions of messages and strict access control applies per hit.
Why interviewers ask this
- ACL at query time — every result must respect workspace membership, private channels, DMs, and legal hold without leaking metadata across tenants.
- Write amplification — each message edit/delete triggers index maintenance; search is a read-heavy path fed by an async indexing pipeline.
- E2EE tension — if message bodies are opaque on the server, you cannot run a classic centralized inverted index without a deliberate metadata or client-index strategy.
Scale anchors (stated assumptions)
| Signal | Assumption |
|---|---|
| DAU | 400M |
| Messages/day | 12B (~139k msg/s average) |
| Search queries | 80M/day (~930 QPS avg, 5× peak) |
| Index freshness SLA | p95 < 5s from message commit |
| Query latency SLA | p99 < 400ms for top-20 results |
Architecture headline
Message Service commits durable records → outbox → Kafka → Indexer bulk-writes OpenSearch shards routed by workspace_id. Search API authenticates the user, expands visible conversation_ids from a membership cache, executes a filtered BM25 query, post-processes highlights, returns cursor pages.
1 public record SearchHit(String messageId, String conversationId, double score, String snippet) {}
1 def acl_filter(conversation_ids: list[str]) -> dict: 2 return {"terms": {"conversation_id": conversation_ids}}
1 export interface SearchRequest { 2 query: string; 3 workspaceId: string; 4 filters?: { fromUserId?: string; before?: number }; 5 cursor?: string; 6 }
Why interviewers care
Message Search interviews reward crisp scope, explicit trade-offs, and failure stories—not generic microservice diagrams.
The failure that defines the design
The outage to narrate is the access-control leak: a search query returns a message from a conversation the user was never part of. Search systems are built to find everything fast, but private-message search must find only what the searcher is allowed to see — and if the ACL filter is bolted on after ranking, or the membership cache is stale after someone leaves a group, the index happily surfaces another person's messages. The fix is structural: ACL filtering is a mandatory, first-class part of every query, applied as a filter the index enforces, never a post-process. A message-search system lives or dies on never returning a result the user cannot legitimately see.
Key Highlights
- •Problem Statement & Context: decisive interview anchor
- •ACL enforced in coordinator DSL, never UI-only
- •Async indexing with versioned idempotent upserts
Section Rescue Kit
Buzzwords to use:
Safe statements:
- "For Problem Statement & Context, I will quantify index lag and query p99 before picking shard counts."
- "I never return search hits outside membership—cache miss fails closed."