Data Analytics

How to build a governed Data Mart library: start with the numbers people argue about

You have a warehouse full of tables and a folder of ad-hoc queries, and someone has asked for one place where the numbers live. This page is for the analyst who has to build it: how to find the three to five numbers worth starting with, how to name and describe each Data Mart, who owns it, what governed means once you take the committee out, how people get the numbers, and what to leave unbuilt. The last section is for the person who asked.

Data AnalyticsIevgen Krasovytskyi19 min read

How to build a governed Data Mart library: start with the numbers people argue about

A governed Data Mart library starts with the three to five numbers people argue about, not with the tables you happen to have. If someone has just asked you for “one place where the numbers are, so we stop asking you every time”, you already have the raw material: a warehouse full of tables and a folder of queries you have written more than once. What you do not have is a short list people can trust without asking you first.

That list is smaller than you expect. Each number on it gets one home, a name that says what a row is, a description, two owners, a few checks, and a rule for who may change it.

The examples use a demo shop whose data is small, clean and synthetic, so yours will be messier. The last section is written for the person who asked, and you can forward it as it is.

The short answer

The short answer

Build fewer Data Marts than you have tables, and choose them by dispute, not by source. A number belongs in the first version of the library when two honest people can compute it two ways and get different results. Everything else can wait until somebody asks twice.

None of this needs a new tool to start. A view in your warehouse and a shared document hold the first version.

Which Data Marts to build first

Which Data Marts to build first

Start from the questions, not from the schema. Write down the numbers that came up in the last few meetings, then test each one: can I compute it two defensible ways, and do the results differ? If they do, the number is contested, and it needs a single home. If they do not, it can stay an ad-hoc query for now.

Here is that test on the demo shop, for the third quarter of 2026. Each line is a number a manager would ask for in one phrase.

The question One honest answer Another honest answer Contested?
How many new customers did we get? 458 accounts registered 53 customers placed their first order; 84 had their first completed order Yes, three ways
How many customers bought from us? 1,593 placed an order 1,397 had a completed order Yes
What is our conversion rate? 2.47% of sessions ended in an order 2.10% counting completed orders only; 2.96% of visitors placed an order (1,932 of 65,191) Yes, three ways
What is the average order value? $513.98 across every order placed $514.03 across completed orders No, five cents apart

Three of the four need a definition. The fourth does not: average order value barely moves between placed and completed orders, the only split tested here, so nobody will bring two versions of that to a meeting. Gross against net, discounts, shipping and tax can still make it contested in your shop. That is the useful result of the test: it tells you what not to build yet. In the demo every order carries a customer ID that exists in Customers, but many accounts were registered after the customer’s first order, which is why registrations and first orders are so far apart. Your gap will be different, and it will still be there.

The “new customers” line takes one short query to reproduce. This one is written for the demo dataset, which sits in Google BigQuery:

WITH first_order AS (
  SELECT
    customer_id,
    MIN(order_date) AS first_placed,
    MIN(IF(status = 'Completed', order_date, NULL))
      AS first_completed
  FROM `owox-demo.ecommerce.orders`
  GROUP BY customer_id
)
SELECT
  COUNTIF(first_placed
    BETWEEN '2026-07-01' AND '2026-09-30') AS placed,
  COUNTIF(first_completed
    BETWEEN '2026-07-01' AND '2026-09-30') AS completed
FROM first_order

It returns 53 and 84. order_date is a DATE in the demo, so BETWEEN covers the whole of 30 September; on a TIMESTAMP column, write < '2026-10-01' instead. The second figure is larger because some customers’ first order, in an earlier quarter, was cancelled or returned, and their first completed one landed in this quarter. Nobody would guess that from the phrase “new customers”, which is the reason the definition has to be written down.

The other figures in the table come from one more query, run on 11 October 2026. “Placed” here means any order with a date in the quarter, whatever its status:

