HowWorks
HowWorks

Everything begins with understanding.

Type your idea to discover matching projects. Start with what's already great so you never have to build from scratch. Build and inspire together—because greatness is never achieved alone.

Explore/DeepDive/

calcom/cal.com

This is a deep technical analysis of cal.com.

cal.com

cal.com

40.1k

Scheduling infrastructure for absolutely everyone.

bycalcom
Detail →
Report Contents
Product — positioning, core features & user journeys
Assessment — architecture, tech stack & implementation
Assets — APIs, data models & key modules
Suggested Actions
Copy Prompt to send key insights to your AI coding assistant
Bookmark the project card to your workspace
Ask any follow-up questions below to dive deeper
AI-Generated • Verify Details
Knowledge Base
Code-to-Docs
calcom/cal.com
@0b0a547 · en

How calcom/cal.com Works

Cal.com positions itself as the open-source alternative to established scheduling tools like Calendly. Its core differentiation lies in offering full control and extensibility. While Calendly is a closed-source SaaS, Cal.com is "white-label by design," self-hostable, and API-driven. This makes it a platform rather than just a tool, appealing to three distinct user segments: individual users seeking more control, teams requiring deep integration and custom workflows, and developers building scheduling capabilities into their own products. Its competitive edge is not in being a free clone, but in its architectural openness, which allows for unlimited customization of data, workflows, and branding.

Overview

Cal.com positions itself as the open-source alternative to established scheduling tools like Calendly. Its core differentiation lies in offering full control and extensibility. While Calendly is a closed-source SaaS, Cal.com is "white-label by design," self-hostable, and API-driven. This makes it a platform rather than just a tool, appealing to three distinct user segments: individual users seeking more control, teams requiring deep integration and custom workflows, and developers building scheduling capabilities into their own products. Its competitive edge is not in being a free clone, but in its architectural openness, which allows for unlimited customization of data, workflows, and branding.

To provide a highly customizable and controllable open-source scheduling infrastructure, serving as a successor to tools like Calendly for individuals, teams, and developers.

How It Works: End-to-End Flows

Scheduling an Event (Invitee Perspective)

This is the primary user journey for an invitee booking a meeting with a Cal.com user. The flow begins when the invitee visits a host's public booking page. The system dynamically calculates and presents available time slots by aggregating the host's schedules, connected calendars, and event-specific rules. The invitee selects a time, provides their personal information, and answers any custom questions set by the host. Upon confirmation, the system atomically creates the booking, processes any required payment, and triggers a cascade of automated actions. This includes creating events in both the host's and invitee's calendars, generating a unique video conference link, and sending out confirmation notifications via email or SMS. The goal is to provide a frictionless, self-service experience that completes the entire scheduling process in a single, seamless interaction.

  1. Invitee views a public booking page
  2. Invitee selects a time slot and provides their details
  3. System creates the booking and processes payment if required
  4. System integrates with external calendar and video apps
  5. System sends confirmation notifications via automated workflows

Creating and Configuring an Event Type (Host Perspective)

This flow describes how a host sets up their availability for others to book. The journey starts in the user's dashboard, where they create a new 'event type'. They define the core attributes like the meeting name, duration, and whether it's a paid event. The host then configures the detailed scheduling rules, such as setting a minimum booking notice, adding buffer time between meetings, and defining their recurring weekly availability. For team-based events, the host assigns other team members and selects the scheduling logic (e.g., 'collective' or 'round-robin'). Finally, they can enable and configure integrations specific to this event type, like choosing which CRM to sync contacts to. This setup process empowers the host to create highly customized and reusable booking pages tailored to different meeting scenarios, all through a guided, no-code interface.

  1. Host creates a new event type and defines basic properties
  2. Host configures detailed availability and scheduling rules
  3. For team events, host assigns members and chooses aggregation logic
  4. Host configures per-event-type app integrations
  5. Host activates the event type, making it public

Automating Reminders with a Workflow

This flow outlines how a host can automate communication for their events. The user navigates to the 'Workflows' section and creates a new workflow. They start by selecting a trigger event, such as '24 hours before the event starts'. Next, they add an action step, choosing the channel (e.g., Email or SMS) and the recipient (e.g., Attendee). They then compose the message content, using dynamic variables like `{ATTENDEE_NAME}` to personalize the communication. After saving the workflow, they associate it with one or more of their event types. From that point on, the system will automatically handle the rest. When a booking is made for an associated event type, the system schedules the reminder. At the configured time—24 hours before the meeting—the background job processor picks up the scheduled task and sends the personalized reminder to the attendee, requiring no further manual effort from the host.

  1. Host creates a new workflow and selects a trigger event
  2. Host adds an action step, choosing channel, recipient, and message
  3. Host associates the workflow with specific event types
  4. When a booking is made, the system schedules the timed reminder
  5. A background job processes the queue and sends the notification at the correct time

