Skip to content

Microsoft Graph-first scheduling with Cal.com for external only

ADR-001: Microsoft Graph-first scheduling with Cal.com for external only

Status: Accepted Date: 2026-04-14 Deciders: Mishaal Murawala, multi-model review (GPT-5.4, Gemini 3.1 Pro, Nemotron 3)

Context

The Smart Scheduler needs to handle both internal meetings (within an M365 or Google Workspace org) and external meetings (with people outside the org). We needed to decide whether to use a single scheduling engine for everything or route to different engines based on context.

Options were: (a) Cal.com for everything, (b) Microsoft Graph for everything, (c) Graph for internal + Cal.com for external only.

Decision

We will use Microsoft Graph findMeetingTimes as the primary scheduling engine for internal M365 meetings, and Cal.com only for external self-serve booking flows.

Consequences

Positive

  • findMeetingTimes provides attendee-aware suggestions with emptySuggestionsReason — no need to build our own conflict resolution
  • No per-seat cost for internal scheduling (Graph is included in M365 license)
  • Cal.com self-hosted is MIT-licensed (verified 2026-04-17, see ADR-008), unlimited users, $0/seat for external flows
  • Eliminates the need to sync M365 calendars to an external system

Negative

  • Two scheduling engines to maintain instead of one
  • findMeetingTimes only works with delegated auth (application permissions return 403)
  • Cal.com requires separate infrastructure deployment (Docker + PostgreSQL)

Risks

  • If PFP uses application-permission tokens exclusively, findMeetingTimes won’t work — need delegated auth flow
  • Cal.com API versioning may drift (already caught: 2024-08-13 was stale, updated to 2026-02-25)

Alternatives Considered

Cal.com for everything

  • Rejected because: would require syncing all M365 calendars to Cal.com, adding latency and a sync dependency. Graph already has native access to all internal calendars with zero sync.

Microsoft Graph for everything (including external)

  • Rejected because: Graph can’t generate self-serve booking links for external parties. External invitees need a URL they can visit to pick a time without M365 access.

Calendly / SavvyCal (commercial)

  • Rejected because: per-seat pricing ($12-25/user/month) doesn’t scale for multi-tenant agency model. Cal.com self-hosted is $0/seat.