Skip to main content

Data Contracts and Lineage

A data contract records the interface between a producer and consumers: ownership, grain, keys, columns, types, semantics, quality objectives, freshness, compatibility, and change process. Lineage records dependencies and transformations. Neither replaces communication, runtime monitoring, or access control.

Prerequisites​

Complete dbt Data Tests and Schemas, Types, and Evolution.

Learning goals​

  • Separate schema enforcement from semantic and operational promises.
  • Add an enforced dbt model contract with typed columns.
  • Use lineage for impact analysis and incident investigation.
  • Classify additive, compatible, and breaking changes.

Worked example​

An enforced dbt contract checks model column names and data types before publication. Constraint enforcement varies by materialization and adapter, so data tests remain necessary.

version: 2
models:
- name: fct_events
description: One row per accepted event_id, amounts in integer minor units.
config:
materialized: table
contract:
enforced: true
columns:
- name: event_id
data_type: varchar
constraints:
- type: not_null
- type: primary_key
- name: amount_cents
data_type: integer
constraints:
- type: not_null

The dependency path raw.events → stg_events → fct_events → mart_daily_region supports table-level impact analysis. dbt's source() and ref() calls populate graph metadata and its manifest artifact. Column lineage depends on SQL parsing and feature/version support; it can omit uses in filters or joins and should not be described as complete provenance.

Adding a nullable currency column may be structurally compatible, yet semantically unsafe if consumers assume all amounts are USD. Renaming amount_cents, changing its unit, revising grain, or rewriting history is breaking. Use versioning or a migration window, identify consumers from both declared lineage and query evidence, and define rollback.

Limitations and common mistakes​

  • A schema registry cannot enforce metric definitions or lawful data use by itself.
  • Inferred lineage can miss dynamic SQL, external scripts, extracts, and manual exports.
  • Declared owners become stale without operational review.
  • “Backward compatible” depends on actual consumer behavior, not only nullable columns.
  • Contracts applied only at the final mart allow bad data to travel too far.

Practice​

Create a change proposal for adding currency. Include default behavior, historical backfill, affected models, consumer notice, validation, rollout, and rollback.

Next steps​

Continue with Warehouse Cost and Query Performance to connect model shape with measured work.

Primary sources​

Checked 2026-10-15: dbt model governance, model contracts, manifest artifact, and column-level lineage caveats.