System Design : Calendar App

Published: (January 6, 2026 at 03:41 PM EST)
3 min read
Source: Dev.to

Source: Dev.to

Functional Requirements

  • Create event, modify event, cancel event
  • View calendar daily, weekly, or yearly
  • Set up recurring meetings
  • Send notification for any change via email

Non‑Functional Requirements

  • High availability → consistency (eventual consistency for syncing events)
  • Should support 1 billion users
  • Low latency for viewing the calendar (read‑heavy > write‑heavy)

Data Models

  • User
  • Event
  • Recurrence

APIs

POST /events/

{
  "title": "Meeting title",
  "userId": "creator_id",          // creator
  "userIds": ["participant1", "participant2"], // optional list of attendees
  "startTime": "2025-01-10T15:00:00Z",
  "endTime": "2025-01-10T16:00:00Z",
  "content": {                     // JSON blob: video call link, description, etc.
    "videoCallLink": "https://example.com/meet/123",
    "description": "Discuss project status"
  },
  "recurrence": "weekly|biweekly|monthly|yearly" // optional
}

GET /events?startDay=&endDay=

Returns a list of events that fall within the requested date range.

High Level Design

(Overview of components, caching layer, database, and client synchronization.)

Deep Dives

1. Storing Daily or Recurring Events

Event Creation & Storage

Case 1 – Simple (One‑Time) Event
Example: Doctor Appointment

event_idowner_idtitlestart_time_utcend_time_utcrruletzversion
evt_101user_1Doctor Appointment2025‑01‑10 15:002025‑01‑10 16:00NULLUTC1

The row is returned and rendered directly; no expansion needed.

Case 2 – Recurring Event (Weekly)
Example: Team Sync

event_idowner_idtitlestart_time_utcend_time_utcrruletzversion
evt_201user_1Team Sync2025‑01‑06 10:002025‑01‑06 11:00FREQ=WEEKLY;BYDAY=MOUTC1

GET behavior (Week view) – fetch the base row, expand the rule only for the requested range, generate occurrences in memory.

Case 3 – Recurring Event with Exception (One Cancellation)
Example: Team Sync on Jan 20 cancelled

event_exceptions table:

exception_idevent_idexception_datetype
ex_301evt_2012025‑01‑20CANCELLED

GET behavior (Week of Jan 20) – expand the weekly rule, match the exception, drop that occurrence, and return the remaining events.

Storage Summary

  • One‑time event → 1 row
  • Weekly recurring for years → 1 row
  • Weekly + N exceptions → 1 + N rows

Result: minimal storage.

2. View Generation & Low Latency

User flow: Server sends a list of events to the client.

Optimization – Redis Cache

  1. Client requests events.
  2. Server checks Redis:
    • Cache hit → return cached events.
    • Cache miss → query the DB, populate Redis, return result.

Pros: fast reads, reduced DB load.
Cons: cache invalidation complexity, eventual consistency window.

Conclusion: Hybrid approach – client‑side expansion + SQLite for offline storage gives low latency and offline capability.

3. Conflict Detection & Locking Strategy

  • Optimistic Locking (default) – low contention, suitable for personal calendars; requires retry logic in the service.
  • Pessimistic Locking – for high‑contention calendars; locks multiple rows to avoid race conditions.

4. Multi‑Device Sync (Push & Pull)

  • Pull (Delta Sync) – used for cold start, reconnect, missed updates.
  • Push (SSE / Push Notifications) – fetch updated rule, re‑expand locally, update SQLite + UI. SSE is preferred: one‑way, lightweight, battery‑friendly.
  • Hybrid model – push for freshness, pull for correctness.

5. Database Choice: SQL vs NoSQL

Why SQL works well

  • Write volume is modest; relational databases scale adequately.
  • Transactions simplify conflict checks.
  • Recurrence queries (RRULE expansion) fit relational models.
  • Strong consistency (or configurable eventual) is easier to guarantee.

NoSQL trade‑offs

  • Conflict checks are hard without transactions.
  • Recurrence queries are a poor fit.
  • Consistency is eventual by default, adding complexity for correctness.
  • Higher implementation complexity for the same guarantees.
Back to Blog

Related posts

Read more »

System Design Quick Guide

System Design is the language of scale, and every engineer needs to speak it. I’ve created this 1‑page Quick Guide to help you decode complex system design topi...

EP 6.3: Master-Slave Architecture

Overview In system design, the Master‑Slave or Leader‑Follower architecture is a fundamental pattern used to achieve scalability and high availability, especia...

Consistent Hashing - System Design

📌 1 💥 The Core Problem: Traditional Hashing Breaks in Distributed Systems ❓ The Scenario In a distributed system many servers handling data we must decide wh...

Stop Writing APIs Like It's 2015

We're in 2025, and many codebases still treat APIs as simple “endpoints that return JSON.” If your API design hasn’t evolved past basic CRUD routes, you’re sacr...