Skip to content

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:

PresetCron
Every 15 min*/15 * * * *
Hourly0 * * * *
Daily 09:000 9 * * *
Weekdays 09:000 9 * * 1-5
Mondays 09:000 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:

FormExampleMeaning
Wildcard*Every value in the field
Single value9Exactly 9
List0,15,30,45Any listed value
Range1-51 through 5 inclusive
Step*/15Every 15th value (0, 15, 30, 45)
Range with step0-30/10Every 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/tickonce 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.

See also

FlowRunner — the no-code platform for small businesses.