Every dashboard team wants its own one-big-table; how do you stop the warehouse model fragmenting?
answer
- say yes to the tables, no to the forks
- who owns the definition?
- joins and projects, never defines
- disposable and regenerable from the core
- count duplicated metrics, not tables
basics
~20 sTreat wide tables as generated, disposable serving artifacts over one modelled core. Business definitions live upstream and are selected, never restated; each mart must be reproducible from the core, owned, lineage-tracked and retirable. Duplicated values are fine; duplicated definitions are not.
solid answer
~50 sSay yes to the wide tables and no to the fragmentation, by separating the **model of record** from the **serving layer**. Facts with declared grains and shared dimensions stay upstream and own every derived attribute; each team's wide mart is generated from them by a transform that only projects and joins, never re-implements a definition. That gives you the test: if a mart contains business logic, it is a fork, not a view. Then govern the serving layer like a product surface — named owner, declared grain, lineage back to the core, a deprecation path, and no promotion of an ad-hoc mart to authoritative source. Keep the marts cheap to regenerate so they stay disposable. Finally, measure the right thing: not how many wide tables exist, but how many places the same metric is computed.
code
text · 12 linesCORE (authoritative, owns definitions)
fact_orders grain: one row per order
dim_customer versioned, owns customer_segment logic
dim_product owns product_category logic
SERVING (generated, disposable, no definitions)
finance_orders_wide <- projects core; owner: finance-data
marketing_orders_wide <- projects core; owner: growth-analytics
ops_orders_wide <- projects core; owner: ops-analytics
RULE: serving reads CORE only. serving never reads serving.
RULE: a CASE that classifies a business entity belongs in CORE.go deeper
Know that several teams each building their own wide table leads to the same metric being computed differently in each, and that the shared definition should live in one upstream place.
Explain the split between a modelled core that owns definitions and generated serving tables that only project and join, and why the second must be reproducible from the first.
Show how you would operate it: lineage and usage telemetry, owners and declared grains per published mart, regeneration by partition, and a rule against mart-on-mart dependencies.
Own the tradeoff and the incentives — make the compliant path faster than forking, define the review test that distinguishes presentation from definition, and report duplicated definitions rather than table count.
## The failure mode One wide mart is a convenience. Fifteen wide marts, each built by the team that needed it, is a second warehouse — one with no shared vocabulary. The symptoms are recognisable: three tables that all claim to hold revenue, none agreeing; a definition change that must be applied in nine places and gets applied in six; nobody able to answer "which table should I use" without asking a person; and a full-history reload that nobody dares run because half the marts would move. The fragmentation is not caused by the width of the tables. It is caused by **business definitions being re-implemented per mart**. That is the thing to prohibit, and everything below follows from it. ## Why it happens It happens for good reasons, which is why banning wide marts outright fails. A team needs a join-free table for a tool that models one table well. The central model does not yet carry the attribute they need. The queue to change the shared dimension is three weeks and the dashboard is due Thursday. Each local decision is rational; the aggregate is a mess. Governance that ignores the pressure gets routed around. ## The organising rule **A wide table is a serving artifact, not the model of record.** State it as policy: - The **core** — facts at declared grains, shared dimensions, and the derived attributes and metric definitions that sit on them — is authoritative and owned centrally. - A **wide mart** is generated *from* the core. Its transform may filter, project, join many-to-one, and rename. It may not define. If a mart contains a `CASE` expression that classifies a business entity, that expression belongs upstream. - A wide mart is **disposable**: droppable and rebuildable from the core at any time, with nothing lost that is not reproducible. Anything a mart holds that cannot be re-derived is data the core is missing, and that is a gap to close, not a reason to keep the mart alive by hand. This rule is testable in review, which is why it works better than "please coordinate". The question is not "is this table too wide" but "does this table define anything?" ## The moves that make it hold **Make the fast path the compliant path.** If adding an attribute to a shared dimension takes three weeks and forking a mart takes an afternoon, teams fork. Cut the cost of contributing upstream — self-service pull requests against the core, a clear review SLA, ownership close to the domain — and most forking pressure disappears. **Generate rather than hand-write.** Wide marts that are produced from a declared list of dimensions and attributes, by one shared transform pattern, cannot drift the way fifteen bespoke scripts do. This is also what makes regeneration routine rather than an event. **Give every published mart an owner, a grain and a lifecycle.** A published table with no name attached to it never gets retired. Record the declared grain, the source core objects, the owner, and the intended audience. Retire on a schedule, with a deprecation window and usage telemetry to see who is still reading. **Track lineage and usage.** You need to answer two questions cheaply: which marts derive from this dimension (blast radius of a change), and who queried this mart last quarter (candidates for retirement). Without these, no consolidation ever happens because nobody can prove a table is dead. **Never let an ad-hoc mart become a source.** The most damaging pattern is mart-on-mart: someone builds a second wide table from the first, inheriting its frozen semantics and its bugs, and now the first cannot be changed. Marts read from the core; marts are not read by other marts. **Measure duplicated definitions, not table count.** Fifteen wide marts that all select `customer_segment` from one dimension is a healthy serving layer. Three that each compute it their own way is the problem. Report the second number to leadership; the first is noise. ## When per-team marts are genuinely fine Do not over-correct. Consumer-specific shaping is legitimate: a team may want its own column names, its own filters, a narrower date range, a nesting choice that suits its tool. Those are presentation decisions and they should be local — that is the whole point of a serving layer. The line is definition versus presentation. Rename freely; reclassify never. Similarly, a genuinely exploratory mart with a known expiry is fine, provided it is labelled as such and nothing downstream is allowed to depend on it. Problems begin when a scratch table quietly becomes load-bearing. ## What you say in the interview The short version: I would not fight the demand for wide tables — it is a real consumer need and the economics on a columnar engine support it. I would fight logic duplication. One modelled core owns grains, shared dimensions and definitions; wide marts are generated, owned, lineage-tracked, disposable projections of it; the review rule is that a mart may join and project but never define; and success is measured by how few places compute the same metric, not by how few tables exist.
- What is the concrete review test for whether a proposed wide mart is a fork?Read its transform. If it only filters, projects, renames and joins many-to-one against core objects, it is a projection and it is fine. If it contains a CASE expression that classifies a business entity, a hand-written revenue formula, or a join that invents a relationship the core does not model, it is a fork — and that logic belongs upstream where every other consumer can inherit it.
- How do you retire a wide mart that several dashboards still read?Prove usage first with query telemetry, then publish a replacement, announce a deprecation window, and help the largest consumers migrate rather than leaving them to discover the change. Keep the old table readable but frozen during the window so a missed consumer degrades into stale data rather than a broken dashboard, then drop it on the announced date.
- Why prohibit building one wide mart on top of another?Because the second inherits the first's frozen semantics, its bugs and its refresh lag, and it makes the first un-changeable — any fix now has downstream consumers nobody enumerated. Marts should read from the modelled core so that lineage stays one hop deep and the blast radius of a core change is enumerable.
The core model is the master copy of a document; wide marts are printouts formatted for different readers. Printing is fine — editing text on a printout and then photocopying that is how the versions stop matching.
saying these in an interview costs you the question
- Bans wide marts outright and expects teams to comply
- Counts tables instead of counting duplicated metric definitions
- Lets a team's ad-hoc mart become another mart's source
- Publishes wide marts with no owner, grain or retirement path
- Assumes a semantic tool alone fixes definitions forked into marts