Docs

Cron and background jobs

All background work runs through one entry point, **GET /v1/cron/tick** (bearer CRON_SECRET). A tick collects the jobs that are due for projects with recent activity, claims them with leases and runs them – least recently served first – until X3_CRON_BUDGET_MS is used up.

Triggers

DeploymentTrigger
Vercel ProVercel Cron every 15 min (apps/api/vercel.json)
Vercel HobbyVercel Cron once a day plus an external scheduler (recommended every 5 min)
StandaloneX3_SCHEDULER=1 – in-process tick every minute
Anythingany HTTPS cron: curl -fsS -H "Authorization: Bearer $CRON_SECRET" https://<api>/v1/cron/tick

A tick that runs out of budget while work is still due re-invokes itself in the background (header x-3x-tick-hop), at most X3_TICK_MAX_HOPS (12) times per trigger. Leases outlive the tick, so the same job is never run twice at the same time, even with overlapping triggers.

Conversion retries and expired salts are additionally piggybacked on ingest traffic (at most every 5 minutes across instances), so a quiet scheduler never delays them much.

Jobs

JobIntervalWork
ingest.saltsdailycreates tomorrow's salt, deletes yesterday's (session hashes become unlinkable)
ingest.cleanupdailyretention per project (raw sessions, pageviews, events), abnormal sessions, storage guard
ingest.usagedailystored-bytes estimate per project (quotas)
ingest.housekeepingdailyidempotency keys, expired user sessions, magic links, webhook deliveries
analytics.rollupfrequentdaily session rollups for long ranges; recomputes days marked dirty
analytics.rescorewhen queuedre-scores sessions after relevance rule changes
conversions.retry5 mindue uploads, batch 25, conversions younger than 90 days
conversions.purgedailyclears transient request context; held rows older than 7 days → skipped
mcp.housekeeping10 minexpired OAuth codes and tokens, long-revoked grants
ads.entities, ads.metrics, ads.clicks, ads.backfill, ads.match, ads.health, ads.fxsee Adsad cost import

GET /v1/cron/{job} runs a single job (same secret) – useful after a deploy or for debugging.

What to expect per plan

  • Vercel Pro / fluid (300 s functions, budget 280 s, cron every 15 min): a 90-day backfill of four ad platforms finishes in one cron call plus a few hops – about 20–40 minutes of wall time, dominated by 10–30 s report calls.
  • Vercel Hobby (60 s functions, budget 40 s, cron once a day): the daily cron plus 12 hops gives roughly 10 minutes of work per day. A backfill then takes several days – add an external scheduler.
  • Standalone: limited only by the database; ticks every minute.

Monitoring

  • GET /v1/projects/{project}/status (dashboard Settings → Status) shows the last run per job, quota usage, pending rescoring and conversion warnings.
  • Ad syncs log every run in …/ads/sync-runs (status, rows, error kind, retry time).
  • Job errors are logged with the job name and scope, never with personal data.