Connecting a Third-Party Application

This journey details how a user extends Cal.com's functionality by connecting it to another service, like Google Calendar. The user goes to the in-app 'App Store' and finds the Google Calendar application. Clicking 'Install' initiates an OAuth 2.0 authorization flow, redirecting the user to Google's sign-in page. After the user logs in and grants Cal.com permission to access their calendar, they are redirected back to the application. In the background, Cal.com securely receives and stores the authorization tokens. The user is then prompted to configure the new integration, such as selecting which of their calendars should be checked for conflicts and which one new events should be added to. Once configured, the integration is active, and the system will automatically use it in all relevant scheduling and booking flows, keeping availability in sync and centralizing all appointments.

  1. User finds an app in the App Store and begins installation
  2. User is redirected to the third-party service to authorize access (OAuth)
  3. System securely handles the callback and stores encrypted credentials
  4. User configures integration settings, like which calendar to use
  5. The integration is now active and used in booking flows

Key Features

Scheduling & Availability Engine

This is the core of Cal.com, responsible for defining when and how users are available for bookings. The design strategy is to provide maximum flexibility, allowing users to translate complex real-world availability into a set of digital rules. It handles everything from simple one-on-one meetings to complex, multi-person team scheduling by aggregating various inputs—recurring schedules, one-off overrides, holidays, and buffers—into a final set of bookable time slots. The product value lies in its ability to accurately model and enforce even the most nuanced scheduling needs, reducing manual coordination and preventing booking errors.

  • Flexible Event Type Configuration — 【User Value】Allows hosts to create distinct, reusable templates for different types of meetings (e.g., 30-min intro call, 1-hour project kickoff), each with its own specific rules, eliminating the need to re-configure settings for every booking page.\n\n【Design Strategy】Treat each 'Event Type' as a comprehensive configuration object that encapsulates all rules for a specific booking scenario. This includes not just duration and location, but also advanced booking controls and team host assignments.\n\n【Business Logic】\n- Step 1: Define basic properties: A title, a unique URL slug, and a duration in minutes.\n- Step 2: Set scheduling rules: A minimum notice period to prevent last-minute bookings, buffer time before and after events to allow for breaks or travel, and a slot interval (e.g., every 15 minutes) to control how start times are presented.\n- Step 3: Configure booking constraints: Limit the number of bookings a person can make per day/week/month for a specific event type.\n- Step 4: Assign hosts and scheduling type: Specify if the event is for an individual, a group ('Collective'), or a rotating set of hosts ('Round-Robin'). For team events, hosts can be assigned different priorities or grouped for complex routing.\n- Step 5: Specify recurring availability patterns for the event, which can override the user's default schedule.
  • Team Availability Aggregation — 【User Value】Simplifies booking meetings with teams by automatically finding slots that work for the required participants, without the typical back-and-forth email chaos.\n\n【Design Strategy】Offer two distinct modes for team scheduling to cover the most common business scenarios: 'Collective' for "all-hands" meetings where everyone must attend, and 'Round-Robin' for "on-call" scenarios where any available team member can take the meeting.\n\n【Business Logic】\n- Step 1: The system first identifies the event's scheduling type: `COLLECTIVE` or `ROUND_ROBIN`.\n- Step 2: For `COLLECTIVE` events, the system retrieves the individual availability (including working hours, out-of-office, and holidays) for every required host.\n- Step 3: It then calculates the mathematical *intersection* of all hosts' available time ranges. A slot is only presented if all specified hosts are simultaneously available.\n- Step 4: For `ROUND_ROBIN` events, hosts are first organized into groups based on a predefined 'group ID'.\n- Step 5: Within each group, the system calculates the *union* of availability, meaning a time slot is available for the group if at least one member is free.\n- Step 6: Across all the different groups, the system then calculates the *intersection* of the group-level availability. This ensures that at least one person from *each* required group (e.g., one from 'Sales' and one from 'Engineering') is available.\n\n【Trade-off】The round-robin logic that intersects availability across groups is powerful for ensuring cross-functional representation. However, it means that if any single group has no available members at a given time, that time becomes unavailable for booking, potentially reducing the overall number of bookable slots.
  • Multi-Layered Availability Calculation — 【User Value】Ensures that the displayed availability is always accurate by layering multiple sources of scheduling information, from recurring weekly hours to last-minute out-of-office entries.\n\n【Design Strategy】Adopt a hierarchical and compositional approach to availability. The system starts with a base schedule and successively applies overrides and exclusions, ensuring that more specific or recent information takes precedence.\n\n【Business Logic】\n- Step 1: **Establish Base Schedule**: For a given host, the system first determines the base schedule to use in this priority order: (1) a schedule defined specifically on the event type, (2) a schedule assigned to that host for this event, (3) the user's personal default schedule, or (4) a system-wide default (9am-5pm, Mon-Fri).\n- Step 2: **Process Recurring Hours**: Convert the weekly working hours (e.g., Mon 9-5, Tue 10-4) from the selected schedule into concrete date ranges for the requested period, correctly handling timezone conversions and daylight saving time shifts.\n- Step 3: **Apply Onetime Overrides**: Layer any specific date overrides (e.g., working longer on a specific Wednesday) on top of the recurring schedule.\n- Step 4: **Subtract Blocked Time**: Remove periods where the user is unavailable. This includes: (a) events from their connected external calendars, (b) manually entered out-of-office periods, and (c) public holidays for the user's configured country (if the holiday falls on one of their designated working days).
  • Time Slot Generation — 【User Value】Translates broad availability windows into a clean, discrete list of bookable starting times for the end-user.\n\n【Design Strategy】Create a slot generation engine that takes a final set of available date ranges and divides it into bookable slots based on the event's duration and configured interval, while respecting booking notice periods.\n\n【Business Logic】\n- Step 1: Receive the final, aggregated availability date ranges after all calculations (working hours, team aggregation, blocked time).\n- Step 2: For each available range, calculate the earliest possible start time, ensuring it is after the configured 'minimum booking notice' (e.g., cannot book within 4 hours of the current time).\n- Step 3: Align the first slot's start time to the specified slot interval (e.g., if the interval is 15 minutes, a start time of 9:07am would be aligned to 9:15am).\n- Step 4: From the aligned start time, continuously generate subsequent slots by incrementing by the event's frequency (typically duration + buffer time) until the end of the available date range is reached.\n- Step 5: An optional 'optimized slots' setting allows slots to start off-interval to maximize the number of available slots shown, at the cost of less uniform start times.

