Managing dbt™ Schedules as Code with YAML

Feb 26, 2026

Table of Contents

Managing dbt Schedules as Code with YAML

If you've ever had a dbt™ job mysteriously change its schedule—or worse, disappear entirely—because someone clicked the wrong button in a UI, you already understand the problem. Manual schedule configuration doesn't scale. It doesn't leave a paper trail, it can't be peer-reviewed, and it drifts between environments faster than you can say "configuration drift."

Managing dbt™ schedules as code with YAML brings the same rigor you apply to your dbt™ models—version control, pull request reviews, and automated deployment—to the way you orchestrate those models. This guide covers everything from the core concepts and YAML schema to CI/CD integration, templating, and how purpose-built tools like Paradime Bolt simplify the entire workflow.

What Are dbt Schedules as Code

Schedules as code is the practice of defining when and how your dbt™ jobs run using YAML files stored alongside your dbt™ project in version control. Instead of configuring schedules through a web UI—clicking through forms to set cron expressions, select commands, and configure notifications—you declare everything in a human-readable YAML file. The platform reads that file and ensures the actual schedules match your declared configuration.

This is the same "infrastructure as code" philosophy that tools like Terraform brought to cloud infrastructure, applied specifically to dbt™ job orchestration.

Here are the key concepts:

  • Schedule as code: A YAML file that specifies job triggers, commands, and settings in a human-readable format. It is the single source of truth for how a dbt™ job runs.

  • Declarative configuration: You define the desired state (e.g., "this job runs at 6 AM UTC daily with dbt build --select tag:daily"), and the platform ensures the actual schedule matches that definition.

  • Version-controlled: Schedule definitions live in Git alongside your dbt™ models. Every change is tracked, reviewable, and reversible.

Why Manage dbt Schedules in YAML

YAML-based schedule management brings software engineering best practices—the same ones your engineering team already uses for application code—to data pipeline orchestration. Here's why that matters.

Version Control and Audit Trails

Every schedule change is tracked in Git history. You can see exactly who changed a cron expression from 0 6 * * * to 0 */2 * * *, when they did it, and why (via the commit message). If a schedule change causes issues, you can pinpoint the exact commit and roll back.

This eliminates the "who changed the production schedule?" mystery that plagues UI-configured jobs. With schedules as code, git log is your audit trail.

Peer Review Through Pull Requests

When schedule changes go through the same pull request review process as dbt™ model changes, your team catches misconfigurations before they reach production. A reviewer can spot that a cron expression runs every minute instead of every hour, or that a --select flag is targeting the wrong tag.

This is especially critical for production schedules where a misconfigured job can trigger unnecessary warehouse compute costs or miss an SLA.

Environment Consistency Across Dev, Staging, and Production

With YAML-based schedules, you can promote identical configurations across environments using templating and environment-specific variables. The schedule structure stays the same; only the variables change (e.g., different target schemas, different notification channels).

This eliminates the common problem of staging and production schedules slowly diverging because someone updated one environment's UI but forgot the other.

Reduced Configuration Errors

YAML validation catches syntax errors before deployment. Tools like yamllint or platform-specific validators flag issues like incorrect indentation, invalid cron expressions, or missing required fields. This is a significant improvement over UI-based configuration, where "click drift"—small, unnoticed changes accumulating over time—is the norm.

Figure: The schedules-as-code workflow from authoring to production deployment.

YAML Schema for dbt Schedule Configurations

The structure of a schedule YAML file depends on the platform you use—dbt Cloud™ with dbt-jobs-as-code, Paradime Bolt with paradime_schedules.yml, or another orchestration tool. However, the core fields are consistent across implementations.

Here's a complete example using Paradime Bolt's paradime_schedules.yml format:

And here's a summary of the most common fields you'll encounter:

Field

Required

Description

name

Yes

Unique identifier for the schedule

schedule (cron)

Yes

Cron expression defining run frequency

commands

Yes

dbt™ commands to execute (e.g., dbt run, dbt build)

git_branch

Yes

The Git branch to run against

environment

No

Target environment (e.g., production)

owner_email

No

Email of the schedule owner

timezone

No

Timezone for the cron schedule (e.g., UTC, US/Eastern)

notifications

No

Alert destinations on success, failure, or SLA breach

sla_minutes

No

SLA threshold in minutes; triggers alerts if exceeded

Schedule Name and Description

Choose clear, descriptive names that convey what the schedule does: daily_warehouse_refresh, hourly_incremental_load, or weekly_reporting_build. Avoid generic names like job1 or my_schedule.

