calcom/cal.com
Webhooks and Tasker
Active contributors: Joe, Pedro, Romit
Purpose
Cal.diy needs two kinds of asynchronous work to keep bookings reliable:
- Webhooks — outbound HTTP callbacks fired on booking events (
BOOKING_CREATED,BOOKING_RESCHEDULED,BOOKING_CANCELLED,MEETING_ENDED,RECORDING_READY, ...) that customers and integrations subscribe to. - Tasker — an in-process deferred-job queue backed by a Postgres table for short-lived work that should not block the booking response (sending reminder emails, scheduling no-show triggers, post-booking follow-ups).
Both live under packages/features/.
Where the code lives
| Concern | Code |
|---|---|
| Webhook subscriptions | Webhook model in packages/prisma/schema.prisma |
| Webhook dispatch | packages/features/webhooks |
| Webhook payload schemas | packages/features/webhooks/lib/ |
| Tasker queue | packages/features/tasker |
| Task model | Task (or similar) in packages/prisma/schema.prisma |
| Trigger.dev (heavy / scheduled jobs) | packages/features/trigger.config.ts + per-feature jobs |
| GitHub Actions cron | .github/workflows/cron-*.yml |
Webhooks
The Webhook Prisma model stores subscriber URL, secret (for HMAC signing), event types, and scope (user / team / event-type / app). On a booking event, the booking pipeline calls into packages/features/webhooks which:
- Resolves which webhooks match the event type and scope.
- Builds the payload (canonical Cal.com event JSON).
- HMAC-signs the payload using the per-webhook secret.
- Enqueues delivery through the tasker (so a slow subscriber doesn't slow the booking response).
- Records delivery attempts and exposes a retry endpoint.
Cron workflow .github/workflows/cron-webhooks-triggers.yml retries failed deliveries.
Tasker
The tasker is an in-process queue that uses Postgres as the durable backing store. The Task table holds rows like:
id | uuid
type | string (e.g., "send-reminder-email")
payload | jsonb
runAt | timestamp
attempts | int
status | enum (pending, in_progress, succeeded, failed)Producers enqueue tasks; consumers (the web app or a worker process) pull tasks where runAt <= now() and execute them. Failed tasks are retried with backoff. The queue is configured per-environment.
Why not Redis or a cloud queue? Cal.diy is designed to be self-hostable with a single Postgres dependency. The tasker keeps the deployment story simple. Trigger.dev (which does use cloud infrastructure) handles the heavier-duty scheduled jobs.
Trigger.dev
packages/features/trigger.config.ts registers Trigger.dev jobs (e.g., long-running calendar syncs, monthly digest emails). The config wires job declarations from individual features into the Trigger.dev workspace. Yarn scripts:
yarn dev:trigger # local Trigger.dev dev server
yarn deploy:trigger:staging
yarn deploy:trigger:prodLogs from Trigger.dev jobs route through packages/lib/triggerDevLogger.ts so they integrate with the rest of the observability stack.
Cron workflows
.github/workflows/cron-*.yml runs scheduled HTTP calls into the web app. Examples:
cron-bookingReminder.yml— drains booking reminder queuecron-scheduleEmailReminders.yml,cron-scheduleSMSReminders.yml,cron-scheduleWhatsappReminders.ymlcron-monthlyDigestEmail.ymlcron-changeTimeZone.ymlcron-checkSmsPrices.ymlcron-syncAppMeta.ymlcron-stale-issue.ymlcron-downgradeUsers.ymlcron-webhooks-triggers.yml
Each one is a short YAML that invokes a known endpoint with a shared secret.
Integration points
- Bookings are the primary producer of both webhooks and tasker jobs.
- Workflows (legacy EE) used to build on top of these; their runtime is being removed.
- Audit log (
packages/features/booking-audit) records every webhook attempt for debuggability.
Entry points for modification
- Add a webhook event type: extend the
WebhookTriggerEventsenum, add a payload builder underpackages/features/webhooks/lib/, and emit from the relevant feature. - Add a tasker task type: register the type in the tasker config, add a producer (call
tasker.enqueue(...)), and a consumer. - Add a Trigger.dev job: declare it in
packages/features/trigger.config.ts(or wire from a feature) and deploy withyarn deploy:trigger:prod. - Add a cron: drop a YAML in
.github/workflows/and an HTTP handler inapps/web/pages/api/cron/.
Related pages
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.