WITH q3_orders AS (
  SELECT
    o.order_id, o.customer_id, o.status,
    SUM(p.line_revenue) AS order_value
  FROM `owox-demo.ecommerce.orders` AS o
  JOIN `owox-demo.ecommerce.purchases` AS p
    USING (order_id)
  WHERE o.order_date
    BETWEEN '2026-07-01' AND '2026-09-30'
  GROUP BY o.order_id, o.customer_id, o.status
),
orders AS (
  SELECT
    COUNT(*) AS placed,
    COUNTIF(status = 'Completed') AS completed,
    COUNT(DISTINCT customer_id) AS buyers,
    COUNT(DISTINCT IF(status = 'Completed',
      customer_id, NULL)) AS buyers_completed,
    SUM(order_value) AS value_placed,
    SUM(IF(status = 'Completed',
      order_value, 0)) AS value_completed
  FROM q3_orders
),
visits AS (
  SELECT
    COUNT(*) AS sessions,
    COUNT(DISTINCT visitor_id) AS visitors,
    COUNT(DISTINCT IF(is_conversion,
      visitor_id, NULL)) AS converting_visitors
  FROM `owox-demo.ecommerce.sessions`
  WHERE date BETWEEN '2026-07-01' AND '2026-09-30'
),
accounts AS (
  SELECT COUNT(*) AS registered
  FROM `owox-demo.ecommerce.customers`
  WHERE registration_date
    BETWEEN '2026-07-01' AND '2026-09-30'
)
SELECT
  registered, buyers, buyers_completed,
  ROUND(100 * placed / sessions, 2) AS cr_placed,
  ROUND(100 * completed / sessions, 2) AS cr_completed,
  ROUND(100 * converting_visitors / visitors, 2)
    AS cr_visitors,
  ROUND(value_placed / placed, 2) AS aov_placed,
  ROUND(value_completed / completed, 2) AS aov_completed
FROM orders, visits, accounts

It returns 458, 1,593, 1,397, 2.47, 2.1, 2.96, 513.98 and 514.03. That is one synthetic shop and one quarter: enough to show the test separating numbers that need a definition from one that does not, not a benchmark for your shop.

From contested numbers to Data Marts

The questions above touch three things: orders, customers and sessions. Those three are the first Data Marts, not the metrics. A metric does not exist on its own: a conversion rate needs sessions and orders, so it is a field on the Data Mart that holds them. The OWOX Data Marts documentation puts it the same way in its guide to designing a data model: one Data Mart is one object at one grain, and “a metric is not an object”.

So the first version of the library for this shop is short:

Data Mart One row is Contested numbers it settles
Orders one order, with its status and date customers who bought; new customers by first order
Customers one registered customer account new customers by registration
Sessions one visit, keyed by session ID and carrying the visitor ID conversion rate per session or per visitor (each order carries the session ID it came from)

Three Data Marts settle every contested line in the table. The fourth and fifth come when their numbers are argued about: order lines for revenue and margin (worked through in the reconciliation of one quarter’s sales figures), and ad spend for marketing cost.

If your shop takes guest orders with no customer ID, those buyers have no row in Customers. Count buyers from Orders, which keeps every order, and give guest orders a stable customer key: a hashed email address, a loyalty ID, or an account-matching rule you write down. A key per order would count every guest order as a new customer. A report that starts from one Data Mart keeps all its rows, and an empty key matches nothing in a joined one (how a model is read), so a guest order joined to Customers keeps its revenue and loses its customer attributes. Say in both descriptions that Customers covers registered accounts only.

What a library looks like when nobody chooses

On 11 October 2026 the demo project OWOX staff use to show the product had 70 published Data Marts and 115 reports, and four of those Data Marts fed 54 of the reports while 36 fed none. Some copies are deliberate, one per supported warehouse, but 37 Data Marts had no description and “Facebook Ads Insights” appeared five times, so a reader cannot tell which copy is which. The reports had already voted for a handful of Data Marts; the rest is what a library becomes when publishing is easier than choosing.

