All docs

Docs · Channels

Cron

time as a channel

The cron head turns the clock into events: every --cron-period seconds (default 60), subscribed stacks receive a tick envelope and their rules decide what the hour demands.

Subscribing is implicit

Define a stack named _cron in your tenant and you’re subscribed: each tick, the chassis queries for tenants with a _cron stack and delivers one envelope per tenant (@cron.job = "_cron", @cron.tenant = <slug>). No registration, no YAML — the stack’s existence is the subscription.

The tick envelope

Rules match on wall-clock fields rather than cron syntax:

WHEN @cron.hour == 9 && @cron.minute == 0     # every day at 09:00
EXEC "https://ops.example.com/morning-sweep"
FieldMeaning
@cron.{minute,hour,dom,dow,month,year}Wall-clock at the tick
@cron.mod5 / mod10 / mod15 / mod30Precomputed buckets — WHEN @cron.mod15 == 0 fires every 15 minutes
@cron.bucketCanonical period-boundary timestamp — the fleet dedup key
@cron.tickMonotonic counter since boot
@cron.job / @cron.tenant / @cron.node_cron or default / subscriber / firing chassis

Tenant deliveries are smeared across the period (a deterministic per-tenant offset) so a thousand tenants don’t stampede at second zero — but the envelope’s clock fields are frozen at the tick instant, so WHEN @cron.minute == 0 still means minute zero regardless of when your delivery lands.

Flags

FlagDefaultMeaning
--cron-period60Seconds between ticks (min 1)
--cron-max-inflight32Concurrent dispatches per tick
--cron-system-tickfalseEnable the tenant-less system tick
--cron-queuelocalQueue backend (in-process; the interface is pluggable for brokers)

The local queue is single-node, at-most-once — no retries, no cross-node dedup. Fleet-grade scheduling rides on @cron.bucket as the dedup key.

Edit this page · View as markdown