The description field appears in the UI and logs, so use it to explain the schedule's purpose and any important context:

Cron Expressions and Trigger Settings

Cron expressions use the standard five-field format: minute hour day-of-month month day-of-week.

Common examples:

  • 0 6 * * * — Every day at 6:00 AM

  • 0 */2 * * * — Every 2 hours

  • 30 8 * * 1-5 — Weekdays at 8:30 AM

  • 0 0 1 * * — First day of every month at midnight

Beyond cron, most platforms support alternative triggers:

  • On run completion: Trigger when another schedule finishes (passed, failed, or both)

  • On merge: Trigger when code is merged to a designated branch

  • API triggers: Trigger programmatically from external systems via webhooks or REST APIs

dbt Commands and Model Selectors

The commands field accepts any valid dbt™ CLI command. Use selectors to target specific subsets of your project:

Common selector patterns:

  • --select tag:daily — Run models tagged as daily

  • --select staging+ — Run the staging model and all downstream dependencies

  • --exclude tag:wip — Exclude work-in-progress models

  • --select state:modified+ — Run only modified models and their children (useful for CI)

  • dbt build — Run models, tests, snapshots, and seeds in DAG order

For advanced use cases, combine selectors:

Environment Variables and Secrets

Never hardcode sensitive values like database credentials or API keys in your YAML files. Instead, reference environment variables that are injected at runtime.

In Paradime Bolt, environment variables are configured at the workspace level and can be overridden per schedule:

For secrets management, Paradime integrates with cloud-native secrets managers:

  • AWS Secrets Manager

  • GCP Secret Manager

  • Azure Key Vault

With dbt-jobs-as-code, you use environment variables set in your CI/CD pipeline or dbt Cloud™ environment:

Notification and Alerting Options

Configure alerts so your team knows immediately when a job succeeds, fails, or breaches its SLA:

Paradime Bolt supports email, Slack, Microsoft Teams, and webhook-based integrations with PagerDuty, DataDog, New Relic, and Incident.io. You can also customize notification templates to control the content and format of alerts.

How to Create and Validate dbt Schedule YAML

The workflow from writing a schedule file to deploying it follows a predictable pattern: define, validate, preview, deploy.

1. Define the Schedule in YAML

Create a new YAML file in your repository. With Paradime Bolt, this is paradime_schedules.yml in your project root. With dbt-jobs-as-code, you typically create files in a jobs/ directory.

Here's a minimal Paradime Bolt example:

And a minimal dbt-jobs-as-code example:

2. Validate YAML Syntax Locally

Catch errors before committing by running validation commands:

Using Paradime CLI:

Using dbt-jobs-as-code:

Using generic YAML linters:

For VS Code users, the YAML extension with dbt-jobs-as-code's JSON schema provides real-time validation and autocompletion:

3. Preview Changes Before Deployment

Before applying changes, preview what will happen. This is the "plan" step—similar to terraform plan—that shows creates, updates, and deletes without actually modifying anything.

Using dbt-jobs-as-code:

This outputs a diff showing which jobs will be created, updated, or deleted, giving you confidence before running the actual sync.

Using Paradime CLI:

Figure: End-to-end workflow for creating and deploying a dbt™ schedule from YAML.

How to Sync and Import dbt Job Configurations

Schedules as code supports bidirectional workflows: pushing YAML definitions to the platform (sync) and pulling existing job configurations into YAML format (import).

Syncing YAML Schedules to Your Orchestration Platform

The "sync" command applies your YAML definitions to the scheduler, creating new jobs, updating existing ones, or deleting jobs that are no longer defined in the YAML.

With dbt-jobs-as-code:

The --limit-projects-envs-to-yml flag ensures the sync only affects projects and environments referenced in the YAML file—a safety measure that prevents accidental changes to other jobs.

With Paradime Bolt:

Paradime reads paradime_schedules.yml from your default branch (main or master) and auto-refreshes every 10 minutes. You can also trigger a manual refresh via the Bolt UI's "Parse Schedules" button.

Figure: Sync workflow from YAML commit to platform update.

Importing Existing dbt Cloud Jobs into YAML

For teams migrating from UI-configured schedules, import commands generate YAML from existing job definitions—no manual transcription required.

With dbt-jobs-as-code:

The import command queries dbt Cloud™ and generates YAML job definitions including environment variable overwrites, giving you a complete starting point for managing jobs as code.

With Paradime Bolt:

