SCD Type-2 Timeline Explorer

A Type-2 slowly changing dimension keeps every historical version of a row so "what was true as of date X" is answerable — but only if every change is captured as a new row, never an in-place update.

Dimension: customer_123.plan

Record a change to this customer's plan. This appends a new row and closes out the previous one — it never overwrites history.

New value Effective date

Timeline

"As of" query

As-of date

Simulates: SELECT * FROM dim WHERE customer_id = 123 AND effective_from <= :as_of AND (effective_to > :as_of OR effective_to IS NULL)

Underlying table

customer_skplaneffective_fromeffective_tois_current

Why this matters

A Type-1 dimension overwrites the current value in place — asking it "what plan was this customer on when they placed order #4821 last March" returns whatever plan they're on today, because history was never kept. Type-2 keeps every version with an effective window, which is exactly what a fact table needs to join against for a historically correct answer. See Data Modelling, "Slowly changing dimensions."

The real failure mode: a query joins a fact table (orders) to a dimension using customer_id and grabs the current row — is_current = true — instead of the row that was current at order_created_at. If the customer has since upgraded from free to pro, every historical order silently gets rewritten as if they had always been on pro. The report is internally consistent and shows no error; it is just wrong, and nobody notices until a revenue-per-plan number stops reconciling with billing.