Snapshots

Snapshots for Slowly Changing Dimensions

A snapshot implements SCD Type 2 (SCD Type 2) over a source that only holds current values. Each dbt 37,942 snapshot run compares the source with the snapshot table, closes changed rows and inserts new versions. Snapshots are configured in YAML:

snapshots/customers_snapshot.yml: Type 2 history of customersYAML
snapshots:
  - name: customers_snapshot
    relation: source('shop', 'customers')
    description: Type 2 history of customers' name and country.
    config:
      schema: snapshots
      unique_key: customer_id
      strategy: check
      check_cols: [name, country]
      dbt_valid_to_current: "cast('9999-12-31' as date)"

The check strategy compares the listed columns; timestamp trusts an updated_at column instead. dbt_valid_to_current puts 9999-12-31 in the open row instead of NULL, as SCD Type 2 recommended. Customer 1 moves to the UK in the shop database:

A source change, then a snapshot runShell
docker exec l2-pg psql -U postgres -d booknest \
  -c "UPDATE customers SET country = 'GB' WHERE customer_id = 1"
dbt snapshot
Output
17:23:57  1 of 1 OK snapshotted analytics_snapshots.customers_snapshot  [INSERT 0 1 in 1.39s]
 customer_id | country |       dbt_valid_from       |        dbt_valid_to
-------------+---------+----------------------------+----------------------------
           1 | AU      | 2026-10-01 17:22:34.540103 | 2026-10-01 17:23:56.246123
           1 | GB      | 2026-10-01 17:23:56.246123 | 9999-12-31 00:00:00

The history comes from querying the snapshot table. A snapshot cannot know the past: the first version's dbt_valid_from is the first run's time, and a change between runs is dated at the next run. Run snapshots often, and backfill the first start date as Implementing SCD Type 2 did if older facts must join them.