schedules

Cron that shows up.
Every run, its own machine.

Attach a cron expression to a function and it fires on time — no runner to babysit, no shared box collecting state between jobs. Every scheduled run executes in a fresh isolated microVM, exactly like a manual invoke.

1-min
finest granularity
5-field
standard cron
1 VM
per run
schedule: "*/15 * * * *"
cron

Write cron the way you already know it.

Standard 5-field expressions — minute, hour, day of month, month, day of week. */5 * * * * just works, and the finest granularity is one minute. No custom DSL, no rate() dialect to translate in your head.

The five fields, unchanged

A schedule is a cron string attached to a function id. Deploy the function once, attach the expression, and it fires until you pause it — change cadence later with a single update, no redeploy of the underlying code.

*/5 * * * * — every 5 min0 * * * * — every hour0 9 * * * — daily 09:00 UTC0 0 * * 1 — Mondays, midnight UTC
shell — npm i -g @pandastack/sdk
# ship the function once
pandastack function deploy handler.py \
  --name daily-report --runtime python

# attach a cron — every day at 09:00 UTC
pandastack schedule create --name daily-report \
  --fn <function-id> --cron "0 9 * * *"
runtime

A fresh microVM answers every tick.

Cron on a shared runner means one job's leftovers become the next job's bug. Here, every scheduled run executes the target function in a fresh isolated Firecracker microVM — the same path a manual invocation takes.

Fresh runtime, every run

No shared state, no noisy neighbours. Each run boots its own machine, does its work, and disappears — nothing accumulates between ticks.

VM-level isolation

Scheduled code runs behind hardware virtualization, not a container namespace. kill -9 can't escape the sandbox.

Golden metrics included

Every invocation lands in ClickHouse automatically — p50/p95/p99 latency, error rate, cold-start rate — scheduled runs included.

operate

Operate it like software, not crontab.

A schedule is a record you can read and act on — cron, paused, last_run_at — not a line in a file on a box somewhere. Pause without deleting, trigger on demand, audit every run through the API.

Test now, not at 09:00

Manual triggers run the cron-backed workflow immediately, so you never wait for the next window to find out a job is broken. Pausing keeps the definition and stops future automatic invocations until you resume — the schedule and its history stay put.

pausedlast_run_atruns history
shell — operating a schedule
# pause without deleting; resume picks the cron back up
pandastack schedule pause <schedule-id>
pandastack schedule resume <schedule-id>

# run it right now, then read the history
pandastack schedule trigger <schedule-id>
pandastack schedule runs <schedule-id>

# change cadence without touching the function
pandastack schedule update <schedule-id> --cron "0 */6 * * *"
pair with functions

Ship a bundle once, schedule it forever.

Schedules drive PandaStack Functions — Python or Node.js bundles stored in GCS, versioned on every deploy. You can even pre-register a function with no code, attach the schedule immediately, and it starts firing the moment the first bundle lands.

Ship on the millisecond cloud.

Free tier with $5.40/mo usage credit. No card. Apache-2.0.