skip to content

What problem do point-in-time and bridge tables solve in a Data Vault?

level: seniorimportance: nice to knowfreq 26%

answer

  1. Insert-only history makes as-of reads expensive
  2. How many satellites does one question usually touch?
  3. One row per key per snapshot date
  4. What lets an equality join replace a ranking?
  5. Delete them and you lose only speed

basics

~20 s

They make vault queries affordable. A point-in-time table pre-resolves which satellite version was in effect per key per snapshot date, and a bridge table pre-resolves multi-hop key paths, turning correlated lookups into plain equality joins.

solid answer

~50 s

Querying a raw vault directly is expensive because history is insert-only: for every satellite you must find the row with the greatest load date at or before the date you care about, per key. Do that across five satellites and you have five correlated subqueries in one statement. A **point-in-time (PIT) table** precomputes the answer: one row per business key per snapshot date, holding the parent hash key and the exact `load_date` of each satellite in force on that date. The query then joins each satellite on `(hash key, load_date)` — an equality join, no ranking, no windowing. A **bridge table** does the equivalent for structure rather than history: it precomputes key combinations across a chain of hubs and links, so a query spanning customer to order to product does not traverse several link hops. Both live in the business vault, hold no information the vault does not already have, and can be dropped and rebuilt at will.

code

sql · 18 lines
sql
CREATE TABLE pit_customer (
  customer_hk           CHAR(32)  NOT NULL,
  snapshot_date         DATE      NOT NULL,
  sat_crm_load_date     TIMESTAMP NOT NULL,
  sat_billing_load_date TIMESTAMP NOT NULL,
  PRIMARY KEY (customer_hk, snapshot_date)
);

-- Equality joins only: no per-satellite ranking at query time
SELECT p.snapshot_date, c.name, c.tier, b.credit_limit
FROM pit_customer p
JOIN sat_customer_crm c
  ON c.customer_hk = p.customer_hk
 AND c.load_date   = p.sat_crm_load_date
JOIN sat_customer_billing b
  ON b.customer_hk = p.customer_hk
 AND b.load_date   = p.sat_billing_load_date
WHERE p.snapshot_date = DATE '2026-06-30';

go deeper

for a junior

Rarely asked at this stage. Recall that both are helper tables built to speed up querying a Data Vault, and that they contain nothing the vault does not already have.

for a middle

Be able to say what a point-in-time table's grain and columns are, and how joining on the load date it names replaces per-satellite ranking in the query.

for a senior

Expect to explain the ghost record and why an absent satellite version otherwise drops rows, and to argue for a snapshot grain given the key count and the as-of queries the marts actually run.

for a principal

Own the precomputation trade-off: these tables cost storage that scales with keys times snapshots plus a rebuild job that can fall behind, and they are shaped by consumption patterns that will change.

## Why raw vault queries hurt A Data Vault raw layer is optimized for loading and retention, not for reading, and two of its design choices work directly against the query planner. First, **history is insert-only**. A satellite holds every version ever seen, keyed by parent hash key plus load date, with no current flag and often no end date. Asking "what did this customer look like on 30 June" means finding, per key, the row with the greatest `load_date` at or before that instant. Second, **attributes are spread across many satellites** — one per source system, plus splits by volatility and sensitivity. A single business question routinely needs four or five of them, each requiring its own per-key latest-as-of resolution, and each versioned on its own independent schedule. The result is a query with several correlated subqueries or window functions, one per satellite, all of which the engine must evaluate before it can join anything. It is slow, and — more damagingly — it is easy to write subtly wrong, because every analyst re-derives the same as-of logic by hand. ## The point-in-time table A PIT table removes the per-satellite resolution from query time by doing it once, on a schedule. It holds one row per business key per snapshot date, and for each satellite of that key a column carrying the exact load date of the version in force on that date: ```sql CREATE TABLE pit_customer ( customer_hk CHAR(32) NOT NULL, snapshot_date DATE NOT NULL, sat_crm_load_date TIMESTAMP NOT NULL, sat_billing_load_date TIMESTAMP NOT NULL, PRIMARY KEY (customer_hk, snapshot_date) ); ``` Queries then join each satellite on both the hash key and the load date the PIT row names — a plain equality join on the satellite's own primary key. All the ranking is gone. The grain of the snapshot is a design decision. Daily is common; some vaults keep a dense daily grid, others store only the dates on which something changed, which is far smaller but requires an as-of lookup to find the right snapshot row. ## The ghost record A PIT table's real value is that its joins stay **inner equality joins**, and that breaks the moment a satellite has no row at or before the snapshot date — a customer known to the CRM but not yet to billing, for instance. The standard fix is a **ghost record**: one row per satellite with a sentinel hash key (conventionally all zeros), a minimum load date, and null attributes. The PIT row points at the ghost's load date when there is no real version, and the join succeeds with nulls instead of dropping the row. Without it, one absent satellite silently deletes the customer from the result. ## The bridge table A bridge table solves the structural analogue. Because a Data Vault expresses every relationship as a link, answering a question that spans customer to order to order line to product means traversing several link tables, each with its own hash keys. A bridge precomputes the key combinations across that chain — hub and link hash keys, often with a snapshot date so it also carries the as-of resolution — so the query joins one wide bridge to the satellites it needs instead of walking the graph. Bridges are commonly built for the exact navigation paths a set of marts uses, which is why they tend to be shaped by consumption rather than by the source model. ## Both are disposable The crucial property of both structures is that they contain **no information the vault does not already hold**. Every value in a PIT or bridge table was derived from hubs, links and satellites. Drop them all and nothing is lost except speed; rebuild them and you get identical content. That is why they belong to the business vault rather than the raw vault, why they are usually rebuilt rather than incrementally maintained, and why they are safe to reshape when consumption patterns change. It also means they carry the standard costs of any precomputation: storage that scales with keys times snapshots, a rebuild job that must run and can fall behind, and staleness between rebuilds. A dense daily PIT over a large hub is not free, and shops routinely limit the snapshot horizon or restrict PIT coverage to the entities marts actually query as-of. ## Where the boundary sits PIT and bridge tables are a query-assist layer, not a consumption layer. They make vault queries tractable for the jobs that build marts; they do not turn the vault into something analysts should query directly. The marts are still the thing BI tools read.

  • Why does a satellite need a ghost record for a point-in-time table to work well?
    Because a PIT join is an inner equality join on (hash key, load date). If a satellite has no version at or before the snapshot date there is nothing to join to, and the key vanishes from the result. A ghost row with a sentinel key, a minimum load date and null attributes keeps the join succeeding with nulls.
  • What happens if you drop every point-in-time and bridge table in the vault?
    Nothing is lost but performance. Both are derived entirely from hubs, links and satellites, so queries still return the same answers via per-satellite as-of resolution — just far more slowly, and with that logic re-implemented by every consumer. Rebuilding them restores identical content.
  • How do you choose the snapshot grain of a point-in-time table?
    By balancing query convenience against size. A dense daily grid makes an as-of read a single equality lookup but costs keys times days in rows. Storing only dates on which something actually changed is far smaller but forces a lookup for the latest snapshot at or before the requested date.

A point-in-time table is an index card that says, for a given date, exactly which page of each source's history to open — so you jump straight to the page instead of leafing through each book to find the last entry before that date.

saying these in an interview costs you the question

  • Says PIT tables store data not present in the satellites
  • Treats bridge tables as the consumption layer analysts query
  • Puts PIT and bridge tables in the raw vault
  • Forgets ghost records and silently drops keys from results
  • Assumes PIT tables must be incrementally maintained, never rebuilt

context