Design the 3-column functionality (open / in progress / completed) of a Jira board
Model columns and cards as normalized state, render columns mapping over ordered card-id lists, implement drag-and-drop with optimistic reordering, persist moves to the server, and handle real-time multi-user sync, virtualization for big boards, and conflict resolution.
A Jira-style 3-column board is a drag-and-drop + ordered-lists + sync problem. The columns are easy; ordering, DnD, persistence, and collaboration are where the design lives.
Data model — normalized
columns: { open: { id, title, cardIds: [...] }, inProgress: {...}, done: {...} }
cards: { 'c1': { id, title, assignee, ... }, ... }
columnOrder: ['open', 'inProgress', 'done']Cards stored by id; each column holds an ordered array of card ids. Normalization makes moves O(1) and avoids deep nesting.
Rendering
- Map
columnOrder→<Column>; each column maps itscardIds→<Card>. - Memoize
<Card>(keyed by id) so moving one card doesn't re-render the whole board.
Drag and drop
- Use a library —
@dnd-kit(modern, accessible) orreact-beautiful-dnd/pragmatic-drag-and-drop. DnD with keyboard accessibility and auto-scroll is hard to hand-roll. - On drop: remove the card id from the source column's array, insert at the target index in the destination array. Two cases: reorder within a column, move across columns.
- Ordering at scale: for big boards, instead of reindexing every card, use fractional/lexicographic rank keys (a card gets a rank between its neighbors) so a move updates one card's rank, not the whole list.
Optimistic updates + persistence
- Update local state immediately on drop (instant feel), then
PATCHthe move to the server. - On failure → roll back and show an error.
- Server is the source of truth for order; reconcile with its response.
Real-time collaboration
- Multiple users move cards simultaneously → WebSocket broadcasting card-move events.
- Apply remote moves as targeted patches; don't yank a card out from under a user mid-drag.
- Conflict: two users move the same card — last-write-wins with a timestamp is usually acceptable for a board; surface "card moved by X" if needed. Rank keys make concurrent moves merge cleanly most of the time.
- Resync on reconnect (refetch board state).
Other concerns
- States: loading skeleton, empty column, error.
- Virtualization — a column with hundreds of cards should virtualize.
- WIP limits — block/warn when "In Progress" exceeds its limit.
- Accessibility — keyboard DnD, ARIA, focus management.
- Filtering/search — derived views over the same normalized state.
The framing
"Normalized state — cards by id, columns holding ordered id arrays. DnD via a library, with optimistic reorder on drop and a PATCH to persist; rank keys so a move touches one card not the list. Real-time sync over WebSocket applying remote moves as targeted patches, last-write-wins for conflicts. Plus virtualization, WIP limits, and keyboard accessibility."
Follow-up questions
- •Why use fractional rank keys instead of array indices for ordering?
- •How do you handle two users moving the same card at once?
- •How do optimistic updates work for a drag-and-drop move?
- •How would you keep a 500-card column performant?
Common mistakes
- •Deeply nested state (cards inside columns) making moves and updates painful.
- •Reindexing every card on each move instead of using rank keys.
- •No optimistic update — laggy drag that waits on the network.
- •Ignoring real-time conflicts and reconnection resync.
- •Hand-rolling DnD and missing keyboard accessibility.
Performance considerations
- •Normalized state + memoized cards bound the re-render blast radius. Rank keys make a move an O(1) single-card update. Virtualize large columns. Batch real-time patches to avoid render storms.
Edge cases
- •Concurrent moves of the same card by different users.
- •Dropping a card back in its original position.
- •A move that fails server-side after the optimistic update.
- •Empty columns as drop targets.
- •Very large columns needing virtualization.
Real-world examples
- •Jira, Trello, Linear board views.
- •@dnd-kit + a normalized store + WebSocket move events.