EntityModel.comDocs
Contents

Start here

Guides

Examples

Platforms

Compare

Reference

Learn

Data Vault 2.0 example

Data Vault is a modeling method for the integration layer of a data warehouse. It separates business keys (hubs), relationships (links) and descriptive attributes over time (satellites), so new sources and changes are added without reworking what's there. This example is a small raw vault for customers, products and orders.

Design notes

  • Hubs hold business keys only. hub_customer has one row per customer ID ever seen, with its hash key, first load time and source. Hubs are insert-only.
  • Links hold relationships. link_order_customer and link_order_product connect hubs through their hash keys. Every relationship is a link, even one-to-many ones, so cardinality changes in the source don't change the model.
  • Satellites hold history. Each satellite is keyed by its parent's hash key plus load_dts, and gets a new row only when hash_diff (a hash of its descriptive columns) changes.
  • Satellites can hang off links. sat_order_product holds the quantity and price of each order line.
  • Every row records where and when it came from (record_source, load_dts), which makes the vault auditable.
  • Hash keys (*_hk) are computed from the business keys, so loads can run in parallel without lookups.

Business-facing star schemas or views are built on top of the vault; see the star schema example.

Diagram

Data Vault 2.0 (Orders): 9 entities, 0 reference lists and 8 relationships. Each box is an entity with its attributes (PK marks the primary key); solid lines are relationships in crow's foot notation, dashed lines point to reference lists.

Link Order Customer Links Hub Order (N:1)LinksLink Order Customer Links Hub Customer (N:1)LinksLink Order Product Links Hub Order (N:1)LinksLink Order Product Links Hub Product (N:1)LinksSat Customer Details Describes Hub Customer (N:1)DescribesSat Product Details Describes Hub Product (N:1)DescribesSat Order Details Describes Hub Order (N:1)DescribesSat Order Product Describes Link Order Product (N:1)DescribesHub Customer: One row per customer business key, ever. Never updated.Hub Customerhub_customerPKcustomer_hkSTRINGcustomer_bkSTRINGload_dtsTIMESTAMPrecord_sourceSTRINGHub Product: One row per product business key (SKU).Hub Producthub_productPKproduct_hkSTRINGproduct_bkSTRINGload_dtsTIMESTAMPrecord_sourceSTRINGHub Order: One row per order business key.Hub Orderhub_orderPKorder_hkSTRINGorder_bkSTRINGload_dtsTIMESTAMPrecord_sourceSTRINGLink Order Customer: Relates an order to the customer who placed it.Link Order Customerlink_order_customerPKorder_customer_hkSTRINGorder_hkSTRINGcustomer_hkSTRINGload_dtsTIMESTAMPrecord_sourceSTRINGLink Order Product: Relates an order to each product on it (the order line).Link Order Productlink_order_productPKorder_product_hkSTRINGorder_hkSTRINGproduct_hkSTRINGline_numberINTload_dtsTIMESTAMPrecord_sourceSTRINGSat Customer Details: Customer attributes over time. A new row only when the hash diff changes.Sat Customer Detailssat_customer_detailsPKcustomer_hkSTRINGPKload_dtsTIMESTAMPhash_diffSTRINGcustomer_nameSTRINGemailSTRINGsegmentSTRINGrecord_sourceSTRINGSat Product Details: Product attributes over time.Sat Product Detailssat_product_detailsPKproduct_hkSTRINGPKload_dtsTIMESTAMPhash_diffSTRINGproduct_nameSTRINGcategorySTRINGlist_priceDECIMALrecord_sourceSTRINGSat Order Details: Order header attributes over time, such as status changes.Sat Order Detailssat_order_detailsPKorder_hkSTRINGPKload_dtsTIMESTAMPhash_diffSTRINGorder_statusSTRINGordered_atTIMESTAMPtotal_amountDECIMALrecord_sourceSTRINGSat Order Product: Attributes of an order line (on the link): quantity and price.Sat Order Productsat_order_productPKorder_product_hkSTRINGPKload_dtsTIMESTAMPhash_diffSTRINGquantityINTunit_priceDECIMALrecord_sourceSTRING
Open the full-size diagram (SVG)

Open this model in EntityModel.com to explore it, change it and export it. Nothing is uploaded: the model travels in the link. Or download model.json.

Entities

Entity Type Description Primary Key Display Attribute Attributes
Hub Customer Entity One row per customer business key, ever. Never updated. customer_hk customer_bk 4
Hub Order Entity One row per order business key. order_hk order_bk 4
Hub Product Entity One row per product business key (SKU). product_hk product_bk 4
Link Order Customer Entity Relates an order to the customer who placed it. order_customer_hk load_dts 5
Link Order Product Entity Relates an order to each product on it (the order line). order_product_hk load_dts 6
Sat Customer Details Entity Customer attributes over time. A new row only when the hash diff changes. customer_hk customer_name 7
Sat Order Details Entity Order header attributes over time, such as status changes. order_hk order_status 7
Sat Order Product Entity Attributes of an order line (on the link): quantity and price. order_product_hk quantity 6
Sat Product Details Entity Product attributes over time. product_hk product_name 7