The counts come from the product’s command-line client, with an API key for the project, and you can run the same on yours:

npx @owox/ctl data-marts list > data-marts.json
jq '[.[] | select(.status == "PUBLISHED")] | {
  published: length,
  reports: (map(.reportsCount) | add),
  top4: (map(.reportsCount) | sort | reverse
    | .[0:4] | add),
  no_report: (map(select(.reportsCount == 0))
    | length),
  no_description: (map(select(
    (.description // "") == "")) | length),
  no_business_owner: (map(select(
    .businessOwnerUsers | length == 0)) | length)
}' data-marts.json

On the demo project it printed 70, 115, 54, 36, 37 and 46.

The Turning Point

OWOX Data Marts

See your first report built in real time. 15 minutes.

  1. Connect your data warehouse
  2. Pick your metrics
  3. Get a live Google Sheets report

In the time it takes to write a ticket. Then imagine never writing that ticket again.

Book a Demo

We'll use your actual use case

Name each Data Mart for what one row is

Name each Data Mart for what one row is

A name has one job: the reader should know what they will count if they count rows. “Orders” passes. “Q3 dashboard source v2” does not, and neither does “eCommerce Report”, because a report is what someone builds from a Data Mart, not what a row is.

  • Name the object, in the plural, in the business’s own word. Orders, Customers, Sessions, Order lines. If finance says “invoices” and the table says billing_docs, the Data Mart is Invoices.
  • Prefer the object to the metric. This guide recommends not naming a Data Mart “ROAS” or “Conversion rate”. A Data Mart per business question works while each question has one formula; once a second formula appears, a metric-named Data Mart invites a twin, while a field on Orders or Sessions keeps the metric in one home.
  • Keep the name unique across the whole library. If you need the same object twice, the names say why: “Orders” and “Orders (wholesale)”, never “Orders” and “Orders 2”. Keep team initials and storage codes out of the name people read. In OWOX Data Marts a Context, a label such as Marketing or Finance attached to the Data Mart, says whose it is (contexts).

Fields follow the same idea: line_net_revenue can stay in the warehouse while people see “Net revenue”. In OWOX Data Marts that is an alias in the Output Schema, next to each field’s description (SQL-based Data Mart).

Describe it so nobody has to ask you

Describe it so nobody has to ask you

The description is where a contested number stops being contested. Write it for the person who will challenge the figure, and for the AI assistant that will read it before answering. Both need the same four things, in this order:

  1. The grain. “One row per order.” Catalog summaries show only the beginning, so this goes first.
  2. The scope. What is excluded: test orders, internal accounts, a region you do not report on.
  3. The date. Which date a row belongs to. An order has a placed date, a paid date and a shipped date, and a quarter’s total depends on which one you used.
  4. The caveats. Anything that has already caused a wrong reading once.

A description for the demo shop’s Orders Data Mart, written to settle the first line of the table above:

One row per order, with its status (Completed, Cancelled or Returned) and its order date, which is the date the order was [placed / paid / completed]. “Completed” means [paid / shipped / delivered / past the return window]. “New customers” in company reports means customers whose first completed order falls in the period, not accounts registered in it; the count is computed here. Test and staff orders are excluded. Definition of Completed owned by finance; new-customer count owned by [Head of Sales].

The demo settles neither bracket. Its statuses do not say whether Completed means paid, shipped or delivered, and its own field description calls order_date “the date when the transaction was completed”, although cancelled orders carry one too. Your description has to say. The new-customer rule then has one home: Customers says what one account is and points to Orders for the count, instead of carrying a second version of it.

Then do the same per field, more briefly: the unit or currency, what an empty value means, and which rows the value covers. A field called status with no description produces a message asking whether “Returned” counts as a sale. A description that says “Completed, Cancelled or Returned; revenue reports count Completed only” does not.

Give every Data Mart two owners

Give every Data Mart two owners

One name on a Data Mart is not enough, because two different things can be wrong with it. The query can be wrong, and the definition can be wrong. Different people can fix each, so each gets an owner.

  • The data owner answers for the query, the fields and the source tables. Usually that is you.
  • The business owner answers for what the number means and has the authority to make the definition final. Anything that is revenue belongs to finance: gross and net sales, refunds, returns, and what “completed” means. Sales and marketing own the figures they name themselves, such as customers who bought or conversion rate.

The business owner is the person your reader should be able to challenge. With one, your answer to “why does this not match my figure?” is the description and the name on it.

OWOX Data Marts has both roles on each Data Mart. Its documentation describes Data Owners as “responsible for data sources and schema” and Business Owners as “responsible for business requirements” (core concepts). In the demo project above, 46 of the 70 published Data Marts have no business owner, and between them they feed 29 of the 115 reports; the count does not say which came first.

Where two owners disagree about a definition, someone above both has to decide, usually the executive both of them report to. Name that person before the first dispute, not during it.

If nobody will take a number, or the business owner does not answer, take it back to the person who asked for the library. Until it is settled, publish the number with “owner pending” at the top of its description, so readers know the definition is yours and provisional.

What governed means in practice

What governed means in practice

“Governed” sounds like a committee. For a library of five Data Marts it is four plain properties, and a Data Mart either has each one or it does not.

Property The question it answers What you actually do
An owner Who do I ask, and who decides? Two names on every Data Mart: data owner and business owner
A description per field What does this number include? Grain, scope, date and caveats on the Data Mart; unit and meaning on each field
Data quality checks How would we know it broke? A few checks that run on a schedule and tell someone
Change approval Can this number change without anyone knowing? Only named people can edit; the business owner agrees to a redefinition first

Checks that run without you

Start with the checks that match how a total usually breaks: the Data Mart is empty, a key is duplicated so rows are counted twice, a required field is mostly empty, or the data has not arrived. Measure that on a load timestamp, the time the rows landed, not on the newest order date: a quiet sales day is not a failed load. For a table loaded every day, a reasonable first rule is to warn when the last load is more than a day old, then tighten it once you know how the load behaves. You can write each check as a query against your warehouse and schedule it.

In OWOX Data Marts these are data quality checks configured on a published Data Mart: empty table, primary key uniqueness, null rate, data freshness (on a timestamp field) and others, each with a severity, run manually or by a scheduled trigger (data quality checks). The report for each run includes the SQL behind every check, so a failure can be reproduced in the warehouse, and a Data Last Updated value shows when the source tables last changed in storage (Data Last Updated). A passing check shows the rows passed the checks you declared. It does not prove the definition is the one the business meant; that is what the business owner is for.

Change approval, without a workflow tool

A definition that anyone can edit is not a definition. Decide who may change each Data Mart, and make “the business owner agreed” a condition of changing what a number means. Fixing a bug is the data owner’s call. Changing “new customers” from registrations to first completed orders is not.

A workable rule for a small team:

  • The change is written down first, in one sentence, with the old and the new definition.
  • The business owner says yes in writing. For finance’s numbers, finance says yes.
  • The description is updated in the same step, with the date of the change.
  • People who use the number are told before their next report differs from their last one.

Revenue-type numbers need a period rule as well. A closed month does not move without finance’s sign-off; a return that arrives later is counted in the month it happens, unless finance has written down a restatement rule; and each month the revenue figures tie out to the ledger, with any difference explained. If your models live in Git, make the business owner a required reviewer on the model’s file, for example with a CODEOWNERS entry, so the merge enforces the rule.

The OWOX Data Marts documentation describes no approval step: there is nothing that holds an edit until an owner signs it off. What it does have is control over who can edit. A new Data Mart is shared for maintenance by default, which lets any member with the Data Owner role edit it; turn that off and “non-owners keep reporting access and lose the ability to edit or join it” (ownership and sharing). The approval itself stays a rule your team keeps.

How people get the numbers

How people get the numbers

A library nobody can reach is a folder again. The definition lives in one place, and each person reads it in the tool they already open. The route is always the same: data from your sources lands in your warehouse, the Data Mart is defined there, and a report carries its rows to where the person works.

If you are doing this by hand, split it in two. The shared document holds the definition text, the two owners, the date of the last change and the caveats; the view in the warehouse holds the SQL and a comment pointing to the document. Sheets and dashboards read the view and nothing else, because a spreadsheet that filters orders again has a second definition in it. Once a number has its view, retire the saved queries that computed it; keep the rest of the folder for one-off questions.

In OWOX Data Marts the same Data Mart, defined on your warehouse (Google BigQuery, Snowflake, AWS Redshift, AWS Athena or Databricks), feeds Google Sheets on a schedule (report triggers), Microsoft Excel refreshed by the user (“scheduled refresh is not available”, Excel) and Data Studio. AI assistants such as Claude or ChatGPT read your descriptions and run bounded queries through the MCP server in OWOX Data Marts Cloud (MCP server); the rows they retrieve go to the assistant’s provider, so clear that with whoever signs off data sharing first.

What not to do

What not to do

  • Do not mirror every raw table. A Data Mart per source table gives people the warehouse again, with nicer names. They still have to know which three tables to combine and which rows to drop, which was the original problem.
  • Do not publish a Data Mart you have not described. An undescribed Data Mart in the list costs every reader a question, and trains them to ask you instead of reading.
  • Do not keep two homes for one metric. Two conversion-rate fields in two Data Marts are two answers. Keep one; delete or hide the other.
  • Do not expect the library to fix the source. If orders are missing from the warehouse, every Data Mart built on them is missing those orders, consistently.

If the list is already long, the way back is the same test in reverse. For each published Data Mart ask: does a report use it, does it have a description, does it have a business owner? Anything with three “no” answers is a candidate to unpublish. Reports built on it tell you who to warn first.

If you already have views or dbt models

If you already have views or dbt models

Then the library is a selection, not a rebuild: pick the few models that hold the contested numbers and leave staging models out of sight. What is usually missing is the description, the business owner, the checks and the change rule, not the query. In OWOX Data Marts a Data Mart can reference an existing view directly, so the SQL is not copied (view-based Data Mart).

In a larger team with certified dashboards and a BI semantic layer, the library is the shortlist over them, and three rules matter more than the SQL. Write down who can certify a figure and who can withdraw it. Give a deprecated Data Mart or dashboard a sunset date and a pointer to its replacement. And when a definition changes, name the past decks that have to be restated.

For the queue of requests that produced those queries in the first place, see turning recurring data tickets into reusable Data Marts. For the argument about access and control behind all of this, see governed self-service analytics.

Where to start

Where to start

Do the first step before you open any tool.

  1. List the numbers from recent meetings and run the two-ways test on each. Keep the ones whose answers differ.
  2. Group them by what a row is. You should end up with three to five objects.
  3. For each object, write the description first, grain, scope, date and caveats, and send it to the person you think is the business owner.
  4. Build or select one query per object, then repoint the existing reports. This is the long step. Start with the most-used report for each number, and warn the people whose figure will change before it changes, with the old and the new definition side by side.
  5. Add the checks and the change rule, and only then tell people where the numbers live.

The library’s next Data Mart is the next number that comes back twice with two answers.

For the person who asked: the short version

For the person who asked: the short version

You asked for one place where the numbers are. Here is what that takes, without the technical detail. Every bracket below is filled in before this is sent.

It is a short list, not a big system. We will start with the three to five numbers that cause arguments: [new customers, customers who bought, conversion rate]. Each of them can honestly be counted more than one way, and that is why two people bring different figures to the same meeting. Nobody is wrong; nobody has written down which way is ours.

For each number we will write one definition and keep it in one place. Spreadsheets and dashboards will read from it, so there are the same definitions behind every answer, and a calculation you can open. AI assistants can read from it too, through the MCP server in OWOX Data Marts Cloud, once data protection has agreed, because the rows an assistant retrieves go to its provider.

What it takes: one owner from the business for each number, some of their time to agree its definition, and my time to build the definitions and switch the existing reports over to them. Nothing needs to be bought for the first version. A tool comes back as its own decision if the definitions have to reach more places than we can keep in step by hand.

Your part is ownership, and it cannot be delegated to the analyst. Each number needs a named person from the business who decides what it means: what counts as a new customer, whether a returned order is a sale. The analyst can build the number and check it. The analyst cannot decide what the company means by it. Where two department heads disagree, the executive they both report to chooses, and revenue figures still tie out to the books whichever way the choice goes.

After that, a number changes only when its owner agrees, and the people who use it are told. That is all “governed” means here.

What it will not do: fix data that is missing or wrong at the source, or answer brand-new questions without the analyst.

How we will know it worked: by [review date], repeat requests for these numbers go from [N in the last two weeks] to [target], and the monthly review uses one agreed figure for each of them, tied out to the ledger where the number is revenue. [In a larger team: the warehouse’s query logs show whether people read the shared definitions.]

Three things to decide now: who owns each of the first numbers, who settles a disagreement between owners, and whether existing reports that compute these numbers their own way will be switched to the shared definition.

Your New Normal

Turn your data into decisions.

Governed data marts give you the clean foundation ML needs to actually work.

  • No AI hallucinations
  • Analyst-governed definitions
  • Every number traces to SQL
Get started free

FAQ

Frequently Asked Questions

What is a governed Data Mart library?

A short list of Data Marts that people can use without asking the analyst first. Each one has a name that says what a row is, a description of what is included and excluded, a data owner and a business owner, a few data quality checks, and a rule for who may change it. It is not a copy of the warehouse: it holds the handful of numbers the company argues about, each defined once.

How many Data Marts should the first version of a library have?

Usually three to five. Count objects, not metrics: orders, customers and sessions are Data Marts, while conversion rate is a field on one of them. Choose by dispute: a number belongs in the first version when two defensible ways of computing it give different results. A number whose answers agree can stay an ad-hoc query until it is asked for again.

Who should own a Data Mart?

Two people. A data owner, usually the analyst, answers for the query, the fields and the source tables. A business owner answers for what the number means and can make its definition final. OWOX Data Marts has both roles on every Data Mart: Data Owners are responsible for data sources and schema, Business Owners for business requirements (core concepts).

Should every warehouse table become a Data Mart?

No. A Data Mart per raw table gives people the warehouse again under friendlier names: they still have to know which tables to combine and which rows to drop. Build a Data Mart for a business object at one grain, such as one row per order, and only when a number that depends on it is contested or asked for repeatedly. The OWOX Data Marts guide to model design gives the same rule: one Data Mart is one object at one grain (design a data model).

Does OWOX Data Marts have an approval step for changes to a Data Mart?

Its documentation describes no approval workflow. What it controls is who can edit. A new Data Mart is shared for maintenance by default, so any member with the Data Owner role can edit it; with that setting off, non-owners keep reporting access and can no longer edit or join it (ownership and sharing). The agreement of the business owner before a definition changes is a rule the team keeps itself.

Can I build the library on views or dbt models I already have?

Yes. Pick the few models that hold the contested numbers and treat those as the library; staging and intermediate models stay out of sight. In OWOX Data Marts a Data Mart can reference an existing warehouse view directly, so the SQL is not copied (view-based Data Mart). What usually has to be added is a description a non-analyst can read, a business owner, checks, and a rule for changes.

Who wrote this

Ievgen Krasovytskyi

Ievgen Krasovytskyi · Head of Marketing

Ievgen Krasovytskyi is the Head of Marketing at OWOX, leading strategy across content, SEO, product marketing, and AI-powered automation. With deep expertise in analytics infrastructure, data warehouses, and marketing technology, he builds systems that connect marketing performance to business outcomes. Ievgen writes about SaaS growth, analytics workflows, and the future of AI in marketing operations.