Core / Cron sweep
Cron sweep
The durability floor beneath every delivery mode. Required for cron and deferred, recommended everywhere.
Why it exists
Every delivery mode writes the same committed rows; the sweep is what guarantees a pending
delivery eventually gets attempted even if waitUntil never fires, an in-process worker crashes,
or a serverless function is frozen mid-request. See Delivery modes for how
the modes layer on top of it.
Wiring it up
A single authenticated POST, from anything that can run on a schedule:
POST /api/notifications/cron
Authorization: Bearer $NOTIFY_CRON_SECRET
Vercel Cron, a GitHub Actions scheduled workflow, a cron container hitting curl, your existing job scheduler — any of them work. There's nothing special about the caller; it just needs to be able to make an authenticated HTTP request on an interval.
Unauthenticated, this route is a free "flush everything right now" trigger against your email
provider. cron.secret is compared in constant time; treat it like any other credential.
Choosing a frequency
1–5 minutes is the usual range. Two things scale with the interval:
- Worst-case latency for anything relying on
cronmode alone (noinline/deferred/workerlayered on top) — a notification can wait up to one full interval before its first attempt. - Retry pacing — backoff intervals are floored by the cron frequency, so a 5-minute cron can't retry a failed delivery faster than 5 minutes regardless of what the backoff schedule says.
There's no lower bound the library enforces; a busy app can run it every 30 seconds if the scheduler supports it.
The digests plugin has its own
digests() registers a separate /digests/cron route, machine-scoped the same way, meant to be
hit hourly rather than on the main interval — digest windows are computed in the recipient's own
timezone, and hourly is what makes "9am" resolve correctly across DST without a second scheduler
per timezone. See Digests.