Skip to main content
Snapshot models maintain historical row versions with validity windows. They answer questions like: what does this entity look like now, what did it look like before, when did it change, and was it absent during a period.

How snapshots work

SQLBuild adds two generated columns to the target table: A point-in-time query uses the interval valid_from <= point_in_time < valid_to.

Change detection strategies

Timestamp strategy

Use when your source has a reliable column recording when the entity changed.
If the source updated_at is newer than the active target row’s updated_at, SQLBuild closes the old version and inserts the new one. If updated_at is unchanged or older, nothing happens.

Check strategy

Use when the source does not have a reliable update timestamp.
SQLBuild compares check_columns between source and active target rows. If any checked value differs, a new version is created. Changes to unchecked columns are ignored. check_columns [*] checks all output columns except unique_key and the generated validity columns. Explicit columns are recommended for important models to avoid noisy history from volatile metadata columns.

Historical input

By default, SQLBuild treats the model query as returning the current state of each entity (one row per unique_key). When your source contains historical observations over time, add observed_at to switch to historical mode.

Historical check snapshot

Use for daily full exports or periodic snapshots without a business update timestamp.
Each observed_at group is treated as a complete picture of the source at that time. Consecutive unchanged observations are collapsed into a single version.

Historical timestamp snapshot

Use for historical observations that include a business update timestamp.
Each row means: “at extract_date, the source’s current state for this key had this updated_at.” Validity windows use updated_at, not observed_at.

Historical change records

Use for CDC tables, audit logs, or historical backfills where rows are individual version records.
Multiple changes for the same key in one batch are allowed. updated_at determines version ordering. observed_at is arrival/load time, not validity time.

Historical input rules

Timestamp snapshots with observed_at require historical_input to be set explicitly.

Hard deletes

When enabled, active target rows whose keys are missing from the source are closed:
  • Current-state input: closed at execution time
  • Historical input (historical_input snapshot): closed at the observed_at time of the group where the key is missing
Hard deletes are not allowed with historical_input changes because change-record batches are not complete source snapshots - a missing key just means no change, not deletion. Reappearing keys create a new active version.

Configuration reference

Initial valid_from defaults

Full refresh safety

Snapshot full refresh can permanently discard history that cannot be reconstructed from the source. SQLBuild guards against this with configurable safety policies.

Project config

Defaults

Model override

The model snapshot_full_refresh field can only make the policy stricter than the project setting. A model cannot weaken deny to allow.

CLI usage

Audits

Snapshot models support the same audit system as other materializations. Audits with delta_and_final run scope execute against the snapshot delta relation before target mutation, blocking promotion if an error-severity audit fails. Final audits run after target mutation.

Duplicate handling

SQLBuild fails with an actionable error if the source query produces duplicate rows at the snapshot identity grain:
  • Current-state: duplicate unique_key
  • Historical snapshot: duplicate unique_key + observed_at
  • Historical changes: duplicate unique_key + updated_at
Deduplicate in your model SQL:

Querying snapshots

Current rows

Point-in-time

Fact-to-dimension historical join

Examples

Composite key

Custom validity column names