System Design: Design Calendly — Scheduling Platform, Availability, Booking, Timezone, Integration, Conflict Detection

Calendly automates scheduling for millions of professionals by eliminating the back-and-forth of finding a mutual time. Designing a scheduling platform tests your understanding of: availability computation across time zones, real-time conflict detection, calendar integration (Google/Outlook), and the booking workflow that prevents double-booking. This is a focused system design question that combines calendar complexity with real-time systems.

Availability Computation

The host defines their availability rules: “Monday-Friday, 9 AM to 5 PM Eastern, with 30-minute slots and 15-minute buffers between meetings.” The system computes available time slots for booking. Algorithm: (1) Generate candidate slots — from the availability rules, generate all possible 30-minute slots within the configured window (next 30 days). Monday 9 AM: 9:00, 9:45, 10:30, 11:15, … (accounting for 15-min buffer: each slot consumes 45 minutes total). (2) Subtract busy times — fetch the host connected calendar events (Google Calendar API, Microsoft Graph API). Any slot that overlaps with an existing event is removed. (3) Subtract already-booked Calendly events — check the Calendly booking database for this host. Remove booked slots. (4) Apply timezone conversion — display available slots in the booker timezone. The host is in Eastern; the booker is in Pacific. A 9 AM Eastern slot displays as 6 AM Pacific. (5) Apply meeting limits — “maximum 5 meetings per day.” If 5 are already booked on Tuesday: all remaining Tuesday slots are removed. (6) Return the final available slots for the selected date range. This computation runs on every page load of the booking link. It must be fast (< 500ms) and accurate (reflect real-time calendar state). Caching: cache the calendar busy times with a 2-minute TTL (calendar events rarely change minute-to-minute). Invalidate on webhook notification from the calendar provider.

Booking Flow and Double-Booking Prevention

When a booker selects a time slot and clicks “Confirm”: (1) Re-validate availability — the slot may have been booked by another person between page load and confirmation (race condition). Re-run the availability check for this specific slot. If no longer available: show “This time is no longer available. Please select another.” (2) Create a temporary hold — atomically mark the slot as “held” for 5 minutes (gives the booker time to fill in their details). Implementation: Redis SET slot_hold:{host_id}:{slot_start} {booker_session} EX 300 NX. The NX flag ensures only one person holds the slot. (3) Collect booker information — name, email, any custom questions configured by the host. (4) Confirm booking — create the booking record in the database. Create the calendar event on the host calendar (Google Calendar API: insert event). Send confirmation emails to both parties. Release the hold. If the booker abandons (does not confirm within 5 minutes): the hold expires, the slot becomes available again. Multi-calendar conflict: the host may have multiple calendars. Check ALL connected calendars for conflicts (work calendar + personal calendar). A slot is available only if it does not conflict with ANY connected calendar. Round-robin teams: for team scheduling, the system checks availability across all team members and assigns the meeting to the first available person. Load balancing: distribute meetings evenly across team members (not always the same person).

Calendar Integration

Calendly integrates with Google Calendar, Microsoft Outlook, and Apple Calendar. Integration provides: (1) Read busy/free — fetch existing events to compute availability. Google Calendar API: FreeBusy query returns busy intervals for a time range. More efficient than fetching all event details (privacy: Calendly only needs to know “busy” times, not what the events are). (2) Write events — when a meeting is booked, create an event on the host calendar with: title, time, location/video link, attendees (host + booker), and description (custom notes). (3) Real-time updates via webhooks — Google Calendar push notifications: when the host calendar changes (new event added, event deleted), Google sends a notification to Calendly. Calendly re-computes availability. This ensures: if the host blocks time on their calendar, the slot immediately disappears from their booking page. (4) Two-way sync — if the host deletes the calendar event: should the Calendly booking be cancelled? Configurable. Some hosts prefer deleting the calendar event without cancelling the meeting. OAuth scopes: Calendly requests minimal calendar permissions. Read: freeBusy (not full event details for privacy). Write: create/update/delete events created by Calendly. Calendly does not need access to all the host calendar events — just the ability to check if a time is busy and create new events. Token refresh: OAuth tokens expire. Calendly stores the refresh token and automatically refreshes before expiry. If the user revokes access: the integration breaks. Detect and notify the user to reconnect.

