Octov0.11.7
Guides

Scheduled Jobs

Run flows on a cron schedule.

Trigger flows on a schedule with the cron source, build the tick payload with CEL, reuse processors by name, and write structured logs to a file. It follows samples/heartbeat.yaml and samples/file-logger.yaml.

The flow in the visual editor

A heartbeat every two seconds

The cron connector needs no settings; each flow's source carries its own schedule. The payload is a CEL expression evaluated at fire time, with the fire time available as now, and its result becomes the message body. The sample also shows named processors: define a block once under processors: and reference it from any flow with ref:.

service:
  name: heartbeat

connectors:
  - name: ticker
    type: cron

# Named processor definitions. Flow blocks reference these by `ref`.
processors:
  - name: heartbeat-log
    type: log
    settings:
      level: info
      message: '"heartbeat fired at " + body.firedAt'

flows:
  - name: heartbeat
    source:
      connector: ticker
      type: cron
      settings:
        # Descriptor schedule: fire every two seconds.
        schedule: "@every 2s"
        payload: '{"firedAt": string(now), "kind": "tick"}'
    process:
      - ref: heartbeat-log

Run it and watch the ticks:

bin/octo run --config samples/heartbeat.yaml

Schedule syntax

The schedule setting accepts two forms:

Descriptors such as @every 2s, @every 1h30m, @hourly and @daily.

Cron expressions with seconds: six fields (sec min hour dom mon dow) rather than the usual five, so schedules have second granularity. 0 30 9 * * 1-5 fires at 09:30:00 on weekdays; */10 * * * * * fires every ten seconds.

A bad schedule or payload expression fails at startup, not at the first tick. The source also accepts a static correlationID to stamp on every emitted message.

When you run multiple replicas of the same service, cron sources elect a leader per connector, so each schedule fires once across the cluster rather than once per replica.

Log to a file

In samples/file-logger.yaml a named logger connector owns its output file (opened on start, closed on shutdown), and any log block writes through it by name.

service:
  name: file-logger-demo

connectors:
  - name: ticker
    type: cron
  - name: audit
    type: logger
    settings:
      output: /tmp/octo-audit.log
      format: json
      level: info
      addSource: false

flows:
  - name: audit-ticks
    source:
      connector: ticker
      type: cron
      settings:
        schedule: "@every 2s"
        payload: '{"date": string(now)}'
    process:
      # This log block writes through the named "audit" logger connector.
      - type: log
        settings:
          logger: audit
          message: '"tick at " + body.date'

All logger settings are optional. The defaults are output: stdout, format: text, level: info. Set format: json for structured lines and addSource: true to include the source location in each record.

Run it and tail the file:

bin/octo run --config samples/file-logger.yaml
tail -f /tmp/octo-audit.log
{"time":"2026-07-09T10:15:04Z","level":"INFO","msg":"tick at 2026-07-09 10:15:04.001 +0000 UTC"}

Where to go next

On this page