Attributes

Hub Customer

One row per customer business key, ever. Never updated.

Attribute Data Type Flags Reference Example Description
customer_hk STRING PK, Required 9f2c…e1 Hash of the business key.
customer_bk STRING Label, Required CUS-104233 Business key from the source.
load_dts TIMESTAMP Required 2026-11-03T02:00:00Z When the key was first loaded.
record_source STRING Required crm.customers

Hub Order

One row per order business key.

Attribute Data Type Flags Reference Example Description
order_hk STRING PK, Required c07d…90
order_bk STRING Label, Required SO-2026-000123
load_dts TIMESTAMP Required 2026-11-03T02:00:00Z
record_source STRING Required shop.orders

Hub Product

One row per product business key (SKU).

Attribute Data Type Flags Reference Example Description
product_hk STRING PK, Required 41ab…7c
product_bk STRING Label, Required TEE-ORG-M-BLU
load_dts TIMESTAMP Required 2026-11-03T02:00:00Z
record_source STRING Required erp.items

Relates an order to the customer who placed it.

Attribute Data Type Flags Reference Example Description
order_customer_hk STRING PK, Required 5d3e…aa Hash of both business keys.
order_hk STRING Required c07d…90
customer_hk STRING Required 9f2c…e1
load_dts TIMESTAMP Label, Required 2026-11-03T02:00:00Z
record_source STRING Required shop.orders

Relates an order to each product on it (the order line).

Attribute Data Type Flags Reference Example Description
order_product_hk STRING PK, Required e81f…02
order_hk STRING Required c07d…90
product_hk STRING Required 41ab…7c
line_number INT Required 1 Dependent child key.
load_dts TIMESTAMP Label, Required 2026-11-03T02:00:00Z
record_source STRING Required shop.order_lines

Sat Customer Details

Customer attributes over time. A new row only when the hash diff changes.

Attribute Data Type Flags Reference Example Description
customer_hk STRING PK, Required 9f2c…e1
load_dts TIMESTAMP PK, Required 2026-11-03T02:00:00Z
hash_diff STRING Required 77e0…4b Hash of the descriptive columns.
customer_name STRING Label, PII Ana Silva
email STRING PII ana@example.com
segment STRING Loyalty Gold
record_source STRING Required crm.customers

Sat Order Details

Order header attributes over time, such as status changes.

Attribute Data Type Flags Reference Example Description
order_hk STRING PK, Required c07d…90
load_dts TIMESTAMP PK, Required 2026-11-03T02:00:00Z
hash_diff STRING Required 0b44…19
order_status STRING Label SHIPPED
ordered_at TIMESTAMP 2026-11-02T18:52:11Z
total_amount DECIMAL(12,2) 146.82
record_source STRING Required shop.orders

Sat Order Product

Attributes of an order line (on the link): quantity and price.

Attribute Data Type Flags Reference Example Description
order_product_hk STRING PK, Required e81f…02
load_dts TIMESTAMP PK, Required 2026-11-03T02:00:00Z
hash_diff STRING Required 9a01…3e
quantity INT Label 2
unit_price DECIMAL(12,2) 24.99
record_source STRING Required shop.order_lines

Sat Product Details

Product attributes over time.

Attribute Data Type Flags Reference Example Description
product_hk STRING PK, Required 41ab…7c
load_dts TIMESTAMP PK, Required 2026-11-03T02:00:00Z
hash_diff STRING Required 1c9a…dd
product_name STRING Label Organic Tee
category STRING Apparel
list_price DECIMAL(12,2) 24.99
record_source STRING Required erp.items

Relationships

Relationship Source Target Cardinality Forward Label Reverse Label Key Description
links_order Link Order Customer Hub Order N:1 Links Linked In link_order_customer.order_hk
links_customer Link Order Customer Hub Customer N:1 Links Linked In link_order_customer.customer_hk
line_order Link Order Product Hub Order N:1 Links Linked In link_order_product.order_hk
line_product Link Order Product Hub Product N:1 Links Linked In link_order_product.product_hk
describes_customer Sat Customer Details Hub Customer N:1 Describes Described By sat_customer_details.customer_hk
describes_product Sat Product Details Hub Product N:1 Describes Described By sat_product_details.product_hk
describes_order Sat Order Details Hub Order N:1 Describes Described By sat_order_details.order_hk
describes_line Sat Order Product Link Order Product N:1 Describes Described By sat_order_product.order_product_hk

SQL DDL (PostgreSQL)

