Skip to content

Scheduling

Bizon Platform uses APScheduler for reliable cron-based scheduling of pipeline runs.

  1. Scheduler Process runs in-process with the FastAPI API server
  2. Cron expressions define when pipelines should run
  3. Job queue receives pending runs for workers to execute
  4. Workers poll the queue and execute pipelines
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Scheduler │────▶│ Job Queue │────▶│ Workers │
│ (APScheduler) │ │ (PostgreSQL) │ │ (Executors) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
Every minute PipelineRun Claim & Run
checks cron status=pending pipelines

Standard 5-field cron syntax:

┌───────────── minute (0-59)
│ ┌───────────── hour (0-23)
│ │ ┌───────────── day of month (1-31)
│ │ │ ┌───────────── month (1-12)
│ │ │ │ ┌───────────── day of week (0-6, 0=Sunday)
│ │ │ │ │
* * * * *
ScheduleExpressionDescription
Every hour0 * * * *At minute 0 of every hour
Every 6 hours0 */6 * * *At 00:00, 06:00, 12:00, 18:00
Daily at midnight0 0 * * *At 00:00 every day
Daily at 9 AM0 9 * * *At 09:00 every day
Weekdays at 8 AM0 8 * * 1-5Mon-Fri at 08:00
Weekly on Sunday0 0 * * 0Sunday at midnight
Monthly on 1st0 0 1 * *1st of month at midnight
Quarterly0 0 1 1,4,7,10 *Jan, Apr, Jul, Oct 1st
  1. Edit the pipeline
  2. Enter cron expression in “Schedule” field
  3. Save changes

Set the schedule to null or empty string for manual-only execution:

{"schedule": null}
StateScheduled Runs
enabled: true + scheduleRuns automatically
enabled: true + no scheduleManual only
enabled: false + scheduleSchedule ignored
enabled: false + no scheduleManual only

Schedules use the server’s timezone. For consistent behavior in production:

Terminal window
# Set timezone in Docker
TZ=UTC

If a run is still in progress when the next scheduled time arrives:

  1. New pending run is created
  2. Worker claims when available
  3. No runs are skipped

To prevent overlap, ensure schedules account for typical run duration.

The UI shows the next scheduled run time for each pipeline.

Check if scheduled runs executed on time:

Terminal window
curl http://localhost:8000/api/pipelines/{id}/runs?triggered_by=schedule

The scheduler runs in the API process. Check API health:

Terminal window
curl http://localhost:8000/api/health
# {"status": "healthy"}
  1. Check enabled - Pipeline must be enabled
  2. Verify schedule - Test expression at crontab.guru
  3. Check workers - At least one worker must be running
  4. View logs - Check API logs for scheduler errors
  1. Scale workers - Add more workers for high load
  2. Check database - Ensure PostgreSQL is responsive
  3. Review run duration - Long runs may cause backlog

Rare, but can occur if:

  • Multiple API instances without proper locking
  • Clock skew between servers

Solution: Use a single API instance or shared lock.

SettingDefaultDescription
WORKER_POLL_INTERVAL2Seconds between worker polls
  1. Stagger schedules - Avoid all pipelines at 0 0 * * *
  2. Allow margin - Schedule before deadlines, not at
  3. Monitor failures - Set up alerts for failed runs
  4. Use off-peak hours - Heavy syncs during low-usage times