Skip to content
About
Main content

Scenarios

Longer problems, like those in senior system design interviews. A strong answer estimates with numbers first, names the mechanism, then recommends a fix and says what it costs.

Try each one before you open the answer.
1Two dashboards show Q3 revenue of $4.20M and $4.79M, and both pass all their data tests. How do you find the cause and prevent it?Show the answer

Mechanism first

Nothing can say which number is "true", so differences come from meaning, not code. The gap is 4.79 ÷ 4.20, about 14%.

Diagnose by the four primitives

  1. Grain: compare each source table's declared ; look for subtotal rows, or rows repeated once per campaign touch.
  2. Identity: do both dashboards count the same entity (orders, or customers)?
  3. Time: "as was" or "as is" versions, and which time zone.
  4. Boundary: are they reading different copies of the same attribute?

A fast test: reconcile row counts and distinct order numbers at the lowest grain both share, then bisect by month.

Fix

Declare the grain of every table, give each metric one owner in a , and run a daily job reconciling the two totals.

Trade-off and warning

Governance becomes a bottleneck. And an unexplained difference signals undefined meaning, not a bug to patch.

Read moreA layer with no oracleThe four primitivesTwo named trapsThe semantic layer

2Design the customer dimension for a retailer with 5 million customers, address changes, a loyalty tier that changes monthly, and a legal requirement to reproduce last year's reports exactly.Show the answer

The requirement drives the type

Reproducible reports need "as was" values for every attribute used in reports. Choose a type per attribute.

Per attribute

  • Email: type 1, overwrite; no history needed.
  • Region or territory: type 2, with a , effective dates and a current flag.
  • Loyalty tier: it changes monthly for everyone, so type 2 would add about . Use a (type 4) of the few tier-and-band combinations, referenced from the .

Late data

Look up versions by effective-date range, with a policy for and a check that they expire.

Keys

Surrogate keys. If loads must run in parallel, use a hash of (source, ), knowing it bakes in trust in the natural key.

Risks

Late corrections to the dimension rewrite history in proportion to the facts they touch; type 6 would make backfills proportional to versions; and nothing ever deletes old versions, so plan retention.

Read moreThe slowly changing dimension typesType 4: a mini-dimensionLate arrivals

3Finance wants each customer's balance for every day of the last 3 years, for 2 million accounts, answered in under a second. What do you build?Show the answer

Estimate

Choose

Balances are semi-additive , so a is the right fact type. Computing from events instead needs a running sum over each account's whole history, expensive per query but cheap to compute once. So precompute: one new day per night (about 2 million rows), stored in columnar form sorted by (account, date). Balances change rarely, so run-length encoding compresses it well.

Rules to enforce

Never sum across days; sum across accounts only within one date; for a period, use the last value or the average. A semantic layer should refuse to sum this measure over time.

Trade-offs

Storage grows with accounts × days, and late events force recomputing every later row from the date they change, so keep events as the source of truth.

Read morePeriodic snapshotSemi-additive measures

4Sales wants revenue by rep, but many large deals have two or three reps, and the total by rep exceeds the company's revenue. Fix it, and explain what is and is not correct afterwards.Show the answer

Diagnose

Joining facts to a many-to-many relationship : a $1,000 deal with two reps sums to $2,000.

Fix

A keyed by a rep-group key, with weights that sum to 1 within each group (for example 0.6 and 0.4). Revenue by rep = SUM(amount × weight), which adds up to company revenue.

What is correct

The sum over reps now equals the total, but each rep's share is only as right as the agreed policy, which no data can validate. Offer a second, clearly named "influenced revenue" measure, correct per rep but never to be summed.

Alternatives

An array of reps on each fact moves the trap to whenever it is unnested; a group key alone loses per-rep queries.

Governance

The needs an owner and a version, because changing it restates every historical rep number.

Read moreThe bridge table and the weighting factorTwo honest options and one dishonest oneTwo other escapes

5After an acquisition, three source systems hold overlapping customers with conflicting data, and compliance needs an audit trail of what each system said. Do you use Data Vault?Show the answer

Test the fit

The sources are many, contested and changing, and the auditor asks what each source said and when. That fits .

Design

Hubs of hashed business keys (source plus key), a link from customer to order, and a satellite per source with load timestamps and the record's source. Deterministic hashes make loading independent of order.

Do not skip the presentation layer

Build a or wide marts on top; the Vault is an addition, not a replacement. Use to link records across systems, and store each resolved person with their own surrogate key and version history, since a merge restates historical counts.

Costs

Complexity for readers, nothing that deletes old data (plan retention), and hashes that bake in trust in the business keys. With one source and one team, it is pure overhead. Whether cheap columnar compute makes the Vault a sensible default is still unsettled.

Read moreData VaultFour properties that followEntity resolution

6Marketing, finance and support each report a different number of 'active customers'. Propose a fix that survives growth to 40 teams.Show the answer

Diagnose

The metric is a computation with unstated edge cases (refunds, test accounts, time zone, partial periods), and each team re-derives it.

Fix

A semantic layer with one definition per metric name, an owner, and code review for changes, so meaning can be diffed. Different meanings get different names, such as engaged_customers. Count resolved people where possible.

Why it scales

With 40 teams, reconciling pairwise is ; shared definitions need 40 agreements.

Trade-offs

The layer is a query compiler, so predicate pushdown must work or performance suffers, and it becomes the bottleneck for disputes over definitions. A model only moves that cost into between domains.

Roll out

Start with the ten metrics executives use, publish them first, and retire shadow definitions with a deprecation date.

Read moreThe semantic layerThe honest costsWhy conformance is a coordination problem

7A pipeline bug corrupted revenue figures for 45 days, and the source keeps its files for only 30. How do you redesign so this becomes recoverable, and what will it cost?Show the answer

Principle

Materialize at the boundaries where reversibility and trust change. Parsing is mechanical, deduplication loses information, and business logic is opinionated.

Design

Three layers: raw (byte-for-byte, with arrival time), clean (parsed and deduplicated), and business (metrics). Publish guarantees at each boundary (schema, freshness, uniqueness, null policy, grain) and name an owner. A logic bug then means rerunning from the clean layer.

Costs

Roughly 3 times the storage, and latency that is the sum of the hops, for example 10 + 15 + 20 = 45 minutes.

The exception

If the upstream is an immutable log with long retention, the raw copy only adds retention depth and decoupling.

Recovering now

Ask the provider for a re-export, or rebuild from any copy of the business layer's inputs. Data that no longer exists anywhere cannot be recomputed. And layers without published guarantees are three copies with no safety.

Read moreMedallion layeringThree correctionsThe cost

8A product team wants to answer retention questions nobody has thought of yet. Should the whole platform be event-sourced?Show the answer

Weigh event sourcing

It keeps every future question open, since you can build new projections retroactively. But it costs snapshots (replay time keeps growing), event schemas that are permanent (versioned only by translating on read), no canonical current state, and handling of for corrections.

For analytics

An activity table, one row per activity per entity, makes temporal questions such as "second order within 7 days" into window queries, without moving the operational system to .

Recommend

Keep operational tables ordinary, feed an activity table from change events, and add a semantic layer: both event approaches push meaning into queries, which then get re-derived by every consumer.

Limits and a decision rule

An activity table handles set and allocation questions poorly, and needs engine support for as-of and interval joins. Decide by counting how many questions in the last six months needed history the current model could not provide.

Read moreEvent sourcingActivity schemaBoth push meaning into the query