Generated from the model. In the app, Export → Code also writes MySQL, Snowflake and Databricks DDL, DBML, dbt schema.yml and data contracts.

-- Data Vault 2.0 (Orders) — data model
-- PostgreSQL DDL, generated 2026-11-03
-- Made with EntityModel.com

CREATE TABLE hub_customer (
  customer_hk TEXT NOT NULL,
  customer_bk TEXT NOT NULL,
  load_dts TIMESTAMP NOT NULL,
  record_source TEXT NOT NULL,
  PRIMARY KEY (customer_hk)
);
COMMENT ON TABLE hub_customer IS 'One row per customer business key, ever. Never updated.';
COMMENT ON COLUMN hub_customer.customer_hk IS 'Hash of the business key.';
COMMENT ON COLUMN hub_customer.customer_bk IS 'Business key from the source.';
COMMENT ON COLUMN hub_customer.load_dts IS 'When the key was first loaded.';

CREATE TABLE hub_product (
  product_hk TEXT NOT NULL,
  product_bk TEXT NOT NULL,
  load_dts TIMESTAMP NOT NULL,
  record_source TEXT NOT NULL,
  PRIMARY KEY (product_hk)
);
COMMENT ON TABLE hub_product IS 'One row per product business key (SKU).';

CREATE TABLE hub_order (
  order_hk TEXT NOT NULL,
  order_bk TEXT NOT NULL,
  load_dts TIMESTAMP NOT NULL,
  record_source TEXT NOT NULL,
  PRIMARY KEY (order_hk)
);
COMMENT ON TABLE hub_order IS 'One row per order business key.';

CREATE TABLE link_order_customer (
  order_customer_hk TEXT NOT NULL,
  order_hk TEXT NOT NULL,
  customer_hk TEXT NOT NULL,
  load_dts TIMESTAMP NOT NULL,
  record_source TEXT NOT NULL,
  PRIMARY KEY (order_customer_hk)
);
COMMENT ON TABLE link_order_customer IS 'Relates an order to the customer who placed it.';
COMMENT ON COLUMN link_order_customer.order_customer_hk IS 'Hash of both business keys.';

CREATE TABLE link_order_product (
  order_product_hk TEXT NOT NULL,
  order_hk TEXT NOT NULL,
  product_hk TEXT NOT NULL,
  line_number INTEGER NOT NULL,
  load_dts TIMESTAMP NOT NULL,
  record_source TEXT NOT NULL,
  PRIMARY KEY (order_product_hk)
);
COMMENT ON TABLE link_order_product IS 'Relates an order to each product on it (the order line).';
COMMENT ON COLUMN link_order_product.line_number IS 'Dependent child key.';

CREATE TABLE sat_customer_details (
  customer_hk TEXT NOT NULL,
  load_dts TIMESTAMP NOT NULL,
  hash_diff TEXT NOT NULL,
  customer_name TEXT,
  email TEXT,
  segment TEXT,
  record_source TEXT NOT NULL,
  PRIMARY KEY (customer_hk, load_dts)
);
COMMENT ON TABLE sat_customer_details IS 'Customer attributes over time. A new row only when the hash diff changes.';
COMMENT ON COLUMN sat_customer_details.hash_diff IS 'Hash of the descriptive columns.';

CREATE TABLE sat_product_details (
  product_hk TEXT NOT NULL,
  load_dts TIMESTAMP NOT NULL,
  hash_diff TEXT NOT NULL,
  product_name TEXT,
  category TEXT,
  list_price NUMERIC(12,2),
  record_source TEXT NOT NULL,
  PRIMARY KEY (product_hk, load_dts)
);
COMMENT ON TABLE sat_product_details IS 'Product attributes over time.';

CREATE TABLE sat_order_details (
  order_hk TEXT NOT NULL,
  load_dts TIMESTAMP NOT NULL,
  hash_diff TEXT NOT NULL,
  order_status TEXT,
  ordered_at TIMESTAMP,
  total_amount NUMERIC(12,2),
  record_source TEXT NOT NULL,
  PRIMARY KEY (order_hk, load_dts)
);
COMMENT ON TABLE sat_order_details IS 'Order header attributes over time, such as status changes.';

CREATE TABLE sat_order_product (
  order_product_hk TEXT NOT NULL,
  load_dts TIMESTAMP NOT NULL,
  hash_diff TEXT NOT NULL,
  quantity INTEGER,
  unit_price NUMERIC(12,2),
  record_source TEXT NOT NULL,
  PRIMARY KEY (order_product_hk, load_dts)
);
COMMENT ON TABLE sat_order_product IS 'Attributes of an order line (on the link): quantity and price.';

