System Design · medium
Asked in Analytics Engineer interviews, in the System Design round.
One row per version of the entity with valid_from / valid_to and a current flag, and a surrogate key per version so facts join to the state as of the event. Test that exactly one version is current per natural key, that the validity windows never overlap, and that valid_from < valid_to — dbt unique/not_null plus a custom overlap test.
One row per version of the entity, each with a validity window, a current flag, and its own surrogate key so facts can join to the version that was true when the fact happened.
CREATE TABLE dim_customer (
customer_key BIGINT PRIMARY KEY, -- surrogate, one per version
customer_id TEXT NOT NULL, -- natural key, repeats across versions
segment TEXT,
region TEXT,
valid_from TIMESTAMP NOT NULL,
valid_to TIMESTAMP NOT NULL, -- '9999-12-31' for the current version
is_current BOOLEAN NOT NULL
);
On a change: close the current version by setting valid_to to the change time and is_current to false, and insert a new version starting at that time. In dbt this is a snapshot with strategy='check' on the tracked columns, or timestamp if the source carries an updated_at.
Facts store the surrogate key resolved at load time with a range join on the event timestamp, so an order joins to the segment current when it was placed.
The tests are what make it trustworthy, because a subtle bug produces plausible numbers:
valid_from < valid_to on every row.The one-current test and the overlap test are custom SQL in dbt; the rest are built-ins. Run them on every build; an SCD that silently grew two current versions doubles every metric joined through it.