Scheduling

Scheduled workflows run automatically on a time-based cadence. Thallus uses standard cron expressions with timezone support, and provides a visual builder so you don't need to memorize cron syntax.

Cron syntax

Schedules are defined using standard 5-field cron expressions:

┌───────────── minute (0–59)
│ ┌───────────── hour (0–23)
│ │ ┌───────────── day of month (1–31)
│ │ │ ┌───────────── month (1–12)
│ │ │ │ ┌───────────── day of week (0–7, Sun=0 or 7)
│ │ │ │ │
* * * * *

Common examples:

Expression Description
0 9 * * 1-5 Weekdays at 9:00 AM
0 9 * * * Every day at 9:00 AM
0 */4 * * * Every 4 hours
30 8 1 * * 8:30 AM on the 1st of each month
0 0 * * 0 Midnight every Sunday
*/15 * * * * Every 15 minutes
0 9,17 * * 1-5 Weekdays at 9:00 AM and 5:00 PM

Special characters:

Character Meaning Example
* Every value * * * * * (every minute)
, List of values 0 9,17 * * * (9 AM and 5 PM)
- Range * * * * 1-5 (Monday through Friday)
/ Step */15 * * * * (every 15 minutes)

Visual schedule builder

The workflow creation page includes a visual schedule builder that generates cron expressions from dropdown selections:

  1. Frequency — select hourly, daily, weekly, or monthly
  2. Day — for weekly schedules, pick the day(s) of the week
  3. Time — set the hour and minute

The builder shows a live preview of the resulting schedule in plain language (e.g., "Every weekday at 9:00 AM") so you can verify it matches your intent before saving.

Timezone handling

Schedules evaluate in the timezone you select during configuration. The system converts this to UTC for internal storage and scheduling:

  1. You configure a schedule with a timezone (e.g., "America/New_York")
  2. The cron expression is evaluated in that timezone to determine the next run time
  3. The next run time is converted to UTC for internal storage
  4. The scheduler compares the next run time against current UTC time each minute

This means a "9:00 AM Eastern" schedule runs at the correct local time regardless of daylight saving changes.

Internal mechanics

How scheduled workflows execute

The scheduler periodically checks for due workflows. Each workflow that has reached its scheduled time is queued for execution. After execution, the system calculates and stores the next run time.

There may be a brief delay between the scheduled time and actual execution start due to the periodic check interval.

Next run calculation

After each execution, the system calculates the next run time:

  • Parses the cron expression with the configured timezone
  • Gets the next occurrence after the current time in the local timezone
  • Converts to UTC for storage

If the cron expression is invalid or the calculation fails, the next run time is not set and the workflow will not execute again until the issue is resolved.

Pausing and resuming

Pausing a workflow (setting its status to Paused) prevents scheduled executions from firing. The next_run_at value is preserved, so when you reactivate the workflow:

  • If next_run_at is in the past, the workflow executes on the next scheduler check (shortly)
  • If next_run_at is in the future, the workflow waits for the scheduled time

Missed executions during the pause period are not retroactively run. The workflow simply picks up from the next scheduled occurrence.

Validation

The system validates cron expressions before saving. Invalid expressions (wrong number of fields, out-of-range values, malformed syntax) are rejected with an error message explaining what's wrong.

The system generates a human-readable description of any valid cron expression, shown in the UI to confirm the schedule matches expectations.