Paradime includes a one-click dbt Cloud™ Importer that migrates all your existing dbt Cloud™ jobs to Paradime Bolt in seconds. Navigate to the importer in the Bolt UI, authenticate with your dbt Cloud™ account, and import your jobs for zero-downtime migration. No manual YAML authoring required—the importer handles the conversion automatically.

Templating and Environment Variables in dbt Schedule YAML

Templating prevents duplication and enables you to manage environment-specific differences without maintaining separate YAML files for each environment.

Using Jinja for Dynamic Schedule Configurations

dbt-jobs-as-code supports Jinja templating within YAML files. Define variables as Jinja placeholders and supply their values through a separate variables file:

Schedule definition with Jinja variables (jobs/jobs.yml):

Production variables (jobs/vars_prod.yml):

Staging variables (jobs/vars_staging.yml):

Run the sync with the appropriate variables file:

This approach lets you maintain a single job definition while deploying to multiple environments with different configurations.

Managing Environment-Specific Variables

Best practices for separating environment configurations:

  • CI/CD secrets: Store sensitive values (API keys, database credentials) in your CI/CD platform's secrets manager (GitHub Actions secrets, GitLab CI variables). Reference them as environment variables in your workflow.

  • Platform-native environment management: Use Paradime's workspace-level environment variables or dbt Cloud™'s environment settings to manage variables centrally. Override at the schedule level when needed.

  • .env files for local development: Use .env files (excluded from version control via .gitignore) for local testing. Never commit .env files containing secrets.

  • Cloud secrets managers: For production workloads, integrate with AWS Secrets Manager, GCP Secret Manager, or Azure Key Vault for centralized secrets management with automatic rotation.

Figure: One YAML template, multiple environment-specific variable files.

How to Integrate dbt Schedule YAML with CI/CD Pipelines

The real power of schedules as code emerges when you automate the entire workflow: a developer edits the YAML, opens a pull request, CI runs a plan, a reviewer approves, and upon merge, CI/CD automatically syncs the changes to your platform.

GitHub Actions Workflow Example

Here's a production-ready GitHub Actions workflow based on the dbt-jobs-as-code reference implementation:

Plan on pull request (.github/workflows/plan_on_pr.yml):

Sync on merge (.github/workflows/sync_on_merge.yml):

GitLab CI Pipeline Example

Here's the equivalent GitLab CI configuration:

Both workflows follow the same principle: plan on PR, sync on merge. The plan step provides visibility into what will change, and the sync step applies those changes only after the PR has been reviewed and merged.

Why Not Use Terraform for dbt Job Scheduling

If your team already uses Terraform for infrastructure management, you might wonder: "Can't we just use the dbt Cloud™ Terraform provider to manage our job schedules too?"

You can. A comprehensive Terraform provider for dbt Cloud™ exists and can manage jobs, projects, environments, and warehouse connections. But there are trade-offs to consider:

  • Terraform: General-purpose IaC tool. Requires HCL knowledge, state file management (storage, locking, sharing), and custom provider configuration. No dbt™-aware validation—it won't tell you that --select tag:daly is a typo. Powerful for managing the full dbt Cloud™ configuration (projects, environments, connections) alongside other infrastructure.

  • Schedules as code (dbt™-native): Purpose-built for dbt™ jobs. Uses YAML (already familiar to dbt™ users). No state file required (dbt-jobs-as-code stores the link in job names). Understands dbt™ commands and selectors. Supports templating for multi-environment promotion. Lower barrier to entry for data teams.

The pragmatic approach is to use both:

  • Terraform for warehouse infrastructure (Snowflake roles, BigQuery datasets), dbt Cloud™ project configuration, and CI jobs managed by your platform team.

  • Schedules as code for day-to-day dbt™ job definitions managed by your data team.

This separation aligns with organizational responsibilities: platform engineers manage infrastructure with Terraform, while analytics engineers manage their own schedules with YAML.

Figure: Using Terraform and schedules as code together, aligned to team responsibilities.

How Paradime Bolt Simplifies dbt Schedules as Code

Paradime Bolt is a production-grade dbt™ orchestration platform that treats schedules as code as a first-class feature. It supports YAML-based schedule definitions through paradime_schedules.yml, with built-in validation, a visual UI that stays in sync with your code, and native integrations across your data stack.

