← Whatnot Interview Insights

Whatnot·Software Engineer·Onsite - System Design / Architecture·Senior

SeniorPrefer not to say
Jun 2026Remote

Summary

System design round at Whatnot for a software engineer role, focused entirely on building a direct messaging system for an e-commerce marketplace. Pretty deep dive, lots of follow-ups, and the multi-device consistency angle caught me more off guard than I expected.

Questions Asked (8)

Q1

Design a direct messaging system for an e-commerce marketplace where buyers and sellers can chat one-on-one, with real-time delivery when online and SMS/email fallback when offline.

System DesignTechnical Trade-offsAPI & Integrations
Author's notes

This is the core question and it ate up most of the session.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying functional and non-functional requirements, such as scale, latency, and delivery guarantees. Then propose a high-level architecture with real-time WebSocket connections and a fallback mechanism using a message queue and notification service. Dive into key components like data storage, presence tracking, and delivery guarantees, discussing trade-offs at each step.

Pro tip: Emphasize idempotency and message ordering to prevent duplicates and ensure conversations make sense, especially when falling back to SMS/email. Also, discuss how to handle offline users gracefully without blocking the sender.

1. Clarify Requirements

Ask about scale (DAU, messages per second), latency expectations, delivery guarantees (at-least-once, exactly-once), and fallback preferences (SMS vs email).

2. High-Level Design

Sketch the main components: API gateway, chat service, presence service, message queue, notification service, and databases. Explain how they interact.

3. Real-Time Delivery

Detail the WebSocket-based approach for online users, including connection management, heartbeats, and message routing.

4. Offline Fallback

Describe how to detect offline users and trigger SMS/email via a notification service, ensuring idempotency and retries.

5. Data Model & Trade-offs

Discuss database choices (e.g., Cassandra for messages, Redis for presence), consistency models, and trade-offs between latency, cost, and complexity.

Key Points to Mention

  • WebSocket for real-time bidirectional communication, with fallback to HTTP long-polling if needed.
  • Presence service using Redis or similar to track online/offline status with TTL heartbeats.
  • Message queue (e.g., Kafka, RabbitMQ) to decouple message ingestion from delivery and enable retries.
  • Idempotency keys to prevent duplicate messages when falling back to SMS/email.
  • Message ordering and delivery guarantees: use sequence numbers per conversation and at-least-once delivery with deduplication.
  • Scalability considerations: sharding by conversation ID, horizontal scaling of WebSocket servers, and rate limiting.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q2

Is the messaging strictly one-to-one, or should the data model account for group threads from the start?

System DesignData Modeling
Author's notes

They asked me to raise this as a clarifying question before diving in.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the product requirements and expected scale with the interviewer, then propose a flexible data model that supports both one-to-one and group threads from the start, explaining the trade-offs. Emphasize that designing for groups early avoids costly migrations later, but keep the initial implementation simple by leveraging a unified conversation model.

Pro tip: Demonstrate awareness of future features like read receipts, typing indicators, and message reactions, which are easier to support with a group-ready model. Also, mention that you'd validate assumptions with product managers to avoid over-engineering.

1. Clarify Requirements

Ask the interviewer about the product roadmap, expected user scale, and whether group messaging is a planned feature. This shows you don't make assumptions and align with business goals.

2. Evaluate Trade-offs

Discuss the pros and cons of designing for one-to-one only versus group-ready from the start, including development speed, complexity, and future migration costs.

3. Propose a Unified Model

Suggest a data model where a conversation can have multiple participants, with a type field to distinguish between direct and group threads. This abstracts the difference and simplifies code.

4. Address Scalability and Performance

Explain how the model handles high write throughput, message ordering, and efficient querying for both direct and group conversations, considering sharding and indexing strategies.

5. Outline Migration and Evolution

If starting with one-to-one, describe how to evolve the schema later with minimal disruption, such as adding a participants table and backfilling data.

Key Points to Mention

  • Unified conversation model with participants and type (direct/group)
  • Trade-offs between upfront complexity and future migration effort
  • Scalability considerations: sharding by conversation ID, message ordering, and read receipts
  • Product roadmap alignment and avoiding over-engineering
  • Data migration strategies if starting with one-to-one
  • Impact on features like notifications, typing indicators, and message reactions

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q3

What delivery semantics would you target: at-least-once with client deduplication, or exactly-once? Is any message loss acceptable?

System DesignTechnical Trade-offs
Author's notes

