Open-Source Wikis

/

Cal.com

/

Features

/

Bookings

calcom/cal.com

Bookings

Active contributors: Romit, Hariom, Pedro, Eunjae

Purpose

The booking pipeline is the busiest, largest, and most-touched part of the codebase. It owns everything from "the booker hits the slot picker" to "calendar event written, video call provisioned, emails sent, webhooks fired, reminders scheduled." packages/features/bookings/ is the single largest workspace by file count.

Directory layout

packages/features/bookings/
├── Booker/                              # The public booking React UI
├── components/                          # Dashboard-side booking components
├── di/                                  # Dependency injection wiring
├── hooks/                               # React hooks
├── lib/                                 # The actual booking logic
│   ├── handleNewBooking/                # Pipeline split into ~30 small modules
│   │   ├── checkActiveBookingsLimitForBooker.ts
│   │   ├── checkBookingAndDurationLimits.ts
│   │   ├── checkIfBookerEmailIsBlocked.ts
│   │   ├── createBooking.ts
│   │   ├── ensureAvailableUsers.ts
│   │   ├── getBookingData.ts
│   │   ├── getCustomInputsResponses.ts
│   │   ├── getEventType.ts
│   │   ├── getEventTypesFromDB.ts
│   │   ├── getLocationValuesForDb.ts
│   │   ├── getRequiresConfirmationFlags.ts
│   │   ├── getSeatedBooking.ts
│   │   ├── getVideoCallDetails.ts
│   │   ├── loadAndValidateUsers.ts
│   │   ├── loadUsers.ts
│   │   ├── scheduleNoShowTriggers.ts
│   │   ├── validateBookingTimeIsNotOutOfBounds.ts
│   │   └── validateEventLength.ts
│   ├── handleSeats/                     # Seat-based event types
│   ├── handleCancelBooking/             # Cancellation pipeline
│   ├── handleConfirmation/              # Two-step booking confirmation
│   ├── EventManager.ts                  # Orchestrates calendar + video creation per event
│   ├── service/
│   │   └── RegularBookingService.ts (2,690 lines) — the orchestrator
│   ├── BookingEmailSmsHandler.ts
│   ├── conflictChecker/
│   ├── getAllCredentialsForUsersOnEvent/
│   └── ...
├── repositories/
│   ├── BookingRepository.ts (2,140 lines) — Prisma queries
│   └── ...
├── services/                            # Higher-level services on top of lib/service/
└── types.ts / types.server.ts

The split between lib/ and services/ is historical: lib/ is the original implementation, services/ is where the team is gradually consolidating to match the repository/service convention used elsewhere. RegularBookingService.ts straddles both worlds and is the most-modified file in the project (15 commits in the last 90 days).

Key abstractions