Here's what sets Paradime Bolt apart:

  • UI and code together: Define schedules in YAML or the UI—they stay in sync. Edit in whichever interface suits the moment without worrying about drift between the two.

  • TurboCI integration: Schedule changes are validated with column-level lineage diff before deployment, so you can see the blast radius of your changes directly within pull requests. This means you catch downstream impacts before they reach production.

  • dbt Cloud™ importer: Migrate existing dbt Cloud™ jobs to Paradime in minutes with a one-click importer. Zero downtime, no manual YAML authoring required.

  • Dependent schedules: Orchestrate sequential workflows with "On Run Completion" triggers—start downstream jobs only after upstream jobs complete successfully, even across different Paradime workspaces.

  • Native integrations: Built-in connections to Slack, Microsoft Teams, JIRA, Linear, PagerDuty, DataDog, New Relic, Incident.io, Elementary, and LightDash. Trigger actions, create tickets, and send granular alerts without building custom webhooks.

  • 99.9% uptime: Production-grade reliability with over 96 million uptime minutes tracked in the last 90 days.

Start for free at Paradime →

FAQs About dbt Schedules as Code

Can I use schedules as code with dbt Core without dbt Cloud?

Yes. Platforms like Paradime Bolt let you manage YAML-based schedules for dbt Core™ projects without requiring dbt Cloud™. You define your schedules in paradime_schedules.yml, commit them to your Git repository, and Bolt handles orchestration, monitoring, and alerting. The open-source dbt-jobs-as-code CLI is specifically designed for dbt Cloud™ jobs, but the concept applies broadly to any orchestration platform that supports YAML-based configuration.

How do I handle schedule dependencies across multiple dbt projects?

Use dependent schedules or triggers that start downstream jobs only after upstream jobs complete successfully. In Paradime Bolt, the "On Run Completion" trigger type lets you chain schedules across different workspaces—you select the parent schedule, the triggering workspace, and whether to trigger on success, failure, or both. This enables cross-project and cross-domain orchestration without building custom logic.

What happens if my YAML schedule file has a syntax error?

If you run validation before deployment (paradime schedule verify or dbt-jobs-as-code validate), syntax errors are caught and reported before any changes are applied. If validation is skipped and you attempt a sync, the sync command will fail, and the existing schedule remains unchanged. This is a key safety feature—a malformed YAML file cannot silently break your production schedules.

Can I run YAML-defined schedules alongside UI-defined schedules?

Most platforms support both approaches simultaneously. dbt-jobs-as-code differentiates code-managed jobs from UI-managed jobs by appending [[identifier]] to job names, ensuring they don't interfere with each other. Paradime Bolt keeps YAML and UI definitions in sync. However, mixing approaches long-term can cause configuration drift—best practice is to choose one source of truth and commit to it.

How do I roll back a schedule change deployed from YAML?

Revert the Git commit containing the schedule change and re-run the sync command. Because your schedules are version-controlled, rolling back is as simple as:

Your schedule returns to the exact previous state tracked in version control—no guessing, no manual UI clicks, no "what was the old cron expression?" conversations.

Interested to Learn More?
Try Out the Free 14-Days Trial

Stop Managing Pipelines. Start Shipping Them.

Join the teams that replaced manual dbt™ workflows with agentic AI. Free to start, no credit card required.

Stop Managing Pipelines. Start Shipping Them.

Join the teams that replaced manual dbt™ workflows with agentic AI. Free to start, no credit card required.

Stop Managing Pipelines. Start Shipping Them.

Join the teams that replaced manual dbt™ workflows with agentic AI. Free to start, no credit card required.

Copyright © 2026 Paradime Labs, Inc. Made with ❤️ in San Francisco ・ London

*dbt® and dbt Core® are federally registered trademarks of dbt Labs, Inc. in the United States and various jurisdictions around the world. Paradime is not a partner of dbt Labs. All rights therein are reserved to dbt Labs. Paradime is not a product or service of or endorsed by dbt Labs, Inc.

Copyright © 2026 Paradime Labs, Inc. Made with ❤️ in San Francisco ・ London

*dbt® and dbt Core® are federally registered trademarks of dbt Labs, Inc. in the United States and various jurisdictions around the world. Paradime is not a partner of dbt Labs. All rights therein are reserved to dbt Labs. Paradime is not a product or service of or endorsed by dbt Labs, Inc.

Copyright © 2026 Paradime Labs, Inc. Made with ❤️ in San Francisco ・ London

*dbt® and dbt Core® are federally registered trademarks of dbt Labs, Inc. in the United States and various jurisdictions around the world. Paradime is not a partner of dbt Labs. All rights therein are reserved to dbt Labs. Paradime is not a product or service of or endorsed by dbt Labs, Inc.