Design a Scalable Calendar Service
Company: Uber
Role: Frontend Engineer
Category: System Design
Difficulty: medium
Interview Round: Technical Screen
Design an online calendar service (think Google Calendar) that supports both **individual** and **shared** calendars.
Users must be able to create, update, delete, and view events across **day, week, month, and agenda** views. The service must also support:
- inviting attendees and tracking their responses (accept / decline / tentative),
- shared-calendar permissions (owner / writer / reader / free-busy-only),
- recurring events with exceptions (edit one instance, this-and-following, or the whole series),
- time zones and daylight-saving transitions,
- reminders across channels (push, email, in-app),
- conflict warnings (double-booking), and
- free/busy availability checks across one or more users.
Because this is a **Frontend Engineer** interview, weight the design toward the **client experience** — the rendering and state model, optimistic mutations, and the API contract the frontend depends on — while still covering the backend services, data model, scalability, consistency, and edge cases that make those client features correct.
```hint Where to start
Separate the two hard axes: (1) the **time/recurrence** model — how a single recurrence rule plus a small set of override rows expands into the instances a view needs; and (2) the **client rendering/state** model — how a normalized local store feeds the four views and absorbs optimistic edits. Most of the interesting tradeoffs live in one of these two.
```
```hint Recurrence
Never materialize an unbounded series. Store an **RRULE** (frequency, interval, BYDAY, UNTIL/COUNT) plus per-instance **exception/override** rows, and expand the rule only for the requested time window. Keep the canonical recurrence anchored in the event's **local time zone**, not UTC, so DST shifts land correctly.
```
```hint Frontend state & API
Think about what one `GET .../events?start=&end=` call returns and how the client caches it per visible range. A **normalized store** (calendars, events, attendees, instances keyed by id) plus virtualized rendering keeps re-renders cheap. For mutations, reach for **optimistic updates** reconciled against the server's authoritative version.
```
```hint Consistency
Concurrent edits to the same event are the classic trap. An **optimistic-concurrency `version`/ETag** on the event (reject stale writes, prompt to merge) plus an idempotency key on create covers most of it; RSVP can be last-write-wins per attendee.
```
### Constraints & Assumptions
- Assume a large consumer scale: on the order of **hundreds of millions of users**, each with several calendars; reads (rendering views) dominate writes by a wide margin (~100:1 is a reasonable assumption to state).
- Calendar load for the visible range should feel instant — target **p99 < 200 ms** for an events-in-range read; reminders should fire within a small bounded delay of their scheduled time.
- High availability is more important than strict global consistency: a brief delay in a collaborator seeing your edit is acceptable; losing or corrupting an event is not.
- All event times are stored canonically in **UTC** with the event's intended **IANA time zone** preserved alongside.
- Authentication, the user/identity service, and raw push/email delivery infrastructure are out of scope — assume they exist.
### Clarifying Questions to Ask
- **Scale & read/write mix** — How many users, calendars per user, events per calendar, and what is the read:write ratio? Are there "super calendars" (large org/shared) that change the partitioning story?
- **Collaboration model** — Is real-time collaborative editing (multiple writers on one event simultaneously) required, or is single-writer-at-a-time with conflict detection sufficient?
- **Offline support** — Must the client work fully offline (create/edit while disconnected, sync later), or only degrade gracefully?
- **Interop** — Do we need to import/export iCalendar (.ics), subscribe to external feeds, or interop with other providers' free/busy?
- **Notification SLA** — How tight is the reminder delivery window, and which channels are in scope?
- **Privacy granularity** — Does free/busy hide event details from people without read access, and are there private/"hidden details" events on shared calendars?
### What a Strong Answer Covers
A strong answer is judged on the following dimensions (these are the areas to cover, not the answers themselves):
- **Requirements & scoping** — separates functional from non-functional, states scale assumptions, and uses clarifying questions to bound the problem before designing.
- **Time-zone & recurrence correctness** — a defensible model for UTC-vs-local storage, RRULE expansion windows, and per-instance exceptions, with DST and all-day events handled deliberately.
- **Frontend architecture** — a normalized client store, virtualized rendering for dense views, range-based fetching/caching, and optimistic mutations with reconciliation; the major UI states are enumerated.
- **API & data model** — clean resource design for calendars/events/attendees/permissions, a range-query endpoint, and an idempotent, version-aware write path.
- **Consistency & concurrency** — how concurrent edits, RSVP races, and idempotent creates are handled, and where eventual consistency is acceptable.
- **Scalability** — partitioning/sharding choice, the right indexes for range queries, caching of hot ranges, async fan-out for notifications/search, and free/busy precomputation.
- **Edge cases & failure handling** — DST, cross-midnight and all-day events, permission changes mid-flight, reminder retries, deleted attendees, and recurring events with no end.
### Follow-up Questions
- How would you implement **"edit this and all following events"** on a recurring series at the data-model level, and what does it cost in extra rows or rule splits?
- A shared team calendar has **50,000 events in the visible month** and the month view is janky. Walk through how you'd diagnose and fix the frontend rendering and the data-fetch path.
- How do you compute **free/busy across 20 attendees** for a 30-minute slot efficiently, and what do you precompute vs. compute on demand?
- A user in `America/New_York` creates a weekly 9am event, then **moves to `Asia/Tokyo`**. What happens to past and future instances, and what's the right product behavior?
Quick Answer: This question evaluates a candidate's ability to design a scalable, user-facing calendar system, covering frontend experience, backend services and APIs, data modeling, and features such as recurrence, time zones, permissions, reminders, and availability checks.