Symbol File Purpose
RegularBookingService packages/features/bookings/lib/service/RegularBookingService.ts The pipeline orchestrator
EventManager packages/features/bookings/lib/EventManager.ts Per-booking calendar + video provisioning
BookingRepository packages/features/bookings/repositories/BookingRepository.ts Prisma queries (uses select)
BookingEmailSmsHandler packages/features/bookings/lib/BookingEmailSmsHandler.ts Email + SMS dispatch on transitions
Booker packages/features/bookings/Booker/ Public booking UI
handleNewBooking modules packages/features/bookings/lib/handleNewBooking/*.ts Pre-write validation steps
handleSeats packages/features/bookings/lib/handleSeats/ Seat-based event-type logic
handleCancelBooking packages/features/bookings/lib/handleCancelBooking/ Cancellation flow
handleConfirmation packages/features/bookings/lib/handleConfirmation/ Confirmation step for "requires confirmation" event types
findBookingQuery packages/features/bookings/lib/handleNewBooking/findBookingQuery.ts Idempotency check

How it works

sequenceDiagram
    participant UI as apps/web/modules/booking
    participant Handler as RegularBookingService.handleNewBooking
    participant Validate as handleNewBooking/*.ts
    participant EventManager as EventManager.ts
    participant Calendars as features/calendars + app-store/<provider>
    participant Video as app-store/<video provider>
    participant Repo as BookingRepository
    participant DB as PostgreSQL
    participant Tasker as features/tasker
    participant Webhooks as features/webhooks
    participant Emails as packages/emails

    UI->>Handler: POST /api/book/event with payload
    Handler->>Validate: validateBookingTimeIsNotOutOfBounds, validateEventLength, ...
    Validate->>Validate: checkBookingAndDurationLimits, ensureAvailableUsers, ...
    Validate-->>Handler: cleaned data
    Handler->>EventManager: provision external resources
    EventManager->>Calendars: createEvent on destination calendar
    EventManager->>Video: createMeeting (if locations include video)
    Calendars-->>EventManager: { externalId, iCalUID, ... }
    Video-->>EventManager: { meetingUrl, ... }
    EventManager-->>Handler: results
    Handler->>Repo: createBooking + BookingReferences (transactional)
    Repo->>DB: INSERT
    Handler->>Emails: BookingEmailSmsHandler.sendConfirmation(booker, organizer)
    Handler->>Webhooks: enqueueWebhook("BOOKING_CREATED")
    Handler->>Tasker: scheduleReminders, scheduleNoShowTriggers
    Handler-->>UI: { uid, redirectUrl }

Edge cases the pipeline handles

  • Recurring bookings (packages/features/bookings/lib/create-recurring-booking.ts)
  • Seat-based events (handleSeats/) — multiple attendees on one slot, with mid-booking joins/cancellations
  • "Requires confirmation" event types — booking starts in PENDING, organizer confirms via email link
  • Reschedules (handleNewBooking/originalRescheduledBookingUtils.ts) — preserve UID, link old/new bookings, update third-party calendar event
  • Cancellations (handleCancelBooking/) — refund payments, free seats, fire webhooks
  • No-show flagging (scheduleNoShowTriggers.ts, packages/features/handleMarkNoShow.ts) — both attendee and host paths
  • Round-robin assignmentgetLuckyUser picks the next host based on weights and availability
  • Hashed links (packages/features/hashedLink) — one-time/private booking URLs
  • Booking limits (checkBookingLimits.ts, checkDurationLimits.ts) — per-day / week / month caps
  • Email-blocking and bot detection (checkIfBookerEmailIsBlocked.ts, packages/features/bot-detection)
  • Custom booking questions (getCustomInputsResponses.ts, getBookingResponsesSchema.ts) — custom fields rendered by the form-builder

Integration points

  • Calendars (packages/features/calendars) — busy-time aggregation, event creation, event update/cancel
  • Slots (packages/features/slots) — slot reservation (via selectedSlots), conflict detection
  • Webhooks (packages/features/webhooks) — BOOKING_CREATED, BOOKING_RESCHEDULED, BOOKING_CANCELLED, MEETING_ENDED, RECORDING_READY, ...
  • Tasker (packages/features/tasker) — reminder emails, no-show triggers, post-booking automation
  • Webhooks (packages/features/booking-audit) — audit trail of every booking state change
  • Workflows — even with the EE runtime being deprecated, basic reminders and follow-up actions still flow through tasker.

Testing

The booking pipeline has the largest test surface in the repo:

  • packages/features/bookings/lib/handleNewBooking/test/fresh-booking.test.ts — 3,862 lines
  • packages/features/bookings/lib/handleNewBooking/test/reschedule.test.ts — 3,395 lines
  • packages/features/bookings/lib/handleSeats/test/handleSeats.test.ts — 2,986 lines
  • packages/features/bookings/lib/getBookingResponsesSchema.test.ts — 2,523 lines

All built on top of the shared scenario builder at packages/testing/src/lib/bookingScenario/bookingScenario.ts.

Entry points for modification

  • Add a pre-write check: drop a new module under handleNewBooking/ and chain it from RegularBookingService.ts. Convention is one tiny file per step.
  • Add a post-booking side effect: extend BookingEmailSmsHandler.ts or enqueue work in tasker. Avoid inline blocking calls.
  • Change calendar/video provisioning: edit EventManager.ts. New provider-specific behavior should live in the app-store adapter, not here.
  • Touch the dashboard list: components live under packages/features/bookings/components/ and apps/web/modules/bookings/.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Bookings – Cal.com wiki | Factory