Design a Collaborative Todo List
AsanaSoftware Engineer · OnsiteLast updated
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.
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.
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?
Hints
Hint 1
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 2
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 3
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 4
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?
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?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.