04
Intermediate  ·  Module 04 of 14

Link Design
Deep Dive

Links capture the relationships between your business entities. They are infinitely flexible — a relationship between 2 or 20 hubs loads the same way, and adding a new relationship never breaks existing loads.

6 ConceptsCore topics
~45 minReading time
IntermediateLevel
Modules 01–03Prerequisites
Module Progress 0%

Concept 02

Many-to-Many Relationships

🧠 ELI5

Links naturally express many-to-many relationships, which are the bane of traditional dimensional modeling (you'd need a bridge table). In Data Vault, many-to-many is the DEFAULT. A customer can have many orders. An order can have many products. These are just Links with multiple Hub foreign keys — no special workaround required.

Common Many-to-Many Link Patterns

Each example below captures a different business relationship. The structural pattern is identical — only the participating hubs change:

Link Name Participating Hubs Business Meaning Grain
LINK_CUSTOMER_ORDER HUB_CUSTOMER, HUB_ORDER A customer placed an order One row per unique (Customer, Order) pair
LINK_ORDER_PRODUCT HUB_ORDER, HUB_PRODUCT An order contained a product One row per unique (Order, Product) pair
LINK_EMPLOYEE_DEPARTMENT_ROLE HUB_EMPLOYEE, HUB_DEPARTMENT, HUB_ROLE Employee holds a role in a department (3-way) One row per unique (Employee, Department, Role) combination

Full Load Pattern for LINK_CUSTOMER_ORDER

The load is always idempotent: the NOT EXISTS guard means running the same load twice produces the same result. Hub hash keys are pre-computed in the staging layer before this query runs.

SQL — Load LINK_CUSTOMER_ORDER from staging
INSERT INTO LINK_CUSTOMER_ORDER (
    LINK_CUSTOMER_ORDER_HK,
    HUB_CUSTOMER_HK,
    HUB_ORDER_HK,
    LOAD_DATE,
    RECORD_SOURCE
)
SELECT
    MD5(
        COALESCE(UPPER(TRIM(stg.CUSTOMER_BK)), '-1') || '||' ||
        COALESCE(UPPER(TRIM(stg.ORDER_BK)),    '-1')
    )                           AS LINK_CUSTOMER_ORDER_HK,
    stg.HUB_CUSTOMER_HK,        -- pre-computed in staging
    stg.HUB_ORDER_HK,           -- pre-computed in staging
    stg.LOAD_DATE,
    stg.RECORD_SOURCE
FROM STG_ORDERS stg
WHERE NOT EXISTS (
    SELECT 1 FROM LINK_CUSTOMER_ORDER lnk
    WHERE lnk.LINK_CUSTOMER_ORDER_HK = MD5(
        COALESCE(UPPER(TRIM(stg.CUSTOMER_BK)), '-1') || '||' ||
        COALESCE(UPPER(TRIM(stg.ORDER_BK)),    '-1')
    )
);

Hash key concatenation order must be fixed and documented. Always define the canonical key order (e.g., alphabetical by BK name) in your data model registry. Changing the order generates different hash values and breaks your link. Use '||' (double pipe) as the separator to avoid false collisions.

Why Many-to-Many is the Default in Data Vault

In Kimball dimensional modeling, a many-to-many fact relationship requires a bridge table — an extra object that must be designed, built, and maintained separately from the dimension model. In Data Vault, every Link is structurally many-to-many by default. There is no bridge concept needed at the Raw Vault layer:

  • Multiple customers can reference the same order (shared billing scenarios) without any schema change.
  • An order can appear in multiple links (LINK_CUSTOMER_ORDER and LINK_ORDER_PRODUCT) independently.
  • Adding a new source that sends additional (Customer, Order) pairs simply inserts new rows — it never restructures the table.

Concept 06

Interview Q&A — Links

What is the grain of a Link and why does it matter? ▶

The grain of a Link is the unique combination of all participating Hub hash keys. One row = one unique combination of those keys. This matters for two critical reasons:

1. Idempotency: Because the grain is hashed and enforced via a NOT EXISTS filter (or MERGE), loading the same relationship from multiple source systems is idempotent — the same hash key is generated regardless of which system sent it, so duplicate rows are never inserted.

2. Scope of the relationship: The grain determines what the link can represent. A Link for “Customer placed Order” records one row per unique (CustomerID, OrderID) pair. If you need one row per order line item, you need a different link with a different grain — perhaps including a LineItemID in the hash. Mixing grains in one link is a fatal design error.

Can a Link contain more than two Hubs? Give an example. ▶

Yes — there is no upper limit. Three-way and four-way links are common in enterprise implementations. The structure is identical to a two-way link: just add additional Hub FK columns and include each additional BK in the concatenated hash.

Example — LINK_TRADE_EXECUTION in financial services:

This link might reference four hubs: HUB_TRADER (who traded), HUB_INSTRUMENT (what was traded), HUB_COUNTERPARTY (with whom), and HUB_VENUE (where it was traded). The link hash key is computed as:

MD5(TRADER_BK || '||' || INSTRUMENT_BK || '||' || COUNTERPARTY_BK || '||' || VENUE_BK)

The grain: one row per unique (Trader, Instrument, Counterparty, Venue) combination. Each of the four Hub FKs is populated with a pre-computed hash from staging. The load pattern is identical to any two-way link.

What is an Effectivity Satellite and how does it relate to a Link? ▶

The split of concern: A Link records that a relationship ever existed. An Effectivity Satellite (EFF SAT) on that link records when the relationship was active.

The EFF SAT has two key business dates: an open date (when the relationship started) and a close date (when it ended — NULL means still active). These are business dates, not load dates.

Example: LINK_EMPLOYEE_DEPARTMENT records that employee E1 ever worked in department D1. SAT_EFF_EMPLOYEE_DEPARTMENT records that this relationship was active from 2020-01-15 to 2022-06-30 (when they transferred).

Without the EFF SAT, you can only answer: “Did they ever work there?” With it, you can answer: “Were they working there on a specific date?” — which is what most business queries actually need.

How does a Non-Historized Link differ from a regular link? ▶

Regular links record relationships that can change over time (a customer can switch account managers). They typically receive an Effectivity Satellite to track when the relationship was active and when it closed.

Non-historized transaction links record transactional events that, once they happen, are permanently true (a customer made a purchase, a transaction was executed). Key differences:

1. No Effectivity Satellite: The transaction happened, it is done. There is no “open/close window” to track.

2. Degenerate Dimensions in the link: Transaction-specific attributes like TRANSACTION_AMOUNT, TRANSACTION_DATE, or QUANTITY may be stored directly in the link itself because they will never change after the event. Regular links would place changing attributes in a satellite instead.

3. High volume loading: Transaction links are often loaded from high-volume event streams. Their design optimizes for insert throughput over query flexibility.

What is a Same-As Link and when would you use one? ▶

A Same-As Link (SAL) records that two different Hub business keys refer to the same real-world entity. Unlike a regular link between two different entities, a SAL points back to the same Hub twice — just like a hierarchical link, but with a semantically distinct purpose: declaring identity equivalence.

Use cases:

1. Master Data Management: Matching a customer in CRM (CRM-1001) to the same customer in ERP (ERP-XYZ-99). The SAL states: “these two business keys are the same person.”

2. Post-acquisition consolidation: A company is acquired and their customer IDs need to be reconciled with your existing IDs. The SAL bridges old and new without deleting either.

3. Duplicate detection: Analytics discovers that two customer records are the same person. A SAL declares the equivalence. The Business Vault then uses the SAL to build a unified “golden record” view while the Raw Vault preserves both original keys with full, independent history.

The matching confidence and method are stored in a dedicated satellite on the SAL (SAT_SAL_{ENTITY}) — not in the SAL table itself, which remains a structural metadata object.

✅ Module 04 Key Takeaways

  • A Link records that a relationship exists between two or more business entities. It contains no descriptive data — only hub FKs, a composite hash key, load date, and record source.
  • The grain of a Link is the unique combination of all participating business keys. One wrong grain decision poisons the entire downstream query layer — always define grain before writing DDL.
  • Hierarchical (self-referencing) links point back to the same Hub twice. Use role-qualified column prefixes (e.g., MANAGER_, EMPLOYEE_) to make both FKs unambiguous and auditable.
  • Non-historized (transaction) links capture permanently-true events. They may include Degenerate Dimensions (amounts, dates) directly in the link and typically do not receive Effectivity Satellites.
  • Same-As Links (SALs) are the foundation of MDM in Data Vault. They declare identity equivalence between two business keys without destroying either key’s independent history in the Raw Vault.