Design a Collaborative Todo List
Company: Asana
Role: Software Engineer
Category: System Design
Difficulty: medium
Interview Round: Onsite
Design a **collaborative todo-list service** — think shared lists where teammates add, edit, assign, reorder, and complete items, and see each other's changes propagate in near real time across web and mobile.
The service must support: creating shared lists; adding and editing todo items; assigning an owner to an item; setting due dates; reordering items within a list; marking items complete; and showing other collaborators' updates in near real time. Your design should explicitly address the data model, the read/write path, real-time synchronization, concurrent editing, permissions, and the consistency trade-offs you choose.
```hint Where to start
Scope before you draw boxes: separate the **must-haves** (shared list/item CRUD, real-time fan-out, per-list permissions) from the **nice-to-haves** (offline replay, notifications, comments). State explicit functional and non-functional requirements, then pick your consistency model deliberately rather than defaulting to "eventually consistent."
```
```hint Ordering the changes
The crux of real-time collaboration is deciding **what counts as "the next change"** when several arrive at once. How could you give every accepted change on a list a single agreed-upon order that all clients — including one that's been offline — can reason about? Whatever you choose, ask: how does a reconnecting client express "give me everything after the last change I saw" with a single cursor, and what happens when the history behind that cursor gets large?
```
```hint Concurrent edits & reordering
Before reaching for heavyweight machinery, ask **what conflicts you actually have** — and whether every kind of edit really deserves the same treatment. Does changing a field, removing an item, and changing where an item sits in the list each pose the same problem, or different ones? For ordering specifically: what goes wrong if positions are dense integers and two people move items at the same time? And does the order in which the server accepts changes affect how hard the merge is?
```
```hint Delivering the change
How does a committed mutation reach other connected clients? Consider persistent connections (**WebSocket** / SSE) on a collaboration tier, fed by a **message bus** so the write path and the fan-out path are decoupled. Watch the gap between "DB committed" and "message published" — what pattern guarantees the published event isn't lost if the bus is briefly down?
```
### Constraints & Assumptions
- **Scale:** consumer / team-product scale — on the order of **millions of users** and **tens of thousands of concurrent collaborators** active at once.
- **Lists are mostly small:** the typical list has tens to low hundreds of items, though a few "hot" lists may have many concurrent editors.
- **Latency target:** an edit by one collaborator should appear on another connected collaborator's screen in well under a second in the common case (assume a soft target of ~500 ms).
- **Clients:** web and native mobile; mobile clients may go offline or have intermittent connectivity.
- **Durability:** no silent data loss; shared workspaces need an auditable history of who changed what.
- Treat **offline support**, **notifications**, and **comments** as in-scope if time permits, but core CRUD + real-time sync + permissions are the must-haves.
### Clarifying Questions to Ask
- Do we need full collaborative *text* editing inside an item's description (character-level OT/CRDT), or is item-level / field-level granularity sufficient?
- What permission roles exist (owner / editor / commenter / viewer), and can permissions be set per-list, per-workspace, or both?
- How strong does offline support need to be — best-effort replay on reconnect, or a guarantee that offline edits never silently lose to concurrent online edits?
- What is the expected read:write ratio and the size distribution of lists (so we know whether to optimize for many tiny lists vs. a few huge hot ones)?
- Are notifications (assignment, due date, comments, completion) required for launch, and through which channels (in-app, push, email)?
- What is the data-retention / audit requirement for shared workspaces?
### What a Strong Answer Covers
- **Requirements split:** clear functional vs. non-functional requirements, with the latency/consistency targets stated as numbers, not adjectives.
- **Data model:** users, lists, memberships/roles, items (with assignee, due date, position, completion), comments, and whatever structure records the history of changes; sensible keys and how data is partitioned.
- **API surface:** REST/RPC for CRUD plus a real-time subscription contract with a resumable cursor so clients can catch up after a disconnect.
- **Write path:** auth → permission check → a transactional apply that keeps the materialized state and the change history in agreement → publish → fan-out, with idempotency on retries.
- **Real-time sync & catch-up:** initial snapshot plus incremental sync from a resume cursor, and sensible behavior when the history behind that cursor has been compacted away.
- **Concurrency model:** an explicit, justified per-field / per-op-type stance on how concurrent edits converge, with a clear position on when heavyweight machinery (CRDT/OT) is warranted versus when simpler techniques suffice — rather than hand-waving "we'll use CRDTs."
- **Scaling:** sharding strategy, hot-list handling, caching of active state, and back-pressure for slow clients.
- **Reliability & safety:** outbox/exactly-once-ish publishing, idempotent mutations, authorization on every operation, encryption.
- **Observability:** the specific metrics that tell you sync is healthy (fan-out latency, change-stream/replication lag, conflict/rebase rate, disconnects).
### Follow-up Questions
- How would your design change if a single "hot" list had **thousands** of simultaneous editors instead of tens? Where does per-list serialization become the bottleneck, and how do you relieve it?
- Walk through an **offline client** that made three edits while disconnected, two of which conflict with edits committed by others in the meantime. How does it reconcile on reconnect, and what does the user see?
- How do you keep the **operation log** from growing without bound while still letting a client that's been offline for days catch up correctly?
- If you needed to add **collaborative rich-text editing** of an item's description, what would you change, and why is that a meaningfully harder problem than syncing the item fields?
Quick Answer: This question evaluates system-design skills for building real-time collaborative applications, covering data modeling, read/write paths, real-time synchronization, concurrent edits and reordering semantics, permission models, and consistency trade-offs within the System Design domain.