Message Reactions: Problem Statement and Interview Framing
How Message Reactions: Problem Statement and Interview Framing shapes architecture and interviewer follow-ups for Design Message Reactions.
Message Reactions: Problem Statement and Interview Framing
Frame reactions as lightweight social signals on immutable messages—Slack emoji rows, Discord super-reactions, Messenger tapbacks—not as a second messaging channel. In Slack and Discord, reactions are social feedback without spawning new messages—they reduce channel noise while signaling consensus, humor, or acknowledgment. Your design must keep per-user-per-emoji uniqueness, make counts converge under concurrent adds, and fan out efficiently to thousands of viewers on viral posts.
Design mechanics for section 1
Treat every reaction toggle as an append-only event with a stable idempotency key derived from (message_id, user_id, emoji, client_op_id). The command handler validates message visibility, membership in the channel, and emoji allowlists before persisting. Aggregates are a projection, not the source of truth—if Redis and Postgres disagree, replay events from the log.
For viral messages, shard counters by hash(message_id, emoji) across N Redis cells; merge at read time. Cap who-reacted list payloads to 20 user IDs plus “+1.2K”; full list loads on demand. Threaded messages inherit parent channel ACLs; reaction notifications usually target thread participants only.
Operations and SLO anchors
Target p99 add latency 250ms end-to-end in-region; aggregate visibility within 1.5s at p99 under normal load. Alert on aggregate_drift_count, reaction_fanout_lag_ms, and hot_shard_skew_ratio. During incidents, disable who-reacted expansion first, then throttle custom emoji uploads, never drop add acknowledgements silently.
Interview pivots unique to §1
If pressed on cost, cite 3.6B events/day and counter cache memory math. If pressed on Facebook/Discord “super reactions,” explain paid bursts as rate-limited weighted counters with separate billing idempotency. If asked about moderation, describe admin purge as tombstone events that subtract counts deterministically.
Section 1 synthesis
Message Reactions: Problem Statement and Interview Framing should connect back to the invariant: one membership row per (message, user, emoji), monotonic version numbers on aggregates, and batched real-time delivery. Mention how this differs from read receipts (state machine) and typing indicators (ephemeral soft state)—reactions are commutative toggles with compact summaries.
1 public record ReactionEvent(String messageId, String userId, String emoji, boolean added, String idempotencyKey) {}
1 def reaction_dedupe_key(message_id: str, user_id: str, emoji: str) -> str: 2 return f"{message_id}:{user_id}:{emoji}"
1 export interface ReactionSummary { emoji: string; count: number; userIdsSample: string[]; } 2 export function mergeReactionDelta(prev: ReactionSummary[], delta: ReactionSummary): ReactionSummary[] { 3 return prev.map((r) => (r.emoji === delta.emoji ? { ...r, count: r.count + delta.count } : r)); 4 }
Why interviewers care
Message Reactions 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 hot-counter meltdown on a viral message. A celebrity post or a company-wide announcement gets millions of reactions in minutes, all incrementing the same (message, emoji) counter — and a single naive row or key becomes a write hotspot that throttles and skews latency for everyone. The fix is structural: shard the counter (sum of per-shard sub-counters), treat counts as eventually consistent (approximate is fine for a reaction tally), and dedup membership separately. A reactions system lives or dies on absorbing a flood of writes to one hot message without making the count a contended bottleneck.
Key Highlights
- •§1: Frame reactions as lightweight social signals on immutable messages—Slack emoji rows, Discord super-reactions, Messenger tapbacks—not as a second messaging channel.
- •Unique (message,user,emoji) membership drives counts
- •Event log enables replay after cache loss
- •Shard hot counters; batch WebSocket deltas
Section Rescue Kit
Buzzwords to use:
Safe statements:
- "I will draw the idempotent add/remove API before the database schema."
- "I will quantify reaction amplification before choosing cache sizes."