skip to content

What are the signs that a medallion lakehouse has degraded into a data swamp?

level: seniorimportance: should knowfreq 42%

answer

  1. The names survived; the promises did not
  2. Ask what one row is — and watch the silence
  3. Count the near-identical copies of one table
  4. Who gets paged when it breaks?
  5. Query logs tell you what is actually read

basics

~20 s

Layers that add no guarantee: uncatalogued bronze nobody can interpret, silver tables with no declared grain or tests, chains of near-duplicate copies, business logic embedded in the landing layer, dashboards reading raw directly, and no owner for any of it.

solid answer

~50 s

The tell is that the layer names survive but the contracts do not. Symptoms in the order they usually appear: bronze becomes a dumping ground of undocumented tables nobody can interpret without asking the person who wrote the loader; silver tables declare no grain and have no tests, so duplicates leak into reports; teams that could not get changes made fork their own `_v2` and `_finance` copies, producing chains of near-identical tables where no one can say which is authoritative; business filters creep into bronze so the raw layer is no longer replayable; and dashboards start reading whichever layer is freshest. The root cause is almost always organisational — no owner per dataset, no review of what gets published, no cost of adding another copy. The remediation is unglamorous: catalogue what exists, name owners, declare and test grains, then delete duplicates rather than deprecating them.

code

text · 6 lines
text
silver_events_clean
  -> silver_events_clean_v2         (fix applied here; v1 still queried)
     -> silver_events_enriched_fin  (finance copy, one extra filter)
        -> gold_kpi_daily           (built partly on v1, partly on _fin)

no declared grain on any of them; no owner; three lineages, one metric

go deeper

for a junior

Recall that the layer names guarantee nothing on their own: a silver table with no stated grain and no tests is just another copy, and raw that nobody catalogued is unusable.

for a middle

Be able to describe the concrete symptoms — undeclared grains, duplicate near-identical models, business filters in ingestion, dashboards on raw — and say which layer's contract each one violates.

for a senior

Show a remediation sequence you would actually run: usage inventory from query logs, owners per dataset, grain tests on consumed tables, consolidation with deletion of duplicates rather than deprecation.

for a principal

Own the root cause, which is organisational: no accountable owners and a change process for shared models so slow that forking is rational. Fixing the process is what prevents the sprawl from regrowing.

## What "swamp" means here A data swamp is a store that holds a lot of data and yields few trustworthy answers. Medallion layering is a defence against it, but the layering is only a naming convention — apply the names without the guarantees and you get a swamp with three schemas instead of one. The signs are recognisable long before anyone says the word. ## Sign 1: bronze nobody can interpret Raw landing is supposed to be uninterpreted, but it must still be **catalogued**. The swamp version has hundreds of tables with no record of which source produced them, which pipeline still writes them, what the columns meant in the source system, or whether anything downstream depends on them. Nobody can delete anything because nobody can prove it is unused, and nobody can use anything because nobody can prove what it is. The fix is metadata, not cleaning: source, owner, load schedule, downstream dependents. ## Sign 2: layers with no declared grain A silver table that cannot answer "what is one row?" is a copy, not a layer. Its duplicates surface as inflated sums in reports weeks later, and each consumer patches around them differently — one uses `DISTINCT`, another a window function with a different tie-break, a third does not notice. When you find several downstream queries deduplicating the same table in different ways, the layer boundary has already failed. ## Sign 3: copy sprawl The signature shape: ``` silver_events_clean silver_events_clean_v2 (fix applied here; v1 still queried) silver_events_enriched_fin (finance's copy, one extra filter) gold_kpi_daily (built on which one? both, in places) ``` This grows when a team needs a change, cannot get it made in the shared model quickly, and forks. Each fork is individually reasonable and collectively fatal: the same metric now has three lineages and the meeting spends its first ten minutes reconciling numbers. The organisational cause — no ownership, no responsive change process for shared models — matters more than the technical one. ## Sign 4: business logic in bronze When someone filters out test accounts, excludes cancelled orders, or joins in a lookup during ingestion, the raw layer stops being raw. Now a reprocess cannot recover what was dropped, and the exclusion rule is invisible to everyone reading downstream tables. The rule of thumb holds: bronze is allowed to *add* provenance columns and nothing else. ## Sign 5: consumers reading whatever layer is convenient Dashboards on bronze, an executive report on an intermediate table, a reverse-ETL job on a staging model. Each of these makes an internal table a public interface without anyone deciding to publish it, so a routine refactor breaks a report and the platform team learns about it from an angry message. Layer discipline includes knowing which tables are consumable and enforcing it — a small set of published gold tables, everything else internal. ## Sign 6: layer sprawl in the other direction The opposite failure is more layers than there are guarantees to make: bronze, cleansed, standardised, conformed, enriched, curated, presentation. Every additional copy costs storage, adds pipeline latency, gives logic another place to hide and makes lineage harder to reason about — while adding nothing a consumer can name. If you cannot state the promise each layer adds, collapse it. ## Sign 7: no owner and no tests The common root. Nobody is paged when a table stops loading, nobody reviews what gets published, nobody bears the cost of adding another copy. Tests either do not exist or have been failing so long that failure is background noise. At that point layer names are decoration. ## Remediation, in the order that works Start with **inventory and usage**: what tables exist, who queries them, what still writes to them. Query logs answer this better than opinions do, and they usually reveal that a large fraction of tables have no readers at all. Then **name owners** per dataset — an unowned table cannot be fixed or retired. Then **declare and test grains** on the tables that actually have consumers, which converts the biggest copies back into contracts. Then **consolidate duplicates**: pick one definition, migrate readers, and *delete* the losers rather than leaving them as deprecated shims, because a shim is a table someone will query next quarter. Finally, close the loop that caused the forking: a change process for shared models that is fast enough that forking is not the rational choice. ## The uncomfortable part Most of this is not a modelling problem. The technical remedies — a catalogue, grain tests, fewer layers — are straightforward; what is hard is agreeing whose definition of revenue wins and who is accountable for the shared model. A candidate who names that honestly is describing the actual job.

  • How do you find out which tables are actually used before pruning?
    Read the query and access logs rather than asking teams — reported usage is systematically overstated. Attribute reads to consumers and jobs over a full business cycle so month-end and quarter-end workloads appear, then rank tables by distinct readers. In most degraded platforms a large share of tables have no readers at all.
  • Two teams disagree about which of their duplicate silver models is authoritative. How do you resolve it?
    Compare the artifacts, not the opinions: declared grain, deduplication rule, filters applied, and where the numbers diverge on a sample. Agree one definition with the business owner of the metric, make it the owned model with tests, migrate readers, then delete the other. Leaving it as a deprecated copy guarantees someone queries it later.
  • When is adding another layer genuinely justified rather than sprawl?
    When it adds a guarantee somebody is accountable for that no existing layer provides — resolved cross-source identity, a conformance step several marts share, or a published contract with a different owner and SLA. If you cannot state the new promise in one sentence, the layer is a copy with a nicer name.

A library where every book was shelved but nobody kept a catalogue: the shelves are labelled, the books are all there, and no one can find or trust anything.

saying these in an interview costs you the question

  • Believes naming schemas bronze/silver/gold is the architecture
  • Adds more layers to solve confusion caused by existing layers
  • Keeps duplicate models as deprecated shims instead of deleting them
  • Lets ingestion filter out rows it considers junk
  • Treats persistent failing tests as normal background noise

context