Appearance
Scheduled (cron)
Give a flow a cron expression and FlowRunner runs it on a clock — no request, no inputs, just the flow doing its work once a minute matches. This page covers the Schedule dialog, the exact cron syntax supported, and how a tick actually fires.
What a schedule does
A schedule pairs one flow file with a cron expression. When the current minute matches, the platform runs that flow from its Start node with no inputs (an empty input object). The result lands in run history tagged as a CRON run, so you can see every fire, its timing, and any error.
This is the trigger for work that isn't driven by a visitor: a nightly summary email, a periodic sync with an external API, a cleanup job.
The Schedule dialog
Open the Schedule dialog for a flow from the canvas. It has three parts:
- An Enabled switch — a schedule can exist but be paused.
- A row of preset chips for common cadences.
- A cron expression field with live validation.
INFO
📸 Screenshot — the Schedule dialog showing the preset chips and the cron field.
The presets are shortcuts that fill the cron field for you:
| Preset | Cron |
|---|---|
| Every 15 min | */15 * * * * |
| Hourly | 0 * * * * |
| Daily 09:00 | 0 9 * * * |
| Weekdays 09:00 | 0 9 * * 1-5 |
| Mondays 09:00 | 0 9 * * 1 |
Save writes the schedule; Remove deletes it. Creating or editing a schedule needs editor access to the project.
IMPORTANT
Schedules are evaluated in UTC, always. 0 9 * * * fires at 09:00 UTC, not in your local timezone. Convert your intended local time to UTC when you write the expression.
Cron syntax
FlowRunner uses standard 5-field cron:
┌───────────── minute (0–59)
│ ┌─────────── hour (0–23)
│ │ ┌───────── day of month (1–31)
│ │ │ ┌─────── month (1–12)
│ │ │ │ ┌───── day of week (0–7, 0 and 7 = Sunday)
│ │ │ │ │
* * * * *Each field supports:
| Form | Example | Meaning |
|---|---|---|
| Wildcard | * | Every value in the field |
| Single value | 9 | Exactly 9 |
| List | 0,15,30,45 | Any listed value |
| Range | 1-5 | 1 through 5 inclusive |
| Step | */15 | Every 15th value (0, 15, 30, 45) |
| Range with step | 0-30/10 | Every 10th value within the range |
There is no support for month or weekday names (JAN, MON), and no non-standard extensions like @daily or L — use numbers.
NOTE
The classic cron quirk applies: when both day-of-month and day-of-week are restricted (neither is *), the flow fires when either matches. When only one is restricted, that one must match. When both are *, every day matches.
How a tick fires
FlowRunner does not compute "next run times." Instead an external timer pings a single endpoint — /api/cron/tick — once a minute, and the platform checks every enabled schedule against the current minute.
Two properties fall out of this design:
- Missed ticks are simply skipped, never made up. If the timer misses a minute, that minute's schedules don't fire — they aren't queued and replayed later.
- A double tick is safe. Each schedule records the minute it last fired, so re-pinging the endpoint within the same minute won't run a flow twice.
Each schedule runs in isolation — one flow throwing is recorded as an error on that schedule and never blocks the others.
Wiring the timer
The once-a-minute ping is the only piece a platform operator has to set up — everything else is self-contained. Point any reliable timer (Vercel Cron, a GitHub Action, an uptime pinger) at /api/cron/tick, carrying the CRON_SECRET as a bearer token or x-cron-secret header.
WARNING
Scheduled triggers are off until CRON_SECRET is set. The tick endpoint fails closed: with no secret configured, every call is rejected, so nothing runs. See Scheduled triggers wiring for the full setup.