Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Interval trigger

Fire a workflow on a fixed wall-clock cadence β€” every: 30s | 1m | 5m. No chain config needed. Unlike cron, intervals allow sub-minute cadences, so a 30-second keeper needs no cron hacks.

workflows:
  price-keeper:
    trigger:
      interval:
        every: 30s          # fire every 30 seconds
        catch_up: false     # optional β€” skip ticks missed while down (default)
    steps:
      - id: poke
        send_transaction:
          network: ethereum
          relayer: keeper
          to: "0xOracle..."
          function: "poke()"
FieldRequiredDescription
everyβœ…Fire cadence as a duration (30s, 1m, 5m, 1h). Sub-minute is allowed. Must be positive
catch_upfalseReplay the ticks missed while rflow was down β€” see catch-up

The trigger payload exposes trigger.scheduled_for (the ISO instant) and trigger.workflow to expressions.

Interval vs cron vs read polling

UseTrigger
A fixed cadence, "every N seconds/minutes"interval (every: 30s)
A calendar schedule, "09:00 on Mondays", timezonescron (expression, tz)
Fire only when an on-chain value crosses a thresholdread (condition)

Exactly-once for the cadence

Ticks land on a stable grid anchored at first boot (anchor, anchor + every, anchor + 2Β·every, …; the first fire is one interval after boot). Each firing claims a trigger key derived from its scheduled instant β€” interval:{workflow}:{ISO} β€” never now(). A restart landing on the same instant, or a second scheduler, claims the same key and the duplicate is skipped. Exactly-once, exactly like events and cron.

The next-due instant is persisted per workflow in rflow.interval_state, so the grid survives restarts: the schedule resumes on the same phase instead of re-anchoring (which would fire immediately on every boot). If you shorten every (say 1h β†’ 30s) and restart, the stale long cursor is clamped to at most one new interval out, so the faster cadence takes effect promptly rather than waiting out the old hour.

catch-up β€” missed ticks

Interval catch-up is deliberately distinct from cron's. Cron replays a calendar; an interval replays a fixed-cadence grid off the persisted cursor.

  • catch_up: false (default): ticks that came due while the process was down are skipped. The cursor jumps forward β€” staying on the original grid phase β€” to the first instant after now, and the schedule resumes. No missed tick is claimed.
  • catch_up: true: on boot every grid instant missed while rflow was down is claimed, each under its own scheduled-instant key (so a repeated boot can never double-fire).

Examples

interval: { every: 15s }                    # every 15 seconds
interval: { every: 1m }                     # every minute
interval: { every: 5m, catch_up: true }     # every 5 minutes, replayed if missed

Combine with send_transaction for keeper pokes and heartbeats, or keep it fully off-chain. Polling a web feed or API with interval + http_call? The web trigger does the fetch, parse, new-item diff and dedupe for you. To rehearse an interval workflow's steps without waiting for the schedule, use rflow test with a { "scheduled_for": "..." } fixture.