The Build Checks the Shape. It Will Not Enforce the Promise.
dbt moved data contracts into the build step. It also lets you declare keys the warehouse never actually checks.
Since 2023, dbt has let teams attach a contract to a model so the pipeline fails when someone reshapes the data downstream consumers depend on. It is governance in CI/CD, which is real progress, right up until you read which guarantees are actually enforced.
dbt Core v1.5, released in 2023, introduced model governance: access controls, versions, and contracts. A model contract declares the expected columns and data types, and during the build dbt runs a preflight check; if the query returns the wrong shape, the model does not build. Later versions extended this to flag breaking changes, dropping a column (v1.5), modifying a constraint (v1.6), or deleting a contracted model (v1.9), so the failure shows up in CI rather than in a consumer's dashboard a week later.
This matters because it relocates governance from a quarterly review meeting to the moment a change is proposed. The check runs where the work happens, on the pull request, against prior project state. That is the entire promise of shift-left: catch the broken agreement before it ships, in front of the person who can still fix it cheaply. For column names and types, dbt delivers exactly that.
What it reveals is the gap between declaring a rule and enforcing one. dbt's own documentation states that primary_key, unique, and foreign_key constraints are, on most cloud warehouses, definable but not enforced; the warehouse accepts the declaration and never validates it. not_null is enforced; the relational guarantees most people assume are doing work are, in practice, decorative. The contract can assert uniqueness with full ceremony while duplicate rows arrive unbothered. The form is enforced. The promise is on the honor system.
Watch whether a team treats a green build as proof the data is correct or merely proof the columns are named right. The accountability question lands here: when a "unique" key turns out not to be, the contract passed, the pipeline was green, and no human was paged, because nothing technically broke. Verify which constraints your platform actually enforces, and put a name next to the ones it does not.
dbt enforces a model's shape at build time — real shift-left governance — but several constraints are definable, not enforced. Know which your warehouse actually checks and validate the decorative ones yourself; a green build is not a kept promise.
dbt Core v1.5 (2023) introduced model governance including contracts, access, and versions.
supports01dbt performs a build-time preflight check on contracted column names and types, failing the build on a mismatch, and detects breaking changes across later versions.
supports02On most cloud warehouses, primary_key, unique, and foreign_key constraints are definable but not enforced, while not_null is enforced.
supports03A passing contract build can coexist with violated relational guarantees because those constraints are not enforced by the platform.
No notes yet. The margin is open.
Sign in to add a note. The margin is moderated — we keep it useful, not cruel.
An engineering convenience became a control point. A control point needs a controller.
Owner MissingA compatibility check can block a breaking change. It can't name who's allowed to make one.
Definition DriftA real standard for data contracts now exists. The argument it was supposed to settle has simply moved up a layer.