Event Schema
The event is the core entity. It supports single and recurring events, multiple attendees, and rich metadata:
events {
event_id UUID PK
calendar_id UUID FK
title VARCHAR(255)
description TEXT
start_time TIMESTAMP WITH TIME ZONE -- stored in UTC
end_time TIMESTAMP WITH TIME ZONE
timezone VARCHAR(64) -- e.g. "America/New_York"
location VARCHAR(500)
recurrence_rule TEXT nullable -- RRULE string per RFC 5545
recurrence_exceptions DATE[] -- dates where normal occurrence is skipped
organizer_user_id UUID FK
visibility ENUM(public, private)
status ENUM(CONFIRMED, TENTATIVE, CANCELLED)
created_at TIMESTAMP
updated_at TIMESTAMP
}
event_attendees {
event_id UUID FK
user_id UUID FK nullable
email VARCHAR(255)
status ENUM(NEEDS_ACTION, ACCEPTED, DECLINED, TENTATIVE)
}
Timezone Storage
All times are stored in UTC in the database. The timezone field records the event's originating timezone. This is critical for recurring events: RRULE evaluation must happen in the event's timezone to correctly handle Daylight Saving Time transitions. A weekly event on Monday at 9am ET stays at 9am ET through DST changes — UTC offset varies, but local time is stable.
Recurring Events
Recurring events store a single master record with an RRULE string rather than pre-generating all instances. Example:
RRULE:FREQ=WEEKLY;BYDAY=MO,WE,FR;COUNT=12
RRULE:FREQ=MONTHLY;BYDAY=1MO;UNTIL=20241231T000000Z
Instances are generated on-demand when the calendar view requests a date range. The server evaluates the RRULE in the event's timezone, filters to the requested window, and returns the list of occurrence timestamps. Libraries like python-dateutil or rrule.js handle RRULE parsing.
Recurring Instance Modification
Two types of modifications to a recurring series:
- Single occurrence edit: add the occurrence date to
recurrence_exceptionson the master event; create a standalone modified_instance record with the exception date and changed fields. The master event's RRULE skips this date; the modified instance is served instead. - This and all future: set
UNTILon the original RRULE to end before the split date; create a new master event starting at the split date with the updated fields and a new RRULE.
Conflict Detection
To detect scheduling conflicts for a user, query their events for time overlap with the proposed slot:
SELECT e.event_id, e.title
FROM events e
JOIN event_attendees a ON e.event_id = a.event_id
WHERE a.user_id = :user_id
AND e.status != 'CANCELLED'
AND e.start_time < :new_end_time
AND e.end_time > :new_start_time
This interval overlap condition (start < other_end AND end > other_start) catches all overlapping cases. For recurring events, generated instances are checked against the proposed slot during RRULE evaluation.
Multi-Attendee Scheduling
Finding a free slot for multiple attendees works by computing the intersection of all their free windows:
- Query all events for each attendee within the search window
- Build a busy-time list per attendee
- Compute free intervals: subtract busy times from the full search window
- Intersect free intervals across all attendees
- Filter resulting slots by minimum duration and business hours
- Return ranked slot suggestions
iCal Import (RFC 5545)
Uploaded .ics files are parsed component by component. VEVENT components map to event records. VTIMEZONE components define timezone rules used to convert local times to UTC. Recurrence rules (RRULE, EXDATE) are stored as-is. ATTENDEE properties map to event_attendees rows. Duplicate detection uses the UID field from the iCal spec — if an event with that UID already exists, the import updates rather than duplicates it.
iCal Export and Calendar Subscription
Events are exported as RFC 5545 compliant .ics files. For calendar subscriptions, a user's calendar is served at a stable URL:
GET /calendars/{calendar_id}/feed.ics?token={private_token}
External calendar apps (Google Calendar, Apple Calendar, Outlook) poll this URL on a schedule to sync events. The feed includes all events in the calendar serialized as VEVENT blocks, with proper RRULE fields for recurring events.
Attendee Invitations
When an event is created with attendees, invitation emails are sent with Accept / Decline / Tentative links. Each link carries a signed token encoding {event_id, attendee_email, response}. Clicking the link updates the attendee's status and redirects to a confirmation page. The organizer sees real-time RSVP status updates as attendees respond.
Calendar Sharing
Calendars can be shared between users with two permission levels:
- View-only: shared user sees events but cannot create or edit
- Edit: shared user can create, modify, and delete events on the calendar
calendar_shares { calendar_id, shared_with_user_id, permission ENUM(view, edit) }
Private events (visibility = private) are shown as “Busy” blocks to view-only users, hiding title and description.
See also: Apple Interview Guide 2026: iOS Systems, Hardware-Software Integration, and iCloud Architecture
See also: Atlassian Interview Guide
See also: Scale AI Interview Guide 2026: Data Infrastructure, RLHF Pipelines, and ML Engineering