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.tsThe 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 assignment —
getLuckyUserpicks 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 (viaselectedSlots), 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 linespackages/features/bookings/lib/handleNewBooking/test/reschedule.test.ts— 3,395 linespackages/features/bookings/lib/handleSeats/test/handleSeats.test.ts— 2,986 linespackages/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 fromRegularBookingService.ts. Convention is one tiny file per step. - Add a post-booking side effect: extend
BookingEmailSmsHandler.tsor enqueue work intasker. 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/andapps/web/modules/bookings/.
Related pages
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.