Reference

Cron schedules

Several features run on a cron schedule: SSL monitor probes, vault expiry digests, scheduled push deploys, and ACME auto-renew. This page explains the model.

The global ticker

Vercel Cron pings /api/monitor/cron once per hour. That endpoint does no per-tenant work on its own — it reads every tenant's schedule + last-run timestamp, and decides (via cron-parser) whether a firing is due in the window (last_run, now]. If yes, it runs; if no, it skips.

This means you don't need sub-hour granularity: the tightest cadence is hourly, and the ticker acts as the shared clock. You set your own cron expression; it fires within at most one hour of the target time.

Preset expressions

The UI hides the cron syntax behind presets. Here's what each one means:

  • 0 2 * * * — Daily at 02:00 (default for monitoring)
  • 0 9 * * * — Daily at 09:00 (default for expiry digest)
  • 0 14 * * * — Daily at 14:00
  • 0 */12 * * * — Every 12 hours
  • 0 */6 * * * — Every 6 hours
  • 0 * * * * — Every hour on the hour
  • 0 2 * * 1 — Weekly, Monday at 02:00

Timezones

Every expression is interpreted in your account-wide timezone (Settings → Preferences). DST shifts are handled by cron-parser: your "Daily at 09:00" still fires at 09:00 local on both sides of the spring-forward / fall-back boundary, not at the naive UTC offset.

The default timezone is UTC; we try to detect your browser zone on first visit and prefill it, but you have to hit Save to commit.

What happens on a missed tick

If Vercel misses an hourly tick (rare), the next tick catches up automatically — isFireDue() checks the full window since the last run. If you're supposed to fire at 02:00 and Vercel misses that hour, you fire at 03:00 instead. You might get a slightly delayed digest but you won't miss one outright.

Seeing your last run

Each schedule records its last-run timestamp:

  • Monitor probe: last_probe_run_at (visible at /dashboard/monitor)
  • Expiry digest: last_expiry_digest_at (visible in Settings → Alerts)
  • Scheduled push: last_scheduled_push_at (visible per-target on the Schedule panel)
  • ACME renewal: renew_notified_at on the order (visible in the audit log)

Vercel Hobby limits

The function cap is 60 seconds. Current tuning:

  • Up to 8 concurrent workers for monitor probes → ~480 hosts per tick
  • Up to 1 ACME renewal per tick (DNS + ACME validation + finalize takes 15-40s)
  • Push deploys are also 60s-capped each; we process them serially per tick

At steady state, a tenant would need thousands of hosts or dozens of simultaneous renewals to feel these limits. If you bump into them, get in touch — we have sharding options up our sleeve.