Said at-least-once with dedup by message ID, which is the right call, but I fumbled explaining why exactly-once is basically impossible in a distributed system without massive tradeoffs.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the business context and requirements, such as whether message loss is acceptable and what the cost of duplicates is. Then compare at-least-once with client deduplication and exactly-once, highlighting trade-offs in complexity, latency, and reliability. Finally, recommend a pragmatic approach based on the specific use case, often favoring at-least-once with idempotent consumers for simplicity and scalability.

Pro tip: Emphasize that exactly-once delivery is often a distributed systems myth; true exactly-once requires end-to-end coordination and is rarely worth the complexity. Instead, focus on idempotency and deduplication to achieve effectively-once semantics.

1. Clarify Requirements

Ask about the business impact of message loss and duplicates. Determine if the system can tolerate occasional loss or if every message must be processed.

2. Define Semantics

Explain at-least-once (messages may be duplicated but not lost) and exactly-once (no loss, no duplicates) in the context of the system.

3. Evaluate Trade-offs

Compare complexity, performance, and reliability. At-least-once with deduplication is simpler and more scalable; exactly-once requires transactional guarantees and can introduce latency.

4. Consider Implementation

Discuss how to implement deduplication (e.g., idempotent consumers, unique message IDs) and the challenges of exactly-once (e.g., distributed transactions, two-phase commit).

5. Make a Recommendation

Propose a solution based on the use case. For many systems, at-least-once with idempotent processing is sufficient and more practical.

Key Points to Mention

  • At-least-once delivery guarantees no message loss but may cause duplicates.
  • Exactly-once delivery is difficult to achieve in distributed systems and often requires significant overhead.
  • Client-side deduplication can be achieved using idempotent operations or unique message identifiers.
  • Message loss may be acceptable for non-critical data (e.g., analytics) but not for financial transactions.
  • Trade-offs include system complexity, latency, throughput, and cost.
  • Real-world systems often use at-least-once with idempotent consumers to achieve effectively-once semantics.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q4

Walk through how a client recovers a missed message after disconnecting mid-delivery, with no loss and no duplicates.

System DesignTechnical Trade-offsAlgorithms & Data Structures
Author's notes

This was the hardest follow-up for me.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the delivery semantics and constraints (e.g., at-least-once vs exactly-once, message ordering, client capabilities). Then describe a protocol where the client acknowledges messages only after processing, and on reconnect, it resumes from the last acknowledged offset or uses idempotent processing with deduplication. Finally, discuss trade-offs and how to handle edge cases like partial acknowledgments.

Pro tip: Mention that exactly-once delivery is impossible without idempotency or transactional coordination, so the practical solution is at-least-once delivery with client-side deduplication. This shows you understand the theoretical limits and real-world engineering trade-offs.

1. Clarify requirements and constraints

Ask about delivery guarantees, message ordering, client state persistence, and whether the system can tolerate duplicates. This sets the stage for a precise answer.

2. Design the acknowledgment protocol

Explain that the client sends an ack only after successfully processing a message, and the server tracks the last acknowledged offset per client. This ensures no loss if the client disconnects before acking.

3. Handle reconnection and resume

On reconnect, the client presents its last acknowledged offset (or the server uses a session token) to resume delivery from that point. This guarantees no messages are skipped.

4. Implement deduplication for exactly-once effect

Since the client may receive duplicates (e.g., if ack is lost), use a unique message ID and a client-side deduplication cache to discard already-processed messages, achieving effectively-once semantics.

5. Discuss trade-offs and edge cases

Cover trade-offs like storage overhead for deduplication, latency from acking, and handling partial acks or out-of-order messages. Mention alternatives like transactional outbox or idempotent consumers.

Key Points to Mention

  • At-least-once delivery with idempotent processing is the practical approach for no loss and no duplicates.
  • Client acknowledges messages only after processing to avoid loss on disconnect.
  • Server tracks per-client offset or uses a session ID to resume delivery.
  • Deduplication using unique message IDs and a client-side cache to handle duplicate deliveries.
  • Trade-offs: storage cost for deduplication, latency from acking, and complexity of exactly-once semantics.
  • Edge cases: lost acks, out-of-order delivery, and client state persistence across restarts.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q5

Two devices from the same user read the same conversation simultaneously and both try to advance the read cursor. How do you keep that state consistent?

System DesignData Modeling
Author's notes