Booking & Payment Lifecycle

This module governs the entire journey of an end-user completing a booking. It handles the initial submission, payment processing for paid events, state management (pending vs. confirmed), and transactional updates for reschedules or cancellations. The design focuses on reliability and extensibility, ensuring bookings are created atomically and that payment can be handled by various providers through a pluggable system. This provides a seamless and secure experience for the person booking, while offering powerful monetization options for the host.

  • Transactional Booking Creation — 【User Value】Guarantees that bookings, especially complex ones like reschedules, are saved reliably without creating inconsistent data (e.g., a cancelled old meeting without a new one being created).\n\n【Design Strategy】Wrap all database operations related to a single booking action within a single database transaction. This ensures that all related changes either succeed together or fail together, maintaining data integrity.\n\n【Business Logic】\n- Step 1: The system receives the booking request, including start/end times, attendee details, and context (e.g., if it's a reschedule or linked to a routing form).\n- Step 2: It determines the initial booking status. If the event type is set to be confirmed by default, the status is set to `ACCEPTED`. Otherwise, it's set to `PENDING` for manual approval.\n- Step 3: A database transaction is initiated.\n- Step 4: If the booking is a reschedule, the system first updates the original booking within the transaction (e.g., changing its status to `CANCELLED`).\n- Step 5: The new booking record is created within the same transaction, along with its associated attendees.\n- Step 6: If the booking originated from a routing form, the form submission record is also updated to link to the new booking.\n- Step 7: The transaction is committed. If any step fails, the entire transaction is rolled back, leaving the system in its original state.
  • Pluggable Payment Handling with Add-ons — 【User Value】Enables hosts to charge for their time and offer paid add-ons directly within the booking flow, creating a native monetization experience.\n\n【Design Strategy】Decouple the booking logic from specific payment providers. A generic payment handler dynamically loads a payment service (e.g., Stripe) and calculates the final price, including dynamic add-ons from booking form answers.\n\n【Business Logic】\n- Step 1: When a booking is submitted for a paid event, the system identifies the configured payment provider for that event type.\n- Step 2: It dynamically loads the corresponding payment service module.\n- Step 3: The base price and currency are retrieved from the event type settings (defaulting to 0 and USD if not set).\n- Step 4: The system inspects the attendee's answers to custom booking fields to calculate add-on costs:\n - For 'number' fields, the attendee's input is multiplied by the field's price.\n - For 'boolean' (checkbox) fields, the price is added if the box is checked.\n - For 'select' or 'radio' fields, the price associated with the chosen option is added.\n- Step 5: The total price (base + add-ons) is calculated and converted to the smallest currency unit (e.g., cents).\n- Step 6: The system then calls the payment provider's service to either create a payment intent (for immediate payment) or collect and hold card details (for 'hold and charge later' scenarios).\n\n【Trade-off】If a payment provider is misconfigured or its module fails to load, the system currently logs a warning and proceeds without payment. This prevents a misconfiguration from blocking all bookings but could lead to unpaid bookings if not monitored.

App Store & Integrations

This module transforms Cal.com from a standalone tool into a connected hub by integrating with third-party services. It features an in-app 'App Store' where users can discover, install, and configure connections to calendars, video conferencing tools, CRMs, and more. The architecture is designed for extensibility, using a plugin-based model where each app is a self-contained unit with its own logic and UI for settings. This allows for rapid development of new integrations and provides users with a seamless way to embed Cal.com into their existing tool stack, automating tasks like creating calendar events or video meeting links.

  • Unified App Discovery and Installation — 【User Value】Provides a central, user-friendly 'App Store' to discover and install integrations, making it easy to connect Cal.com with other essential tools without needing technical expertise.\n\n【Design Strategy】Create a central app registry that aggregates metadata from all available integration packages. The UI then consumes this registry to render a browsable store, complete with categories, descriptions, and installation status, guiding the user through a multi-step installation wizard.\n\n【Business Logic】\n- Step 1: An 'App Registry' service scans the `/packages/app-store` directory at runtime to build a catalog of all available applications.\n- Step 2: For each app, it loads metadata including its name, description, category (e.g., 'Calendar', 'Video'), and logo.\n- Step 3: The system checks the user's credentials to determine which apps are already installed for the user or their team, and displays an 'Installed' status.\n- Step 4: When a user clicks 'Install', they are guided through a step-by-step wizard which may include: (a) choosing whether to install for their personal account or a team, (b) going through an OAuth flow to grant permissions, and (c) applying the new integration to selected event types.
  • Per-Event-Type App Configuration — 【User Value】Offers granular control by allowing users to enable or configure integrations differently for each type of event. For example, using Google Meet for 'Internal' meetings and Zoom for 'Client' meetings.\n\n【Design Strategy】Store app-specific settings within a flexible JSON metadata field on the Event Type database model. This avoids rigid schema changes and allows each app to define its own unique configuration options.\n\n【Business Logic】\n- Step 1: On the 'Event Type' settings page, a dedicated 'Apps' section lists all installed integrations.\n- Step 2: For each app, a specific configuration interface is rendered, defined by the app's own code.\n- Step 3: When a user changes a setting for an app (e.g., choosing a specific CRM pipeline), the configuration is saved as a key-value pair within the `metadata.apps` JSON object of that specific event type.\n- Step 4: During a booking flow for that event type, the system reads this metadata to determine which apps to use and how they should behave (e.g., which calendar to create the event in, which video link to generate).
  • Automated OAuth Token Management — 【User Value】Ensures that connections to third-party apps remain active without forcing users to constantly re-authenticate. The system handles token refreshes in the background, providing a 'set it and forget it' experience.\n\n【Design Strategy】Implement a generic `OAuthManager` class that abstracts the complexity of the OAuth 2.0 token refresh flow. This manager can be used by any integration that uses OAuth.\n\n【Business Logic】\n- Step 1: When an integration needs to make an API call to a third-party service, it first consults the `OAuthManager`.\n- Step 2: The manager checks if the stored access token is close to expiring (e.g., within 5 seconds of its expiry time).\n- Step 3: If the token is expiring, the manager automatically uses the stored refresh token to request a new access token from the third-party service's token endpoint.\n- Step 4: The new access token and its new expiry time are saved back to the user's encrypted credential store.\n- Step 5: The fresh, valid access token is then used to make the intended API call.\n\n【Trade-off】The token refresh mechanism does not currently coordinate across concurrent requests. If multiple requests are made simultaneously for an expiring token, it could trigger redundant refresh calls, though this is a rare edge case.
  • Centralized Calendar & Video Integration — 【User Value】Automatically creates calendar events and generates unique video meeting links for every booking, eliminating manual and error-prone administrative work for the host.\n\n【Design Strategy】Use manager classes (`CalendarManager`, `VideoApiAdapter`) to orchestrate actions across different providers. The booking flow interacts with these generic managers, which then delegate the specific API calls to the appropriate service (e.g., Google Calendar, Zoom) based on the event's configuration.\n\n【Business Logic】\n- Step 1: After a booking is confirmed, the system's `CalendarManager` is invoked.\n- Step 2: The manager identifies the 'destination calendars' configured for the event type (e.g., the host's 'Work' calendar and a team's 'Bookings' calendar).\n- Step 3: For each destination calendar, it calls the `createEvent` method of the corresponding calendar service (e.g., Google Calendar Service), passing all booking details.\n- Step 4: Similarly, the system checks if a video conferencing app is configured as the location.\n- Step 5: It instantiates the correct `VideoApiAdapter` (e.g., Zoom Adapter) and calls its `createMeeting` method.\n- Step 6: The unique join URL returned by the video provider is then saved to the booking record and included in calendar invitations and notifications.

Workflow Automation & Notifications

This module empowers users to automate communication and actions based on the booking lifecycle. It provides a no-code workflow builder to create sequences of timed actions triggered by events like 'new booking,' 'event cancelled,' or '24 hours before event.' Supported actions include sending emails, SMS, WhatsApp messages, or even making AI-powered phone calls. This system significantly reduces the host's manual follow-up burden, ensures consistent communication with attendees, and can be used for reminders, thank-you notes, or feedback requests.

  • Event-Driven Workflow Triggers — 【User Value】Allows for timely, context-aware automation by kicking off workflows at the exact moment a key event happens in the booking journey.\n\n【Design Strategy】Define a set of specific, reliable trigger points throughout the booking and form submission lifecycles. When one of these events occurs, the system automatically finds and executes any associated workflows.\n\n【Business Logic】\n- Step 1: The system defines a list of more than 10 distinct `WorkflowTriggerEvents`, including:\n - `NEW_EVENT`: When a booking is first confirmed.\n - `RESCHEDULE_EVENT`: When a booking is rescheduled.\n - `EVENT_CANCELLED`: When a booking is cancelled.\n - `BEFORE_EVENT`: A timed trigger that fires at a specified duration before the meeting starts.\n - `AFTER_EVENT`: A timed trigger that fires after a meeting ends.\n - `FORM_SUBMITTED`: When a user submits a routing form.\n- Step 2: When an action occurs in the application (e.g., a booking is created), it emits the corresponding trigger event.\n- Step 3: The `WorkflowService` catches this event and queries the database for all active workflows that are subscribed to this specific trigger and are associated with the relevant user, team, or event type.
  • Multi-Channel Notification Actions — 【User Value】Reach attendees on their preferred communication channel by sending automated messages via Email, SMS, WhatsApp, and even AI Phone Calls.\n\n【Design Strategy】Create a unified action system where a workflow step defines the 'what' (the message) and the 'who' (the recipient), while dedicated delivery services handle the 'how' for each channel (e.g., SendGrid for email, Twilio for SMS).\n\n【Business Logic】\n- Step 1: When creating a workflow step, the user selects an action from a list, such as `EMAIL_ATTENDEE`, `SMS_HOST`, or `WHATSAPP_NUMBER`.\n- Step 2: The user composes the message content using a template editor that supports dynamic variables (e.g., `{EVENT_NAME}`, `{ATTENDEE_NAME}`).\n- Step 3: When the workflow executes, the system identifies the action type and recipient.\n- Step 4: It then routes the request to the appropriate service: `WorkflowEmailService` for emails, `SMSManager` for SMS and WhatsApp, or `Retell` for AI phone calls.\n- Step 5: For SMS/WhatsApp, the system checks against user/team credit balance and rate limits before sending.
  • Scheduled Reminder Processing — 【User Value】Ensures reminders and follow-ups are sent at exactly the right time (e.g., 1 hour before a meeting, 1 day after) without any manual intervention.\n\n【Design Strategy】Use a two-phase system. First, when a booking is made, calculate the exact future send time for all timed workflows and store them as 'reminders'. Second, have a separate, recurring background job that continuously scans for and processes these scheduled reminders.\n\n【Business Logic】\n- Step 1: When a booking is made for an event with a timed workflow (e.g., 'send reminder 24 hours before'), the system calculates the exact `scheduledDate` (e.g., `booking.startTime` - 24 hours).\n- Step 2: A `WorkflowReminder` record is created in the database containing the scheduled send time, the recipient, and the message to be sent.\n- Step 3: A set of cron jobs (background tasks) run at a regular interval (e.g., every few minutes).\n- Step 4: Each cron job queries the database for `WorkflowReminder` records that are due to be sent within a short future window (e.g., the next 2 hours).\n- Step 5: For each due reminder, the job renders the final message content with all variables and dispatches it through the appropriate channel service (e.g., SendGrid, Twilio).\n\n【Trade-off】The system currently logs errors on delivery failure but does not have an automatic retry mechanism for failed notifications. A transient issue with a provider could cause a reminder to be missed.

User & Access Management

This module handles user identity, authentication, and authorization. It provides secure signup and login mechanisms, including two-factor authentication (2FA) and enterprise single sign-on (SSO). The system is designed with security and operational control in mind, featuring anti-abuse measures like rate limiting and bot protection on signup, as well as granular permissioning for team and organization functionalities. This ensures that only authorized users can access and manage their scheduling data and settings.

  • Secure Credential Authentication with 2FA — 【User Value】Protects user accounts from unauthorized access by requiring a second factor of authentication (a code from an authenticator app or a backup code) in addition to a password.\n\n【Design Strategy】Integrate Two-Factor Authentication (2FA) directly into the NextAuth credential-based login flow, making it a seamless part of the sign-in process for users who have it enabled.\n\n【Business Logic】\n- Step 1: A user attempts to log in with their email and password.\n- Step 2: The system verifies the password. If incorrect, it returns a generic error to prevent username enumeration.\n- Step 3: If the password is correct, the system checks if 2FA is enabled for the user's account.\n- Step 4: If 2FA is enabled, the system returns a specific response indicating that a second factor is required.\n- Step 5: The user then submits their 2FA code. The system checks for one of two types:\n - **Time-based One-Time Password (TOTP)**: Validates the code from an authenticator app against the user's stored secret key.\n - **Backup Code**: If a backup code is provided, it's decrypted, checked against the user's stored list of valid backup codes, and if it matches, the code is immediately invalidated to prevent reuse.\n- Step 6: Only after successful validation of the second factor is the user's session created.
  • Gated User Signup with Anti-Abuse — 【User Value】Protects the platform from spam and malicious actors by placing multiple security checks and operational gates on the user registration process.\n\n【Design Strategy】Implement a multi-layered defense on the signup API endpoint. Each layer must be passed before a user account can be created, combining automated bot detection with manual operational controls.\n\n【Business Logic】\n- Step 1: **IP-based Rate Limiting**: The system first checks the user's IP address against a rate limit (e.g., a maximum of 10 signup attempts per IP per minute) to prevent rapid, automated account creation.\n- Step 2: **Bot Detection**: It then requires a valid token from Cloudflare Turnstile (a privacy-friendly alternative to CAPTCHA) to verify that the request is likely coming from a human.\n- Step 3: **Global Signup Gate**: The system checks for a global configuration flag (`NEXT_PUBLIC_DISABLE_SIGNUP`). If this flag is active, all new signups are blocked unless the user has a special invitation token. This allows administrators to temporarily halt all public registrations.\n- Step 4: Only after passing all three gates does the system proceed with creating the new user account.
  • Enterprise SSO Connection Management — 【User Value】Allows large organizations to integrate Cal.com with their corporate identity provider (e.g., Okta, Azure AD), enabling employees to log in with their existing company credentials.\n\n【Design Strategy】Provide administrative APIs for organization admins to configure and manage SAML and OIDC connections. The system uses a specialized SSO controller to handle the complex protocols, abstracting them away from the core application logic.\n\n【Business Logic】\n- Step 1: An organization admin navigates to the SSO settings within Cal.com.\n- Step 2: They provide the necessary details from their identity provider, such as the metadata URL (for SAML) or client ID/secret (for OIDC).\n- Step 3: The system stores this configuration, linking it to the organization's unique tenant ID.\n- Step 4: The configuration includes redirect URIs that Cal.com will use during the authentication handshake.\n- Step 5: When an employee from that organization tries to log in, they are redirected to their company's sign-in page. After successful authentication, the identity provider sends a signed response back to Cal.com, which validates it and establishes a user session.

Platform & Developer API

This module exposes Cal.com's core functionalities as a programmatic API (API v2), transforming the product into a true scheduling infrastructure platform. It enables developers to build custom integrations, embed scheduling into their own applications, or manage Cal.com resources (like users, teams, and event types) programmatically. The API is designed with standard practices like versioning, role-based access control, and consistent pagination, providing a stable and secure surface for third-party development.

  • Versioned and Role-Gated API Endpoints — 【User Value】For developers, this provides a stable and predictable API that won't have breaking changes unexpectedly. For platform owners, it ensures that only authorized clients and users can perform sensitive actions.\n\n【Design Strategy】Employ a dual strategy of API versioning and role-based access control (RBAC). API versions are explicitly declared on controllers, and request/response schemas are date-stamped to allow for non-breaking evolution. Access is protected by guards that check for specific roles (e.g., 'TEAM_ADMIN').\n\n【Business Logic】\n- Step 1: A developer makes an API request, typically including an API key in the headers.\n- Step 2: The API gateway first authenticates the request to identify the user or client.\n- Step 3: A `RolesGuard` then checks if the authenticated user has the required role for the requested endpoint (e.g., a user must have the `TEAM_ADMIN` role to add members to a team).\n- Step 4: If authorization passes, the request proceeds to the controller. The API version (requested via headers or URL) determines which specific request/response schema (DTO) is used, ensuring backward compatibility for older clients.
  • Standardized Pagination for List Endpoints — 【User Value】Allows developers to efficiently retrieve large datasets (e.g., a list of all bookings or event types) in manageable chunks, preventing timeouts and oversized responses.\n\n【Design Strategy】Implement a consistent `skip/take` pagination pattern across all API endpoints that return lists of resources.\n\n【Business Logic】\n- Step 1: When requesting a list of resources (e.g., `GET /v2/teams/:teamId/schedules`), developers can include optional `skip` and `take` query parameters.\n- Step 2: `skip` defines the number of records to bypass (for starting on a specific 'page'). `take` defines the maximum number of records to return (the 'page size').\n- Step 3: If these parameters are omitted, the API applies safe defaults (e.g., `skip=0`, `take=250`) to ensure responses are always bounded and performant.\n- Step 4: The API service then queries the database using these limit and offset values to return the requested slice of data.
  • Secure Webhook Management — 【User Value】Lets developers subscribe to real-time events in Cal.com (like 'booking created') to trigger actions in their own systems, while protecting the platform from security risks like Server-Side Request Forgery (SSRF).\n\n【Design Strategy】Provide dedicated API endpoints for managing webhooks, with built-in validation to ensure that webhook URLs are safe and legitimate.\n\n【Business Logic】\n- Step 1: A developer uses the API to create a new webhook subscription, providing a callback URL and the list of events they want to subscribe to.\n- Step 2: Before saving the webhook, the system runs the provided URL through a series of validation checks.\n- Step 3: These checks ensure the URL uses an allowed protocol (e.g., HTTPS), does not point to internal or private IP addresses, and meets other security criteria to prevent SSRF attacks.\n- Step 4: Only if the URL passes validation is the webhook subscription created. When a subscribed event later occurs, the system sends a signed payload to the validated URL.

Core Technical Capabilities

Extensible App & Integration Framework

Problem: How to support a vast and growing ecosystem of third-party services (calendars, video, payments, CRMs) without creating a monolithic, unmaintainable codebase?

Solution: The system is built on a plugin-style architecture where each integration is a self-contained module. \n- Step 1: **Standardized Interfaces**: Define common interfaces for each category of app, such as `CalendarService` (with methods like `createEvent`, `getAvailability`) or `VideoApiAdapter` (with `createMeeting`).\n- Step 2: **Self-Contained Modules**: Each app in the `packages/app-store` directory implements the required interface and bundles its own API logic, configuration UI, and metadata.\n- Step 3: **Central App Registry**: A registry service dynamically scans and aggregates metadata from all app modules to populate the App Store UI, making app discovery automatic.\n- Step 4: **Generic OAuth Manager**: A reusable `OAuthManager` class handles the entire token lifecycle (acquisition, secure storage, and automatic background refresh) for any app using OAuth2, eliminating redundant code.\n- Step 5: **Flexible Metadata Storage**: App settings are stored in a generic JSON field on the event type model, allowing each app to have its own custom configuration without requiring database schema changes. This makes the entire framework highly scalable and easy for developers to contribute new integrations to.

Technologies: OAuth2, Prisma, Zod, React Context, Dynamic Imports

Boundaries & Risks: The framework's stability relies on each app module correctly implementing its interface; a faulty app could potentially disrupt the booking flow. The OAuthManager does not currently have locking for concurrent refresh requests, which could lead to race conditions under very high load. The system trusts app metadata to be accurate for rendering and configuration.

High-Performance Server-Side Session Caching

Problem: How to provide fast page loads and API responses for authenticated users without overwhelming the database with repetitive session lookups on every single request?

Solution: A custom `getServerSession` function is used as a lightweight and performant alternative to the standard NextAuth session handler. \n- Step 1: On a server-side request, the function retrieves the raw JWT from the request headers or cookies.\n- Step 2: It uses the entire serialized JWT string as a key to look up a session in a shared, in-memory LRU (Least Recently Used) cache, which has a fixed size (e.g., 1000 entries).\n- Step 3: If a valid, pre-computed session object is found in the cache (a 'cache hit'), it is returned immediately, completely avoiding any database interaction.\n- Step 4: If no session is found in the cache (a 'cache miss'), the function proceeds to parse the JWT, query the database for the user and their profile, constructs the full session object, and then stores this new object in the cache before returning it.\nThis strategy ensures that for a burst of requests from the same user, only the very first one hits the database, while all subsequent requests are served instantly from memory.

Technologies: LRU Cache, JWT, Next.js, Prisma

Boundaries & Risks: The cache is in-memory and therefore local to each server instance. In a scaled-out, multi-server deployment, the caches are not synchronized. This could lead to brief periods of stale data if a user's permissions change and their subsequent request hits a different server with an old, cached version of their session. The function also explicitly does not refresh expired tokens, relying on the client to handle re-authentication.

Booking Integrity via Idempotency Keys

Problem: How to prevent a user from accidentally creating duplicate bookings if they double-click the 'Confirm' button or if a network request is retried automatically?

Solution: The system leverages a Prisma query extension to automatically add a deterministic idempotency key to new bookings. \n- Step 1: The extension intercepts any 'create booking' query.\n- Step 2: If the booking status is `ACCEPTED`, it generates a unique but stable key using a UUIDv5 hash of the booking's core attributes: its start time, end time, and the user it's for.\n- Step 3: This generated key is added to the booking record before it's sent to the database. The database schema has a unique constraint on this idempotency key field.\n- Step 4: If a duplicate request comes in with the exact same attributes, it will generate the exact same key. The database will reject the second insert operation due to the unique constraint violation, preventing a double booking.\n- Step 5: When a booking is later `CANCELLED` or `REJECTED`, the extension intercepts the update query and sets the idempotency key to null, freeing up that unique combination for future bookings.

Technologies: Prisma Extensions, UUIDv5, Database Constraints

Boundaries & Risks: This protection only applies to bookings that are immediately `ACCEPTED`. Bookings that start in a `PENDING` state do not get an idempotency key. The mechanism is dependent on the Prisma extension, so any database write that bypasses this client-side logic would not be protected.

Automated Database Migrations on Startup

Problem: How to ensure the application code is always running against the correct database schema version, especially in self-hosted or containerized deployments, to prevent runtime errors from schema mismatches?

Solution: A startup script is executed before the main application launches, which programmatically runs the database migration process. \n- Step 1: At application start, the script first checks for environment variables that might signal to skip migrations (e.g., `SKIP_DB_MIGRATIONS=1`) or if database connection URLs are missing.\n- Step 2: If cleared to proceed, it executes the Prisma CLI command `prisma migrate deploy` as a child process.\n- Step 3: This command compares the expected schema (defined in the Prisma schema file) with the actual state of the connected database and applies any pending migration files to bring the database up to date.\n- Step 4: If the migration fails for any reason (e.g., database connection error, invalid SQL), the script captures the error, logs it, and exits the entire process with a non-zero exit code. This fail-fast approach prevents the application from starting in an inconsistent state.

Technologies: Prisma Migrate, Node.js, Docker

Boundaries & Risks: The process relies on the Prisma CLI being available in the runtime environment. Since it shells out to an external command, its behavior can be influenced by system-level configurations. Misconfigured environment variables can cause the migration to be skipped silently, potentially leading to the application running against an older schema.

Related Projects

Discover more public DeepDive reports to compare architecture decisions.

  • usememos/memosc4176b4ef1c1 - en
  • selop/pokebox2a11d7da068a - en
  • imanian/appointmate66f1c0a89b98 - en
  • bytedance/UI-TARS-desktop3f254968e627 - en
  • ItzCrazyKns/Perplexicad7b020e5bb64 - en
  • openclaw/openclaw74fbbda2833e - en
Browse all public DeepDive reports