Practice/Microsoft/Design a Calendar App
Design a Calendar App
System DesignMust
Problem Statement
Design a task management platform similar to Asana or Trello where teams collaborate on projects. Users create tasks, assign them to teammates, set deadlines, add comments, and track progress through workflow stages. The system must support real-time collaboration so that when one user updates a task, others see changes immediately. Teams range from small startups with ten users to enterprise organizations with tens of thousands of users across multiple projects.
Your design should handle high read traffic as users frequently view project boards and task lists, ensure that concurrent updates don't corrupt data, and reliably deliver notifications when tasks are assigned or status changes. Consider how to model relationships between projects, tasks, subtasks, and users, how to scale queries that filter and sort tasks by multiple criteria, and how to keep the UI responsive even when projects contain thousands of tasks.
Key Requirements
Functional
- Task lifecycle management -- users create tasks with title, description, assignee, due date, priority, and tags; tasks move through customizable workflow stages
- Hierarchical organization -- tasks belong to projects, can have subtasks, and support attachments and comment threads
- Real-time collaboration -- multiple users viewing the same project see updates instantly when tasks are created, edited, or moved
- Search and filtering -- users query tasks across projects by assignee, due date, status, tags, and text content
- Activity tracking -- the system logs all changes to tasks for audit trails and activity feeds
Non-Functional
- Scalability -- support 100,000+ concurrent users with 10 million active tasks; handle 5,000 task updates per second during peak hours
- Reliability -- ensure no task updates are lost; notification delivery should be at-least-once with idempotent handling
- Latency -- task list and board views load in under 300ms; real-time updates propagate to connected clients within 2 seconds
- Consistency -- prevent conflicting concurrent edits; users should see a coherent view of task state even under high contention
What Interviewers Focus On
Based on real interview experiences, these are the areas interviewers probe most deeply:
1. Data Modeling and Query Patterns
The interviewer wants to see how you structure tasks, projects, users, and comments to support both transactional writes and complex read queries. A naive schema becomes a bottleneck when filtering thousands of tasks by multiple fields or rendering deeply nested subtask hierarchies.
Hints to consider:
- Store denormalized copies of frequently accessed fields like assignee name and project title directly on tasks to avoid joins on hot paths
- Use adjacency lists or nested sets for subtask hierarchies depending on whether you optimize for writes or reads
- Maintain separate indices optimized for common query patterns like "my open tasks" or "overdue in this project"
- Consider sharding by project_id if single projects grow large enough to hit storage or query limits
2. Handling Concurrent Updates and Conflict Resolution
Multiple users may simultaneously edit the same task's fields or move it between workflow stages. The interviewer expects you to articulate a strategy for detecting conflicts, merging changes, or rejecting stale updates without locking the UI or corrupting state.
Hints to consider:
- Use optimistic locking with version numbers or timestamps; reject writes that don't match the current version
- Apply operational transformation or CRDTs for rich-text comment fields where concurrent edits should merge automatically
- Implement idempotency keys for all mutations so retries don't duplicate comments or create phantom tasks
- Clearly define whether last-write-wins is acceptable for certain fields or whether you need more sophisticated conflict resolution
3. Real-Time Synchronization Architecture
Users expect to see task changes instantly without refreshing. The interviewer will probe how you push updates to connected clients efficiently, handle backpressure when a user reconnects after being offline, and ensure consistency between the real-time stream and database state.
Hints to consider:
- Use WebSockets or Server-Sent Events to push task deltas to subscribed clients; scope subscriptions to specific projects to limit fanout
- Maintain a Change Data Capture stream from your database or publish events via an outbox pattern to decouple persistence from notification
- Implement sequence numbers or logical clocks so clients can detect gaps and request missed updates when reconnecting
- Cache active subscription metadata in Redis to quickly route events to the correct WebSocket connections
4. Notification and Activity Feed Generation
When a task is assigned or commented on, relevant users need notifications across email, push, and in-app feeds. The interviewer wants to see how you fan out notifications reliably, deduplicate redundant events, and let users customize notification preferences without blocking the main write path.
Hints to consider:
- Decouple notification delivery from task updates by publishing events to a message queue for async processing
- Maintain per-user preference mappings in a fast key-value store so you can filter notification targets before sending
- Use batching windows to aggregate multiple updates to the same task into a single notification within a time window
- Track delivery state and implement retry logic with exponential backoff for transient failures in email or push gateways
5. Scaling Read-Heavy Workloads
Task lists and project boards are queried far more often than they are updated. The interviewer expects you to discuss caching strategies, read replicas, and indexing approaches that keep query latency low even as data volume grows.
Hints to consider:
- Cache rendered task lists by project and filter criteria in Redis with short TTLs; invalidate on writes affecting that project
- Use read replicas for analytics and reporting queries to offload the primary database
- Precompute aggregate views like "count of tasks by status" and update them incrementally on task state changes
- Partition historical tasks from active ones so queries on current work don't scan large inactive datasets