Went with a compare-and-swap on the cursor value, take the max of the two positions rather than a blind overwrite.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the requirements: is the read cursor per-user or per-device, and what consistency guarantees are needed? Then propose a design that uses a monotonic, conflict-free update strategy (e.g., last-write-wins with versioning or CRDTs) and explain how to handle concurrent writes from multiple devices. Finally, discuss trade-offs and how to ensure eventual consistency without losing updates.

Pro tip: Emphasize that read cursors should be monotonic (never go backwards) and that you can use a simple 'max' merge strategy to resolve conflicts, which avoids complex coordination. Also mention that you might store the cursor per user, not per device, to simplify consistency.

1. Clarify requirements and constraints

Ask whether the read cursor is per-user or per-device, what consistency level is needed (strong vs eventual), and if the system must handle offline devices. This shows you understand the problem before jumping to solutions.

2. Choose a data model and conflict resolution strategy

Propose storing the cursor as a single value per user with a version or timestamp, and use a merge function like 'max' to resolve concurrent updates. Alternatively, consider a CRDT (e.g., grow-only set of read message IDs) if more complex semantics are needed.

3. Design the write path and concurrency control

Explain how updates are sent to the backend (e.g., via API with optimistic concurrency using ETags or version numbers) and how the server applies the merge. Mention using a database with atomic operations or a distributed store with last-write-wins.

4. Ensure consistency across devices

Describe how other devices learn about the updated cursor (e.g., via push notifications or polling) and how you handle stale reads. Highlight that eventual consistency is acceptable for read cursors and that monotonicity prevents regressions.

5. Discuss trade-offs and edge cases

Address scenarios like offline updates, clock skew, and network partitions. Compare approaches (e.g., LWW vs CRDT) in terms of complexity, latency, and correctness, and justify your choice for Whatnot's use case.

Key Points to Mention

  • Monotonic read cursor: updates should only advance, never regress, to avoid marking messages as unread.
  • Conflict resolution: use last-write-wins with timestamps or version numbers, or a 'max' merge function.
  • Data modeling: store cursor per user (not per device) to simplify consistency and reduce conflicts.
  • Concurrency control: optimistic concurrency with versioning or atomic database operations to handle simultaneous writes.
  • Eventual consistency: accept that devices may temporarily have different cursors, but converge quickly.
  • CRDTs: consider using a grow-only set or max-wins register for a more robust, conflict-free solution.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q6

How do you guarantee strict per-conversation message ordering when the store is sharded and multiple app servers might assign sequence numbers for the same conversation concurrently?

System DesignTechnical Trade-offsAlgorithms & Data Structures
Author's notes

Shard by conversation ID so one shard owns the sequence counter for a given conversation.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the requirements: strict per-conversation ordering means messages within a conversation must be totally ordered, but global ordering across conversations is not required. Then propose a solution that centralizes sequence assignment per conversation, such as routing all messages for a conversation to a single partition or using a distributed lock/consensus protocol, and discuss trade-offs like latency, scalability, and fault tolerance.

Pro tip: Mention that you can avoid distributed locks by using a per-conversation message queue (e.g., Kafka partition keyed by conversation ID) where a single consumer assigns sequence numbers, and highlight that this maintains ordering while scaling horizontally across conversations.

1. Clarify requirements and constraints

Confirm that ordering is only required per conversation, not globally, and identify the scale (number of conversations, messages per second) and consistency needs (e.g., strict vs. eventual).

2. Identify the core challenge

Explain that with sharded storage and multiple app servers, concurrent writes to the same conversation can lead to race conditions in sequence number assignment, causing out-of-order messages.

3. Propose a centralized sequencing mechanism

Suggest routing all messages for a given conversation to a single logical entity (e.g., a partition leader, a dedicated sequencer service, or a distributed lock) that assigns monotonically increasing sequence numbers.

4. Discuss implementation options and trade-offs

Compare approaches like per-conversation Kafka partitions, Redis INCR with Lua scripts, ZooKeeper/etcd locks, or database sequences, and analyze their impact on latency, throughput, and availability.

5. Address failure scenarios and scaling

Explain how to handle sequencer failures (e.g., leader election, replication) and how to scale by sharding conversations across multiple sequencers, ensuring no single point of contention.

