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.
- Navigate to your project in the dagctl web UI
- Click the Plans tab
- Click Create Plan
- Select the target environment (e.g.,
prod,dev) - Review the changed files and resolved scope in the diff view
- Approve the plan (or request approval from a team member for protected environments)
- 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
- Schedule recurring dbt commands — dbt Jobs
- Configure protected environments and approval policies — Environment Protection