Skip to content

SQLMesh Jobs

Quick Summary

SQLMesh jobs in dagctl are scheduled workers that keep your SQLMesh environments up to date. Each job runs inside a Kubernetes pod that is injected with your project's credentials and state connection, then processes the models that are due to run.

Setting Recommended Why
Job Type sqlmesh run + separate sqlmesh janitor Prevents janitor failures from blocking data execution
Schedule (Cron) */15 * * * * Matches most common model cadences
Slack Alerts Enabled on failures Get notified when jobs fail

Key Takeaways

  • Run sqlmesh run and sqlmesh janitor as separate jobs - A failed janitor should not disrupt production model execution
  • Schedule at the rate of your most frequent model - No more frequent than every 5 minutes
  • 15-minute intervals work well for most teams - Adjust only if your models require tighter SLAs
  • ⚠️ Keep the interval longer than your run duration - Overlapping runs are rejected as skipped, not queued
  • ⚠️ One run job per project - Model selectors in the job command are ignored
  • ⚠️ Cron schedules are evaluated in UTC - 0 6 * * * runs at 06:00 UTC regardless of where your team is

Job Types

sqlmesh run

Executes your SQLMesh models for the current interval. This is the primary job type. dagctl submits the job on schedule, and the execution pod acts as a worker draining your project's work queue, which is populated every 5 minutes from the models that have intervals due.

Models execute concurrently within the job, up to the MAX_CONCURRENT_MODELS limit. See Execution for details on the concurrency model.

Model selectors have no effect

Which models a run job processes is determined entirely by the work queue, not by the job's command. Selector flags such as --select-model are accepted and then ignored — a job configured with a selector processes exactly the same work as one without.

Creating several run jobs with different selectors does not partition your DAG. It produces several identical workers competing for the same queue. Use a single run job per project.

sqlmesh janitor

Cleans up expired intervals and stale state entries. A job is treated as a janitor job when its command contains the word janitor; otherwise it runs as a queue worker. Janitor runs should be scheduled separately from sqlmesh run jobs.

Warning

Do not combine sqlmesh run and sqlmesh janitor in the same job. If the janitor fails, it will prevent model execution from completing. Run them on independent schedules so failures are isolated.

Scheduling

The cron schedule controls how often dagctl triggers a new job pod. Set the schedule to match the cadence of your most frequently-running model.

Model cadence Recommended job schedule
Hourly 0 * * * *
Every 30 minutes */30 * * * *
Every 15 minutes */15 * * * *
Every 5 minutes */5 * * * * (minimum)

Do not schedule faster than your run duration

max_concurrent_job_runs defaults to 1. If a run is triggered while the previous one is still executing, the new run is rejected and recorded with a status of skipped — it does not queue and it does not run later.

Choose an interval comfortably longer than your typical run duration, or raise max_concurrent_job_runs on the project. Watch for skipped runs in your run history; they indicate the schedule is outpacing execution.

Concurrency

Two separate limits apply:

Limit Default Controls
MAX_CONCURRENT_MODELS 5 Models executed in parallel within a single job run. Override per job via the job's environment variable settings.
max_concurrent_job_runs 1 Job runs allowed to execute simultaneously for a project. Additional runs are rejected as skipped.

For full details on the work queue and parallel execution, see Execution.

Next Steps