Key Points to Mention

  • Per-conversation ordering vs. global ordering: only the former is needed, which allows sharding by conversation ID.
  • Use of a message broker like Kafka with partition key = conversation ID to guarantee ordered delivery to a single consumer.
  • Distributed locking or consensus (e.g., ZooKeeper, etcd) to serialize sequence assignment per conversation, with trade-offs in latency and complexity.
  • Optimistic concurrency control with version numbers and retries, but note that it may not guarantee strict ordering without additional coordination.
  • Database sequences or atomic counters (e.g., Redis INCR) scoped per conversation, ensuring atomicity.
  • Handling failures: replication of the sequencer, idempotent writes, and client-side ordering with server-side reconciliation.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q7

How would you extend this design to support group conversations without rewriting the core delivery path?

System DesignTechnical Trade-offs
Author's notes

Kept the same fan-out model but replace the single recipient with a participant list.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the existing core delivery path and its abstractions, then propose an extension that introduces a group abstraction layer without modifying the core. Focus on how to reuse the existing delivery mechanism by treating a group as a virtual recipient or by adding a fan-out step that is transparent to the core.

Pro tip: Emphasize backward compatibility and incremental rollout: show how you can add group support behind a feature flag and migrate gradually, minimizing risk to the existing system.

1. Clarify the current design

Ask questions to understand the core delivery path: what are the key components, interfaces, and assumptions? Identify what 'without rewriting' means in terms of constraints.

2. Identify extension points

Determine where group semantics can be layered on top of the existing path, such as at the message routing, fan-out, or storage layers, without altering the core logic.

3. Propose a group abstraction

Introduce a group entity that maps to multiple recipients, and design a fan-out mechanism that delivers to each member using the existing delivery path.

4. Address trade-offs and scalability

Discuss how the extension handles increased load, consistency, and failure scenarios. Consider options like asynchronous fan-out, batching, or sharding.

5. Plan for rollout and monitoring

Outline a migration strategy with feature flags, A/B testing, and metrics to ensure the core path remains unaffected and performance is maintained.

Key Points to Mention

  • Reuse of existing delivery path via a fan-out service or message queue
  • Group as a virtual recipient or distribution list abstraction
  • Idempotency and delivery guarantees for group messages
  • Scalability considerations: fan-out on write vs. read, batching, and rate limiting
  • Backward compatibility and feature flagging for gradual rollout
  • Monitoring and observability to detect regressions in the core path

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q8

How do you make offline SMS and email notifications idempotent and debounced so a user offline for an hour with 20 messages doesn't receive 20 separate texts?

System DesignTechnical Trade-offsAPI & Integrations
Author's notes

Aggregate notifications with a short delay window, say 30 seconds, and send one summary rather than one per message.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the requirements and constraints, then propose a solution that combines idempotency (using unique message IDs and deduplication) with debouncing (batching notifications within a time window). Explain how you would handle offline users by queuing notifications and delivering a summary when they come online, while ensuring exactly-once delivery semantics.

Pro tip: Emphasize the importance of idempotency keys and a centralized notification service to avoid duplicate sends, and mention that debouncing should be configurable per user to balance timeliness and spam reduction.

1. Clarify Requirements and Constraints

Ask about the expected scale, latency requirements, and whether the user can receive a summary or must get individual messages. Confirm that the goal is to reduce notification spam while ensuring no critical messages are lost.

2. Design Idempotent Delivery

Use unique message IDs and an idempotency key (e.g., user ID + message ID) to deduplicate. Store sent notifications in a database with a unique constraint to prevent duplicates, and use a message queue with at-least-once delivery and consumer deduplication.

3. Implement Debouncing and Batching

Introduce a debounce window (e.g., 5 minutes) where notifications for a user are aggregated. Use a scheduler or delayed queue to hold notifications and send a single summary after the window expires or when the user comes online.

4. Handle Offline Users and State Management

Track user online/offline status and queue notifications accordingly. When the user comes online, deliver a consolidated summary. Ensure the queue is durable and can survive restarts.

5. Discuss Trade-offs and Edge Cases

Address trade-offs between latency and spam reduction, and how to handle urgent messages that bypass debouncing. Consider failure scenarios like duplicate sends due to retries and how to monitor and alert on them.

Key Points to Mention

  • Idempotency keys and unique constraints to prevent duplicate sends
  • Debouncing with a time window and batching notifications into a summary
  • Use of a message queue (e.g., Kafka, SQS) with deduplication logic
  • User presence tracking to trigger delivery when user comes online
  • Configurable debounce intervals per user or notification type
  • Monitoring and alerting for duplicate notifications and delivery failures

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.