-- Keys between tables
ALTER TABLE hub_customer ADD CONSTRAINT uq_hub_customer_customer_bk UNIQUE (customer_bk);
ALTER TABLE hub_product ADD CONSTRAINT uq_hub_product_product_bk UNIQUE (product_bk);
ALTER TABLE hub_order ADD CONSTRAINT uq_hub_order_order_bk UNIQUE (order_bk);
ALTER TABLE link_order_customer ADD CONSTRAINT fk_links_order FOREIGN KEY (order_hk) REFERENCES hub_order (order_hk);
ALTER TABLE link_order_customer ADD CONSTRAINT fk_links_customer FOREIGN KEY (customer_hk) REFERENCES hub_customer (customer_hk);
ALTER TABLE link_order_product ADD CONSTRAINT fk_line_order FOREIGN KEY (order_hk) REFERENCES hub_order (order_hk);
ALTER TABLE link_order_product ADD CONSTRAINT fk_line_product FOREIGN KEY (product_hk) REFERENCES hub_product (product_hk);
ALTER TABLE sat_customer_details ADD CONSTRAINT fk_describes_customer FOREIGN KEY (customer_hk) REFERENCES hub_customer (customer_hk);
ALTER TABLE sat_product_details ADD CONSTRAINT fk_describes_product FOREIGN KEY (product_hk) REFERENCES hub_product (product_hk);
ALTER TABLE sat_order_details ADD CONSTRAINT fk_describes_order FOREIGN KEY (order_hk) REFERENCES hub_order (order_hk);
ALTER TABLE sat_order_product ADD CONSTRAINT fk_describes_line FOREIGN KEY (order_product_hk) REFERENCES link_order_product (order_product_hk);

Mermaid

Paste into a mermaid code block on GitHub, GitLab or Notion to show the diagram there.

---
title: Data Vault 2.0 (Orders)
---
%% Made with EntityModel.com
erDiagram
  hub_customer {
    string customer_hk PK "Hash of the business key."
    string customer_bk "Business key from the source."
    timestamp load_dts "When the key was first loaded."
    string record_source "Record Source"
  }
  hub_product {
    string product_hk PK "Product Hk"
    string product_bk "Product Bk"
    timestamp load_dts "Load Dts"
    string record_source "Record Source"
  }
  hub_order {
    string order_hk PK "Order Hk"
    string order_bk "Order Bk"
    timestamp load_dts "Load Dts"
    string record_source "Record Source"
  }
  link_order_customer {
    string order_customer_hk PK "Hash of both business keys."
    string order_hk FK "Order Hk"
    string customer_hk FK "Customer Hk"
    timestamp load_dts "Load Dts"
    string record_source "Record Source"
  }
  link_order_product {
    string order_product_hk PK "Order Product Hk"
    string order_hk FK "Order Hk"
    string product_hk FK "Product Hk"
    int line_number "Dependent child key."
    timestamp load_dts "Load Dts"
    string record_source "Record Source"
  }
  sat_customer_details {
    string customer_hk PK, FK "Customer Hk"
    timestamp load_dts PK "Load Dts"
    string hash_diff "Hash of the descriptive columns."
    string customer_name "Customer Name"
    string email "Email"
    string segment "Segment"
    string record_source "Record Source"
  }
  sat_product_details {
    string product_hk PK, FK "Product Hk"
    timestamp load_dts PK "Load Dts"
    string hash_diff "Hash Diff"
    string product_name "Product Name"
    string category "Category"
    decimal list_price "List Price"
    string record_source "Record Source"
  }
  sat_order_details {
    string order_hk PK, FK "Order Hk"
    timestamp load_dts PK "Load Dts"
    string hash_diff "Hash Diff"
    string order_status "Order Status"
    timestamp ordered_at "Ordered At"
    decimal total_amount "Total Amount"
    string record_source "Record Source"
  }
  sat_order_product {
    string order_product_hk PK, FK "Order Product Hk"
    timestamp load_dts PK "Load Dts"
    string hash_diff "Hash Diff"
    int quantity "Quantity"
    decimal unit_price "Unit Price"
    string record_source "Record Source"
  }
  link_order_customer }o--|| hub_order : "Links"
  link_order_customer }o--|| hub_customer : "Links"
  link_order_product }o--|| hub_order : "Links"
  link_order_product }o--|| hub_product : "Links"
  sat_customer_details }o--|| hub_customer : "Describes"
  sat_product_details }o--|| hub_product : "Describes"
  sat_order_details }o--|| hub_order : "Describes"
  sat_order_product }o--|| link_order_product : "Describes"

Frequently asked questions

Hubs store unique business keys, links store relationships between hubs, and satellites store descriptive attributes and their history for a hub or a link. Together they separate identity, relationships and context.

When should you use Data Vault instead of a star schema?

Data Vault suits the integration layer when you combine many changing sources and need full history and auditability. Star schemas suit the presentation layer that analysts query. Many warehouses use both: a vault for integration, stars built on top for reporting.