All docs

Docs · Reference

Scheduled

Run work at a future time

Cron turns the clock into a tick; scheduled turns a single instant into one event. A rule enqueues "run this, not before T" and walks away; the chassis fires it when T arrives.

Where cron is recurring and tenant-wide, scheduled is a one-shot you place from inside a flow — a follow-up email next Tuesday, a reminder in two weeks, the next installment at 08:00.

Enqueue with txco://schedule

Any rule can place an event. The tenant is the request-pinned tenant, so the event always fires back into the tenant that scheduled it.

EXEC "txco://schedule" WITH
  idempotency_key = "drip:reader@example.com:37",   # dedup + cancel handle
  schedule_at     = "2026-06-30T08:00:00Z",         # RFC3339; "not before"
  payload         = .job                            # any JSON object
  • idempotency_key is scoped to the tenant. Re-running with the same key while the event is still pending reschedules in place (new time/payload) — no duplicate. Once it has fired, the key is spent.
  • Cancel a pending event: EXEC "txco://schedule" WITH idempotency_key = "…", cancel = true.

Firing

At its due time the event is delivered into your tenant’s _scheduled stack (define one to receive them — the stack’s existence is the subscription, like _cron). Your payload rides on @scheduled.payload:

# _scheduled/0/route.txcl
WHEN @scheduled.payload.kind == "drip"
EXEC "txco://route" WITH stack = "send-drip"
FieldMeaning
@scheduled.payload.*the JSON object you enqueued
@scheduled.idempotency_keythe key it was scheduled under
@scheduled.event_idstore row id
@scheduled.fired_atfire instant, UTC RFC3339
@scheduled.tenant / @scheduled.nodesubscriber / firing chassis

Delivery

Events live in a durable table (--scheduled-store, default sqlite). The poller claims each due row before firing — a status flip, so a slow fire can’t double-send — and a claim left stranded by a crash is retried after --scheduled-stale-after. A response timeout is treated as fired (at-most-once bias — the work likely ran). Outcomes are visible in the logs and trace only.

Flags

FlagDefaultMeaning
--scheduled-storesqliteBackend for the scheduled_events table
--scheduled-db-path./chassis/data/scheduled.dbBundled SQLite store path
--scheduled-period20Seconds between poll passes (worst-case firing latency past schedule_at)
--scheduled-max-inflight32Concurrent fires per pass
--scheduled-stale-after600Seconds before an abandoned claim is retried
--scheduled-retention604800Seconds to keep terminal (done/failed) rows

Enable by adding scheduled to --personalities.

Edit this page · View as markdown