Scheduled jobs
Scheduled work runs as Inngest functions. This table is read from source (src/inngest/**); the live cadence of any job that reads an environment variable is whatever production sets, so confirm in the Inngest dashboard before relying on a number. Times are UTC unless noted.
Data sync
| Function id | Cron (default) | What it does | Controls |
|---|---|---|---|
sync-marketing-metrics | 7,37 * * * * | Fans out client syncs and commerce work. Does not dispatch paid ad work itself. | MARKETING_SYNC_CRON (production overrides the code default) |
paid-account-conveyor | */10 * * * * | Picks one paid ad account per tick, oldest data first, and syncs it. This is the ordinary retry path for failed paid syncs (about one fleet rotation). | none |
paid-today-refresh | 12,42 * * * * | Refreshes same-day ad spend for every live account, so "Ad spend as of" is at most about 30 minutes old. A platform throttled in the last 30 minutes sits out the slot. | PAID_TODAY_REFRESH_ENABLED=false makes every tick a no-op |
sync-self-healer | 5,25,45 * * * * | Re-dispatches paid ad-account syncs that are stuck (interrupted run, exhausted retries, expired throttle). It only sends the same event the conveyor sends, never pauses or resumes a binding, and refuses a binding the conveyor handled within a rotation. | Off unless SYNC_HEALER_ENABLED=true; cron via SYNC_HEALER_CRON |
sync-hyros-orders | 43 * * * * | Order-grain Hyros events. | none |
sync-vrio-reports | 51 * * * * | Vrio report-grain CRM attribution (a shadow source until a client's CRM source is switched). | none |
sync-ga4 | 17 */6 * * * | GA4 daily purchases per bound property. | none |
sync-entity-metadata | 23 */6 * * * | Status, schedule, spend cap, landing URL and other entity metadata used by the Status columns and the Landing Page breakdown. | none |
paid-account-onboarding | 47 8 * * * | Retained-history onboarding for new paid accounts. | none |
meta-account-onboarding | 17 8 * * * | Meta history, then dimensions, then creatives for new accounts. | none |
Checks and monitoring
| Function id | Cron (default) | What it does |
|---|---|---|
paid-coverage-audit | 23 9 * * * | Finds days with no paid data and re-requests them. |
entity-parity-monitor | 23 10 * * * | Compares Google campaign and ad group numbers with Google; a difference becomes an Issue. |
monitor-launchpad-v2-runtime | */10 * * * * | Probes whether the app is reachable and records an alert or recovery notice (alerts are suppressed for an hour after one is sent). |
inngest-self-sync | 2,17,32,47 * * * * | Re-registers functions with Inngest so a new function goes live shortly after a deploy. Production only. |
spend-guard-tick | 4,19,34,49 * * * * | Checks spend for every enabled Spend Guard. |
spend-guard-daily-summary | 9,24,39,54 * * * * | Sends the daily Slack summary when its configured local time is reached. |
ClickUp and creative
| Function id | Cron (default) | Controls |
|---|---|---|
reconcile-clickup-marketing-identity | 15,45 * * * * | CLICKUP_IDENTITY_SYNC_CRON |
bind-ads-to-clickup | 30 3 * * * | BIND_ADS_CRON |
backfill-creative-metadata | 0 4 * * * | CREATIVE_METADATA_BACKFILL_CRON |
backfill-launchpad-metadata | 30 4 * * * | LAUNCHPAD_METADATA_BACKFILL_CRON |
incomplete-editing-report | 0 6 * * 1-5 in America/New_York | none |
Operating notes
- Concurrency is deliberately low: spend-guard checks run 5 at a time and 1 per ad account, and paid syncs share a single gate. Do not raise these without checking the Inngest plan limit.
- A job that is "off" by flag still shows as registered in Inngest; a tick simply logs that it is disabled.
- Runbooks: Sync failures, Durable steps, ClickHouse rollups.