Designing production deploys assuming success will burn you. dbt is declarative and reproducible, but for schema changes, incremental processing, and marts with many downstream dependents, you need a deliberate release strategy and an immediate rollback mechanism.
This article extracts only the stable practices common to both dbt Cloud and dbt Core, covering both the angles tested on the dbt Analytics Engineer exam and the procedures that actually help in production.
Stable production operations are built on environment separation (dev/staging/prod), Blue/Green schema swaps, and differential runs using dbt state (previous artifacts). Validate against staging at the PR stage, confirm the migration is safe, then update the production Green side and control exposure via swap or cutover.
In dbt, the typical pattern is to split schemas by target.name, materialize marts as tables, and staging as views. CI validates only the diff via state:modified+, and production is rolled out incrementally rather than all at once.
End-to-end pipeline (Blue/Green and state usage)
dbt_project.yml: separate schemas per environment (the foundation of Blue/Green)
name: analytics
config-version: 2
profile: analytics
models:
+schema: "analytics_{{ target.name }}"
staging:
+materialized: view
+tags: ["staging"]
marts:
+materialized: table
+tags: ["marts"]
# Example: prepare two targets prod_blue / prod_green in profiles.yml and control exposure via switchingSlim CI based on state files (the previous manifest) is the standard approach for PR validation. --select state:modified+ targets only changed nodes and their downstream, while --defer delegates unchanged upstream to production artifacts. This shortens CI time while accurately capturing the real impact of the change.
After merge, the release job applies the change to the Green environment. Once all quality gates (tests, freshness, contracts) pass, swap via alias (view) or name swap.
Slim CI example with dbt Core + GitHub Actions
name: dbt-ci
on:
pull_request:
branches: [ main ]
jobs:
slim-ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dbt (Snowflake example)
run: |
pip install dbt-core dbt-snowflake
- name: Restore prod artifacts (previous manifest)
uses: actions/download-artifact@v4
with:
name: prod_artifacts
path: ./prod_state
- name: Dependencies
run: dbt deps
- name: Slim CI build
run: |
dbt build \
--profiles-dir . \
--target staging \
--select state:modified+ \
--defer \
--state ./prod_state \
--fail-fastProduction incidents are usually caused by irreversible schema changes. Avoid dropping columns, narrowing types, or changing semantics. Use staged migration (add → run in parallel → switch → drop). In dbt, run a v2 model alongside the current one and control exposure via views or aliases.
For incremental models, use on_schema_change with compatibility-preserving settings (such as append_new_columns). On supported adapters, enable model contracts (contract enforce) to catch type or column drift early.
models/fct_orders_v2.sql (safe v2 migration with a contract example)
{{ config(
materialized='incremental',
on_schema_change='append_new_columns',
tags=['marts','v2'],
contract={'enforce': true}
) }}
select
order_id::integer as order_id,
customer_id,
order_ts,
-- New columns are added as nullable to preserve backward compatibility
cast(null as string) as order_channel
from {{ ref('stg_orders') }}
-- In schema.yml, declare types and required columns explicitly, and add not_null/unique/relationships testsChoose a rollback strategy by balancing cutover speed, data integrity, and dependency impact. Consider in order: Blue/Green alias cutover; database clone or time travel (Snowflake Time Travel/Zero-copy Clone, Delta Lake Time Travel/RESTORE, etc.); and finally, as a last resort, revert to the previous green commit and rebuild.
Table swaps cut over in seconds but require having the target tables pre-built in parallel. Clone/time travel is storage-efficient and fast but depends on engine features. A dbt rebuild is engine-agnostic and reliable but RTO is longer.
| Strategy | Overview | Approx. RTO | Prerequisites / Support |
|---|---|---|---|
| Blue/Green + swap | Build in parallel on Green, swap view/table names instantly | Seconds to tens of seconds | All engines (use views or separate schemas as fallback). Snowflake supports table SWAP. |
| Clone / time travel | Instant restore to a point in time (Snowflake Time Travel/Zero-copy Clone, Delta Time Travel/RESTORE, etc.) | Seconds to a few minutes | Requires supported engine features |
| Previous-green rebuild | Checkout the last successful commit and re-run dbt build | Minutes to tens of minutes | Engine-agnostic |
Representative rollback procedure (example)
# 1) Blue/Green: rename swap on Snowflake (requires review and privileges)
-- Assumes parallel build already completed on the BLUE side
ALTER TABLE analytics_prod.orders SWAP WITH analytics_green.orders;
# 2) Delta Lake (Databricks etc.): point-in-time restore (syntax/availability varies by environment)
-- Example: RESTORE TABLE catalog.schema.orders TO VERSION AS OF 123;
# 3) dbt: revert to the previous green commit and rebuild
LAST_GREEN_SHA="<saved release SHA>"
git checkout "$LAST_GREEN_SHA"
dbt deps
# Select only impacted models while delegating production references to existing artifacts
# (use --defer/--state to filter as needed)
dbt build --target prod --fail-fastdbt generic/custom tests, source freshness, and model contracts are powerful pre-production gates. Design so anything that can be caught at PR time is caught, and run a full test suite again when applying to Green after merge.
After cutover, periodically run assertion models for monitoring (row-count delta, distribution drift, etc.) and surface issues via job alerts. Combine dbt Cloud job notifications with each engine's audit logs to detect issues faster in practice.
schema.yml tests and freshness example
version: 2
models:
- name: fct_orders_v2
tests:
- not_null:
column_name: order_id
- unique:
column_name: order_id
- relationships:
to: ref('dim_customers')
field: customer_id
sources:
- name: app
freshness:
warn_after: {count: 24, period: hour}
error_after: {count: 48, period: hour}
tables:
- name: orders_rawDuring an incident, a Runbook you can execute without hesitation is everything. Decide in advance which strategy to use under which conditions, and prepare commands ready to copy-paste. Set RTO/RPO targets and share Blue/Green cutover permissions, schema naming conventions, and artifact storage locations.
On the exam, frequent topics include: environment separation, diff runs with state, the backward-compatibility principle, and being able to choose between Blue/Green and clone/time travel based on their characteristics.
Runbook fragment (sample shell procedure)
# Identify impact scope
FAILED_MODEL="{{ this }}"
# 1) Immediately pause production jobs (varies by tool)
# 2) Blue/Green swap or clone-based recovery
# e.g., apply Snowflake swap / Delta RESTORE
# 3) If reverting to the last green
LAST_GREEN_SHA=$(cat last_green.sha)
git checkout "$LAST_GREEN_SHA" && dbt deps && dbt build --target prod --fail-fast
# 4) Run smoke tests, resume jobs, intensify monitoringAnalytics Engineer
問題 1
After applying a mart to production with dbt on Snowflake, some KPIs are off. You want to roll back with the shortest possible downtime. Which response is most appropriate?
正解: A
The shortest, lowest-risk recovery is to switch exposure instantly using a Blue/Green setup that was pre-built in parallel. On Snowflake, with the right privileges, ALTER TABLE ... SWAP WITH lets you swap table names instantly. B takes too long, C makes irreversible changes and is risky, and D ignores quality gates and is inappropriate.
When should I use dbt --defer?
Use it when validating a PR against staging in CI, so unchanged upstream nodes are delegated to production artifacts. Combined with --select state:modified+, you build only the diff and get both speed and reliability.
Is it safe to enable model contracts (contract enforce) in production?
On supported adapters, we recommend enabling them. They catch type or column drift early and prevent dangerous deployments. To roll out safely, first run them as warnings in CI, confirm there are no unexpected failures, then switch to enforcement in production.
How should I think about rollback for incremental models?
For short-term rollback, swapping the incremental target via Blue/Green is the fastest path. If engine features are available, clone or time travel (Snowflake Time Travel, Delta Time Travel/RESTORE, etc.) can restore a specific version. As a last resort, checkout the previous green commit and re-run dbt build.
Practice with certification-focused question sets
無料で問題を解いてみるNicheeLab Editorial Team
NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.
dbt Models: SQL-Defined Transformation Units (2026)
Model fundamentals — SELECT-based definitions, naming, refs,...
dbt Analytics Engineering Exam: Complete Guide (2026)
Pass the AE Certification — scope, weighting, sample questio...
dbt Cloud vs dbt Core: Feature & Cost Comparison (2026)
Honest comparison of dbt Cloud vs. dbt Core — IDE, scheduler...
dbt Project Structure: models/seeds/macros Layout (2026)
Recommended dbt project layout — models, seeds, macros, snap...
dbt_project.yml Explained: Every Config (2026)
Every dbt_project.yml setting that matters — paths, vars, ma...