Kimball, Inmon, Data Vault, and OBT: Which Data Modeling Framework Fits Your Warehouse
Four frameworks, one warehouse — what each approach optimizes for, when it wins, when it loses, and how to combine them in a modern dbt stack without ending up with a shape nobody can maintain.
Every data team eventually argues about modeling. The argument usually starts as a schema decision — "should this be a star or should we just flatten it?" — and ends as an identity question, because how you model your warehouse is really a statement about who it's for and what change looks like in your business.
Four frameworks show up over and over: Kimball's dimensional modeling, Inmon's corporate information factory, Data Vault, and — more recently — one big table (OBT). None of them is wrong. Each optimizes for a different property, and picking the wrong one for your context is how teams end up with a warehouse that is technically correct and practically unusable.
This post walks through what each framework actually is, what it buys you, what it costs, and how to combine them in a modern warehouse without ending up with the worst of every world.
Why Framework Choice Still Matters
"Just build tables that answer the questions" sounds reasonable and produces a warehouse where the same question returns three different answers by lunchtime. Framework choice matters because it forces you to decide, up front, a few things you'd otherwise re-decide table by table:
- Where the business logic lives. In the raw layer? In a curated integration layer? In the consumption layer next to the dashboards? Every framework answers this differently, and the answer determines how easy it is to change a definition without breaking twelve downstream models.
- How you absorb source-system change. A new field on the customer object, a renamed column, a system replatform — these are inevitable. Some frameworks isolate the raw shape from the analytics shape, so change happens in one layer. Others don't.
- How you handle history. Whether the warehouse remembers what a customer's segment used to be — and how expensively — is a modeling decision, not a storage one.
- Who can safely add a table. A framework with strong conventions lets a new engineer add a fact table on day two. A framework with no conventions turns every addition into a design review.
Cheap storage did not make these questions go away. It made it possible to postpone them, which is why so many warehouses that started as "we'll just use dbt and figure it out" now have four different definitions of active customer.
The Four Frameworks at a Glance
Before we go deep on each one, here's the shape of the argument. Each framework is really a set of answers to "where does raw data go, where does business logic go, and what do analysts query?"
| Framework | Core unit | Optimizes for | Cost you pay |
|---|---|---|---|
| Kimball | Star schema — fact + conformed dimensions | Analyst legibility, query performance, fast time-to-first-dashboard | Business logic mixed into the analytics layer; harder to refactor |
| Inmon | 3NF enterprise data warehouse feeding dependent data marts | Single source of truth, integrated enterprise view | Long build time; heavy up-front modeling; slow to change |
| Data Vault 2.0 | Hubs, links, satellites in a raw vault, plus a Kimball-style business vault on top | Auditability, source-system agility, parallel loading | Many small tables; complex joins; steep learning curve |
| OBT (one big table) | A single wide, denormalized fact-plus-attributes table | BI-tool ergonomics, no-join queries, semantic-layer simplicity | Storage bloat; painful history; hidden grain problems |
A useful frame: Kimball asks "how should analysts see the world?", Inmon asks "how should the enterprise see the world?", Data Vault asks "how should the warehouse absorb change?", and OBT asks "how do we make the BI tool stop complaining?".
Kimball — The Dimensional Approach
Ralph Kimball's dimensional modeling is the framework most working data engineers meet first, because it's the one the industry converged on for BI. The core unit is the star schema: a narrow, deep fact table holding measurements plus foreign keys, surrounded by wide, flat dimension tables holding context. Business logic is applied on the way into the marts; the resulting shape is designed to be read by an analyst without a data-modeling PhD.
what it looks like in a modern stack
{{ config(materialized='incremental', unique_key='revenue_sk') }}
select
{{ dbt_utils.generate_surrogate_key(['order_id','line_id']) }} as revenue_sk,
o.order_sk,
c.customer_sk,
p.product_sk,
d.date_sk,
ol.quantity,
ol.net_amount_inr,
ol.discount_inr,
ol.cogs_inr
from {{ ref('stg_order_lines') }} ol
left join {{ ref('dim_customer') }} c on c.customer_id = ol.customer_id and c.is_current
left join {{ ref('dim_product') }} p on p.product_id = ol.product_id and p.is_current
left join {{ ref('dim_date') }} d on d.date_actual = ol.order_date
left join {{ ref('dim_order') }} o on o.order_id = ol.order_id
{% if is_incremental() %}
where ol._loaded_at > (select max(_loaded_at) from {{ this }})
{% endif %}
where it wins
Kimball is unbeatable for BI-first warehouses where the audience is analysts and the primary output is dashboards and metrics. The star schema is optimized both for columnar storage (small number of joins to well-clustered dimensions) and for the human reading the ERD. Slowly-changing dimensions handle history cleanly. Onboarding is fast — most analytics engineers already know it.
where it hurts
Business logic is baked into the marts. When the definition of "revenue" changes, you rebuild the mart; when the source system adds a field, you thread it through staging → intermediate → mart. Kimball is not designed to be a system of record, and it does not audit itself. If two dimensions disagree — because one snapshotted a bad batch and the other didn't — reconstructing what happened is up to you.
Inmon — The Corporate Information Factory
Bill Inmon's approach predates the modern data stack by two decades but still turns up whenever a large organization needs a single, authoritative enterprise view. The idea is a top-down enterprise data warehouse (EDW) modeled in third normal form — one row per real-world entity, one attribute per column, foreign keys everywhere — that feeds downstream data marts, which are usually Kimball-shaped.
what it looks like in practice
Inmon warehouses are built entity-first: customer, account, product, contract, policy — each with its own table, keys to related entities, and no denormalization. Business definitions live in the EDW layer. Reporting doesn't run directly against the EDW; it runs against marts built on top of it. The EDW is the single source of truth; the marts are its consumption faces.
create table edw.customer (
customer_id bigint primary key,
customer_type_id int references edw.customer_type,
primary_address_id bigint references edw.address,
household_id bigint references edw.household,
first_name varchar(80),
last_name varchar(80),
effective_from date not null,
effective_to date not null,
unique(customer_id, effective_from)
);
-- attributes that change frequently sit on satellite tables
-- (customer_contact, customer_preferences, customer_segment)
where it wins
Inmon is the right shape for organizations where the warehouse is a system of record — banks, insurers, telcos, regulated healthcare. The EDW gives you an unambiguous definition of every business entity, non-redundant storage, and a place to enforce enterprise-wide referential integrity. It's also the framework auditors are most comfortable with.
where it hurts
Time-to-first-dashboard is measured in quarters, not sprints. Every new source system has to be reconciled with the existing entity model before its data can flow through; every change to the entity model touches many tables. In a small team with fast-moving product data, an Inmon-style EDW is where dashboards go to wait.
In modern practice you rarely see a pure Inmon warehouse. The pattern more common today is Inmon-flavoured intermediate: a normalized, integrated layer between staging and marts, without the full CIF ceremony, that gives you the "one authoritative definition per entity" property without the two-year build.
Data Vault 2.0 — Auditable and Adaptive
Data Vault, formalized by Dan Linstedt, is what you get when you optimize for change. Rather than modeling the business as it is today, it models the audit trail of how you learned about the business, then produces a Kimball-style consumption layer on top.
The raw vault has three shapes:
- Hub — one row per unique business key. A hub table for
customerholds nothing but the natural key, a hashed surrogate, the load timestamp, and the record source. Hubs never change. - Link — a many-to-many association between hubs. An
order_customer_product_linkrow says "these three hubs were seen together on this order". Links, like hubs, are insert-only. - Satellite — descriptive attributes hanging off a hub or link, versioned by
load_ts. A change to a customer's segment inserts a new satellite row; the old row is never updated. History is a query, not a snapshot job.
select
{{ dbt_utils.generate_surrogate_key(['customer_id_source','source_system']) }} as customer_hk,
customer_id_source as customer_bk,
current_timestamp() as load_ts,
source_system as record_source
from {{ ref('stg_customer') }}
qualify row_number() over (partition by customer_hk order by load_ts) = 1
the business vault on top
Nobody queries the raw vault directly. On top of it sits a business vault that applies logic — deduplication, current-record flags, business rules — and, above that, a Kimball-style consumption layer of dims and facts that analysts and BI tools actually see. Data Vault does not replace dimensional modeling; it feeds it.
where it wins
Data Vault is the right shape when the warehouse is the system of record for change: financial services with heavy audit demands, healthcare where you need to reconstruct exactly what was known about a patient at any point in time, or any environment where source systems come and go faster than the analytics team can absorb. Loads are highly parallel (hubs, links, and satellites have no cross dependencies on each other), and every row carries provenance.
where it hurts
The learning curve is real. A modest business domain becomes hundreds of small tables; a single "customer with their latest segment" query has to join a hub, a satellite, and often a link. Without a Data Vault-aware tool (dbtvault, VaultSpeed, WhereScape) the boilerplate is exhausting. And because analysts always work off the consumption layer, you effectively maintain two warehouses.
One Big Table (OBT) — The Modern Anti-Framework
OBT is what happens when a team builds warehouses for BI tools rather than for analysts writing SQL. Take a fact table, join it to every dimension you can think of, keep every attribute alongside every measurement, and materialize the result as one wide table. The BI tool never has to join anything. The semantic layer becomes a thin wrapper.
what it looks like
{{ config(materialized='incremental', unique_key='order_line_id') }}
select
ol.order_id,
ol.line_id,
ol.order_line_id,
ol.order_date,
ol.quantity,
ol.net_amount_inr,
ol.discount_inr,
-- customer attributes, denormalized in
c.customer_name, c.customer_segment, c.city, c.state,
c.acquisition_channel, c.first_order_date,
-- product attributes, denormalized in
p.product_name, p.category, p.sub_category, p.brand,
p.cogs_inr, p.list_price_inr,
-- calendar attributes, denormalized in
d.day_of_week, d.month_name, d.quarter, d.fiscal_year
from {{ ref('stg_order_lines') }} ol
left join {{ ref('dim_customer') }} c using (customer_id)
left join {{ ref('dim_product') }} p using (product_id)
left join {{ ref('dim_date') }} d on d.date_actual = ol.order_date
where it wins
OBT is the pragmatic answer when the consumer is Looker, Tableau, Power BI, or a metrics layer with limited join support, and when the warehouse is on modern columnar storage where wide tables compress well. There's no join blast radius, no dimension-conformance argument at dashboard time, and semantic layers on top become simpler because every measurement already carries its context.
where it hurts
OBT quietly hides two problems. First, grain drift: because there's no clean separation of measurements from context, a well-meaning engineer will add "monthly churn" as a column on an order-line table, and now half the rows have a value that doesn't correspond to the row's grain. Second, history: an OBT freezes attribute values at build time, so unless you rebuild the whole table you cannot answer "what was this customer's segment when this order was placed?" — the classic Kimball SCD Type 2 question — without deeply unpleasant workarounds.
Use OBT as a consumption layer sitting on top of properly modeled dims and facts. Do not use it as the primary storage shape of the warehouse.
Choosing a Framework
No framework is universally right, and the answer for most teams is a hybrid. Some diagnostics that actually work:
- How many source systems, and how volatile? One or two stable sources → Kimball is enough. Ten sources, half of them mid-migration → Data Vault earns its complexity.
- Who consumes the warehouse? Analysts writing SQL → Kimball. A BI tool with limited joins or a semantic layer → OBT on top of Kimball. Auditors and regulators → Data Vault or Inmon.
- How important is historical reconstruction? "What did we know on Tuesday at 2pm?" is a Data Vault question. "What was this customer's segment at order time?" is a Kimball SCD question.
- What's the team size? A three-person analytics team should not run Data Vault; the ratio of framework overhead to business value is wrong. Below ten people, Kimball with an Inmon-flavoured intermediate is almost always the right default.
- How long is the warehouse expected to live? A three-year tactical build tolerates OBT and light Kimball. A ten-year enterprise warehouse absorbing many source-system replacements needs Data Vault's insulation.
Combining Frameworks in a Modern Stack
In practice, most healthy warehouses run a hybrid. A common shape:
- Staging — one model per source table, light casting and renaming, no logic. Framework-agnostic.
- Raw Vault / Integration — either full Data Vault (hubs/links/satellites) for regulated or multi-source environments, or an Inmon-flavoured integration layer holding one canonical row per entity. This is where cross-source reconciliation happens.
- Marts — Kimball dims and facts, materialized as incremental or table models. Analysts query these directly; the definitions live here.
- Consumption / OBT — optional wide tables built on top of the marts for BI tools that struggle with joins, or for very hot analytical questions.
dbt makes this layering explicit through folder structure and ref(). Each layer has one job; the transition between them is a version-controlled model, not a stored procedure. And because every layer inherits from the one below it, replacing the integration layer (say, moving from Inmon-style to full Data Vault) does not require rewriting the marts.
models/
├── staging/ # framework-agnostic; one model per source table
│ ├── crm/
│ ├── billing/
│ └── product/
├── integration/ # Data Vault raw + business vault, or Inmon 3NF
│ ├── raw_vault/
│ ├── business_vault/
│ └── entities/
├── marts/ # Kimball — dims and facts
│ ├── finance/
│ ├── product/
│ └── shared_dims/
└── consumption/ # optional OBT views for BI
└── obt_orders.sql
If you can't say which folder a new model belongs in without a five-minute discussion, the framework is not landed yet — that discussion is the framework doing its job, one model at a time.
Common Mistakes
- Adopting Data Vault because a talk was persuasive. If your warehouse has two source systems and five analysts, Data Vault's overhead will bury you. Reach for it when a Kimball-first stack starts creaking under real source-system change, not before.
- Treating OBT as the storage layer. One big table is a consumption shape. When it becomes the only shape, you lose history, you lose grain discipline, and any change to an attribute triggers a full rebuild.
- Skipping the integration layer. Going straight from staging to marts saves an afternoon and costs a year. Without an integration layer, every mart re-implements the same joins and definitions, and they drift.
- Confusing Kimball with "just make a fact table". Dimensional modeling is a system: conformed dimensions, declared grain, SCDs, an unknown member, the works. A pile of fact tables that share no dimensions is not Kimball; it's chaos with jargon.
- Believing the framework will pick itself. Frameworks lose to inertia. The default in a team that hasn't picked one is "whatever the loudest engineer builds first" — and that becomes the shape of the warehouse whether it should be or not.
Wrapping Up
The four frameworks are not competitors so much as different answers to the question "what is the warehouse for?". Kimball optimizes for analysts. Inmon optimizes for the enterprise. Data Vault optimizes for change. OBT optimizes for BI tools.
Most modern warehouses run some combination of them: a Kimball marts layer that analysts and BI tools query, sitting on top of an integration layer that looks either Inmon-like (for small teams) or Data-Vault-shaped (for large, regulated, multi-source environments), sitting on top of framework-agnostic staging. OBT shows up as a consumption convenience on top, not the storage layer beneath.
Pick one as the primary shape, and be explicit about why. The framework is not the point; the point is that a warehouse where every table's role is obvious is a warehouse whose numbers you can defend at the next quarterly review. That's a modeling property, not a technology property, and no amount of cheap storage will produce it by accident.
— This article is part of an ongoing data-engineering series on techedge.in. Wrestling with a modeling choice? Drop a comment, I read every one.
One email, every other week.
New posts on data engineering, applied AI, and the business decisions around them. No noise, unsubscribe anytime.
Comments
All comments are reviewed before they appear publicly — this keeps spam out.
Loading comments…