Event Types and Routing

A host can have multiple event types: “30-minute intro call,” “60-minute deep dive,” “15-minute quick sync.” Each event type has its own: duration, availability rules (maybe the 60-minute meeting is only available Tuesday/Thursday), buffer time, custom questions, and video conferencing link (Zoom auto-generation, Google Meet, or manual). Routing forms: a single booking link that asks qualifying questions and routes to the appropriate event type or team member. “What is your company size?” -> Enterprise (routed to senior AE, 60-min call) vs SMB (routed to junior AE, 30-min call). Collective scheduling: find a time when multiple hosts are ALL available. The system intersects availability across all required attendees. With 3 required attendees: the available slots are the intersection of their free times. This is significantly more constrained — with 3 busy people, there may be very few mutual openings. Group events: one-to-many scheduling. The host offers a time slot that multiple bookers can join (up to a configured maximum). Use for: webinars, office hours, and group coaching. The slot is available until the maximum attendees is reached. Booking page customization: branding (logo, colors), custom questions (text, dropdown, radio buttons, checkboxes), payment collection (Stripe integration for paid consultations), and redirect after booking (to a thank-you page or next steps).

Reminders and Follow-ups

Reminders reduce no-shows. Automated reminders: (1) Email reminders — configurable: 24 hours before, 1 hour before, or 15 minutes before. Include: meeting time (in the recipient timezone), video link, location, and a reschedule/cancel link. (2) SMS reminders — for higher-touch scheduling (medical appointments, sales calls). Requires the booker phone number. (3) Calendar reminders — the calendar event itself triggers a device notification (configured when the event is created: 10-minute popup reminder). Reminder scheduling: a background job (similar to our Distributed Task Scheduler guide) checks for upcoming bookings and sends reminders at the configured offset. Use a Redis sorted set: ZADD reminders {send_timestamp} {booking_id}. A scheduler polls every minute for due reminders. Follow-up: after the meeting, automatically send: a thank-you email, a feedback survey, or a link to book a follow-up meeting. Triggered by: meeting end time + configured delay (e.g., 30 minutes after the meeting). Cancellation and rescheduling: bookers can cancel or reschedule via a link in the confirmation email. Cancellation: the slot is released (becomes available again), the calendar event is deleted, and both parties are notified. Rescheduling: the old slot is released, the booker selects a new time (availability re-computed), and a new booking is created. Minimum notice: hosts can require 24-hour notice for cancellation (prevent last-minute cancels).

{“@context”:”https://schema.org”,”@type”:”FAQPage”,”mainEntity”:[{“@type”:”Question”,”name”:”How does Calendly prevent double-booking?”,”acceptedAnswer”:{“@type”:”Answer”,”text”:”When a booker selects a slot and clicks Confirm: (1) Re-validate availability (the slot may have been taken between page load and click). (2) Atomic hold: Redis SET slot_hold:{host}:{time} {session} EX 300 NX. The NX flag ensures only ONE person holds the slot. Others see This time is no longer available. (3) The booker fills in details within 5 minutes (hold duration). (4) On confirmation: create the database booking, insert a calendar event via Google/Outlook API, send confirmations, release the hold. If the booker abandons (no confirmation in 5 minutes): the hold expires automatically, and the slot becomes available again. Multi-calendar: check ALL connected calendars (work + personal). A slot is available only if it conflicts with NO calendar. Round-robin teams: check availability across all team members, assign to the first available, with load balancing to distribute evenly.”}}]}
Scroll to Top