Skip to content

dbt Plans

Quick Summary

dbt plans deploy project changes by building a new container image from your current commit and executing dbt commands against it. A plan gives you visibility into what changed before anything runs, and supports an approval workflow for protected environments.

Key Takeaways

  • Plans are triggered by a version bump in .dagctl/config.yaml — this is the only signal dagctl uses to detect a new deployment is needed
  • The build phase runs Kaniko to produce a new container image — build logs are visible in the web UI
  • Scope is determined automatically from the git diff — changed model files trigger selective runs, changed macros or configs trigger a full build
  • Plans can be retried up to 3 times if they fail
  • Protected environments require explicit approval before any build or run happens

How dbt Plans Differ from SQLMesh Plans

Dimension dbt Plans SQLMesh Plans
Change detection Version field in .dagctl/config.yaml State-based diff against SQLMesh state database
Build phase Kaniko builds a new container image No image build — uses existing image
Scope git diff between last deployed commit and HEAD Model change type (added, modified, removed)
Execution dbt build with optional --select sqlmesh plan --auto-apply

Plan Phases

Phase 1 — Explain

dagctl detects that the version in .dagctl/config.yaml has changed since the last deployed plan. It runs a git diff between the last deployed commit and HEAD to identify what changed. Changed files are categorized:

  • Models (models/**/*.sql)
  • Tests (tests/**/*.sql, models/**/*.yml)
  • Macros (macros/**/*.sql)
  • Seeds (seeds/**/*.csv)
  • Configuration (dbt_project.yml, profiles.yml, packages.yml)

If model files changed, dagctl builds a --select expression covering only those models. The full list of changed files and the resolved scope are shown in the web UI before you approve anything.

Phase 2 — Approve

The plan sits in pending status until a team member reviews and approves it. For unprotected environments, you can approve your own plan. For protected environments (e.g., prod), another team member with the required role must approve.

See Environment Protection for role requirements.

Phase 3 — Build

After approval, dagctl submits a Kaniko job in your organization's namespace to build a new container image from the current commit. Build logs stream in real time to the web UI.

Warning

The build uses the exact commit that was diffed in Phase 1. If you push new commits after creating the plan, those commits are not included until you create a new plan.

Phase 4 — Run

Once the image is built, dagctl executes dbt against the new image. The command and scope depend on what changed:

Scope When What runs
selective Model files changed dbt build --select <changed_models>
all Non-model files changed (macros, configs, tests) dbt build (full run)
build_only No model changes Image is rebuilt, no dbt commands execute

The build_only scope is common when you're updating Python dependencies, changing dbt version, or making infrastructure-only changes that don't affect model SQL.

Creating a Plan

Before creating a plan, make sure you have incremented the version field in .dagctl/config.yaml and pushed the change to your branch.

  1. Navigate to your project in the dagctl web UI
  2. Click the Plans tab
  3. Click Create Plan
  4. Select the target environment (e.g., prod, dev)
  5. Review the changed files and resolved scope in the diff view
  6. Approve the plan (or request approval from a team member for protected environments)
  7. Monitor the build and run phases in real time

Approval Workflow

Protected environments use an allowlist model. Only users explicitly added to the exception list for a protected environment can execute plans targeting it. Unprotected environments allow any project member to approve and execute.

See Environment Protection for configuration details.

Retries

If a plan fails during the build or run phase, you can retry it from the Plans tab. Plans support up to 3 retry attempts. Each retry re-uses the same commit and scope — it does not re-run the diff. If the underlying issue requires a code change, create a new plan instead.

Next Steps