Model Versioning¶
Model versioning allows you to make breaking changes to a model's interface without immediately breaking downstream consumers. Both the old and new versions coexist in the warehouse until the old one is deprecated.
The Problem¶
Renaming a column in orders breaks every model that references it. Without versioning, you must:
1. Rename the column in orders
2. Update every downstream model in the same PR
3. Hope nothing breaks in production
With versioning, you introduce orders v2 alongside v1. Downstream teams migrate at their own pace.
Declare a Versioned Model¶
Create a new file models/orders_v2.sql:
-- version: 2
-- defined_in: orders
-- materialized: table
-- contract: true
SELECT
id AS order_id, -- renamed from "id"
customer_id,
total_cents / 100.0 AS amount, -- type changed from integer cents to decimal
order_status AS status, -- renamed from "order_status"
placed_at AS created_at -- renamed from "placed_at"
FROM raw_orders
The original models/orders.sql becomes v1 implicitly (or you can add -- version: 1).
Physical Table Names¶
| Model file | version |
Physical table |
|---|---|---|
orders.sql |
(none) | orders (latest alias) |
orders_v2.sql |
2 |
orders_v2 |
orders_v1.sql |
1 |
orders_v1 |
The orders table is automatically aliased to the latest version's table (v2 in this case) so existing ref('orders') calls continue to work.
ref() with Version¶
-- Resolves to the LATEST version (v2)
SELECT * FROM ref('orders')
-- Resolves to v1 specifically
SELECT * FROM ref('orders', version=1)
-- Resolves to v2 specifically
SELECT * FROM ref('orders', version=2)
Deprecation Workflow¶
- Introduce v2 — create
orders_v2.sql, add contract - Announce — notify downstream teams of the migration
- Migrate downstream — teams update
ref('orders')calls or useref('orders', version=2) - Deprecate v1 — add
-- enabled: falsetoorders_v1.sqlafter all consumers migrate - Delete v1 — remove the file after the deprecation period
schema.yml for Versioned Models¶
models:
- name: orders_v2
description: "Orders v2 — renamed columns for clarity"
config:
version: 2
defined_in: orders
latest_version: 2
materialized: table
columns:
- name: order_id
data_type: INTEGER
- name: amount
data_type: DOUBLE