Medallion Architectuur

Het precieze contract per laag, hoe bronze/silver/gold zich vertaalt naar dbt's staging/intermediate/marts-structuur, materialization- en teststrategie per laag, streaming binnen medallion, en hoe je een verwijderverzoek door een immutable bronze-laag heen verwerkt.

12 min leestijd Gemiddeld Bijgewerkt: 2026-08-14 Data Transformation

Introductie

Bronze, silver en gold zijn inmiddels in bijna elk hoofdstuk van dit handbook voorbijgekomen — als de laag waar ruwe data landt, als de plek waar deduplicatie gebeurt, als het patroon achter de case study in Modern Data Platform Architecture. Dit hoofdstuk herhaalt die basisdefinities niet, maar gaat een niveau dieper: wat mag er precies in elke laag gebeuren en wat nooit, hoe vertaalt dit patroon zich naar een concrete dbt-projectstructuur en materialization-strategie, hoe test je elke laag anders, en hoe verwerk je een AVG-verwijderverzoek door een laag heen die per ontwerp onveranderlijk hoort te zijn?

Het Contract per Laag: Wat Hoort Waar

De definities "ruw", "schoon" en "business-klaar" zijn een startpunt, maar te vaag om als engineeringrichtlijn te dienen. Een preciezer contract, geformuleerd als wat wel en niet is toegestaan:

Bronze — toegestaan: ongewijzigd opslaan van brondata, technische metadata toevoegen (_ingested_at, _source_system), append-only schrijven. Nooit toegestaan: rijen filteren op basis van businesslogica, waarden transformeren of casten, rijen updaten of verwijderen (behalve voor het uitzonderingsgeval van wettelijk verplichte verwijdering, zie verderop). Zodra iemand in een bronze-transformatie een WHERE-clausule op business-logica tegenkomt (WHERE status != 'test'), is dat een teken dat die logica in silver hoort.

Silver — toegestaan: deduplicatie, type-casting, het combineren van meerdere bronnen tot één betrouwbare representatie per entiteit, basale validatie (rijen met een ontbrekende primary key verwijderen of quarantaine plaatsen), kolomniveau-maskering van gevoelige velden. Nooit toegestaan: business-specifieke aggregaties of KPI-berekeningen — silver blijft op transactie-/entiteitsniveau, niet op rapportageniveau.

Gold — toegestaan: aggregaties, joins tussen meerdere silver-entiteiten, herberekening naar de exacte vorm die een dashboard of downstream-systeem nodig heeft — inclusief de fact/dimension-structuren uit Star Schema & Dimensional Modeling. Nooit toegestaan: rechtstreeks lezen uit bronze, ook niet als "snelkoppeling" voor een dringende rapportagevraag — elke gold-tabel bouwt voort op silver, zodat datakwaliteitsregels uit silver gegarandeerd worden toegepast voordat data gold bereikt.

Implementatie: Schema's, Catalogen en Lakehouse-zones

Dit contract is techniek-agnostisch, maar de fysieke implementatie verschilt per platform.

Op Snowflake wordt dit meestal uitgedrukt als aparte schema's binnen één database (raw.orders, staging.orders, analytics.orders) of, bij sterkere isolatie-eisen, aparte databases per laag met specifieke rolgebaseerde toegang per database. Op Databricks wordt dit typisch vertaald naar Unity Catalog-catalogi of -schema's (bronze.orders, silver.orders, gold.orders), vaak gekoppeld aan fysiek gescheiden opslaglocaties in de onderliggende cloud storage. Op Microsoft Fabric verschijnt dit als aparte Lakehouses of als mappenstructuur binnen één Lakehouse (Bronze/orders, Silver/orders, Gold/orders), met OneLake als onderliggende gedeelde opslaglaag.

In alle drie de gevallen geldt hetzelfde onderliggende principe: toegangscontrole volgt de laag, niet de tabel. Het data-engineeringteam krijgt schrijftoegang tot bronze en silver; analisten krijgen alleen leestoegang tot gold — een directe toepassing van de governance-principes uit Modern Data Platform Architecture, nu concreet vertaald naar namespace-ontwerp.

dbt-projectstructuur: Staging, Intermediate, Marts

Wie een dbt-project opzet, ontdekt al snel dat dbt zijn eigen naamgevingsconventie hanteert — staging, intermediate, marts — die niet toevallig één-op-één overeenkomt met bronze/silver/gold, maar er wel een specifieke extra nuance aan toevoegt:

models/
├── staging/           # 1 model per bron-tabel, minimale transformatie
│   ├── stg_orders.sql       # hernoemen, casten — nog dicht bij bronze
│   └── stg_customers.sql
├── intermediate/       # combineren van meerdere staging-modellen
│   └── int_orders_enriched.sql   # dit is waar silver echt silver wordt
└── marts/              # business-klare, vaak per domein gegroepeerd
    ├── finance/
    │   └── fct_revenue.sql
    └── sales/
        └── dim_customer.sql

staging is dun bronze-naar-silver-vertaalwerk: kolommen hernoemen naar een consistente conventie, types casten, verder niets — bewust minimalistisch, zodat elk staging-model maximaal overzichtelijk blijft en één-op-één een bron-tabel volgt. intermediate is waar de echte silver-logica zit: deduplicatie, het combineren van meerdere staging-modellen, validatie. marts is gold: per business-domein georganiseerd, vaak in de fact/dimension-vorm uit het star schema-hoofdstuk. Deze indeling is dbt's eigen conventie (zie de dbt Labs-structuurgids) en niet verplicht, maar wordt inmiddels breed genoeg gebruikt dat het als de facto standaard binnen dbt-projecten geldt, naast medallion architecture als de facto standaard op platformniveau.

Materialization-strategie per Laag

Een veelgemaakte, kostbare misvatting is elke laag op dezelfde manier materialiseren. In de praktijk verschilt de optimale keuze sterk per laag:

  • Bronze/staging — meestal een view, of bij grotere volumes een incremental table. Omdat staging-modellen zo dun zijn (alleen hernoemen/casten), is het materialiseren als view vaak goedkoop genoeg en bespaart het onnodige opslag van een bijna-identieke kopie van bronze.
  • Silver/intermediate — meestal een table, of bij groeiende historie een incremental table met een duidelijke unique key — dit is waar de zwaardere deduplicatie- en combinatielogica zit, die je niet bij elke downstream-query opnieuw wilt laten berekenen.
  • Gold/marts — bijna altijd een table, soms incremental voor zeer grote fact tables. Dit zijn de tabellen die BI-tools rechtstreeks bevragen; ze moeten voorspelbaar snel zijn, wat een view (die de onderliggende query elke keer herberekent) zelden kan garanderen.
# dbt_project.yml — materialization-strategie per laag, per folder
models:
  my_project:
    staging:
      +materialized: view
    intermediate:
      +materialized: table
    marts:
      +materialized: table
      finance:
        +materialized: incremental
        +unique_key: order_id
Genereer deze structuur direct

Laat de dbt Generator een staging-, intermediate- of mart-model met de juiste materialization en tests opzetten.

Open dbt Generator

Testing Strategy per Laag

Net als materialization verschilt ook wat je test fundamenteel per laag — een teststrategie die "overal dezelfde tests" toepast, verspilt compute op tests die in die specifieke laag niets betekenisvols opleveren.

Bronze — test vooral aanwezigheid en versheid: is de verwachte data daadwerkelijk geland, en niet ouder dan verwacht? Inhoudelijke tests (uniciteit, referentiële integriteit) zijn hier grotendeels zinloos — bronze bevat per definitie nog rommel, dat is precies waarom de laag bestaat.

Silver — test structurele correctheid: not_null op verplichte velden, unique op de entiteits-sleutel, relationships-tests die refereren naar andere silver-tabellen. Dit is de laag waar Data Quality & Testing het zwaarst wordt toegepast, omdat dit de laatste plek is voordat data zich vermengt in complexere gold-berekeningen.

Gold — test business-logica-correctheid: komt de som van de regels overeen met het totaal, telt een KPI op tot een bekend controlegetal, wijkt een dag-op-dag-verandering niet onverklaarbaar sterk af? Dit zijn vaak custom, domeinspecifieke tests in plaats van dbt's generieke ingebouwde tests.

# schema.yml — teststrategie geconcentreerd per laag
models:
  - name: stg_orders          # bronze/staging: alleen versheid
    tests:
      - dbt_utils.recency:
          datepart: hour
          field: _ingested_at
          interval: 26

  - name: int_orders_enriched  # silver/intermediate: structuur
    columns:
      - name: order_id
        tests: [not_null, unique]
      - name: customer_id
        tests:
          - relationships:
              to: ref('int_customers')
              field: customer_id

  - name: fct_revenue          # gold/marts: business-logica
    tests:
      - dbt_utils.expression_is_true:
          expression: "total_revenue >= 0"

Streaming Data binnen Medallion Architecture

Het patroon is ontworpen met batch in gedachten, maar werkt met aanpassingen ook voor streaming-bronnen (zie de batch-versus-streaming-afweging uit Introduction to Data Engineering). Bronze wordt dan een continu appendende tabel die events opslaat zoals ze binnenkomen — via Kafka, Kinesis, of Databricks' Auto Loader — zonder enige transformatie, precies zoals bij batch. Silver draait dan als een micro-batch- of streaming-job die continu of elke paar minuten dedupliceert en valideert (Spark Structured Streaming en Snowflake's Dynamic Tables zijn hier twee platformspecifieke implementaties van). Gold blijft meestal periodiek — de meeste dashboards hebben geen sub-minuut-verse aggregaties nodig, zelfs als de onderliggende bronze/silver-lagen wel continu bijwerken, wat opnieuw de "kies batch tenzij een concrete eis anders vereist"-vuistregel uit hoofdstuk 1 bevestigt.

Backfills en het Recht op Vergetelheid

Een technisch probleem dat nog niet aan bod kwam: als bronze per ontwerp onveranderlijk is, hoe verwerk je dan een AVG-verwijderverzoek van een klant die vraagt om al zijn data te laten wissen? De ruwe, onveranderlijke bronze-laag lijkt dit principieel tegen te spreken.

De gangbare oplossing is een van twee patronen. Tombstoning voegt een verwijderingsmarkering toe (een nieuwe bronze-rij die aangeeft "dit record is verwijderd op moment X") in plaats van de bestaande rij te wijzigen — bronze blijft technisch append-only, maar silver-transformaties respecteren de tombstone en sluiten het record uit van elke laag erna. Crypto-shredding is grondiger: persoonsgegevens worden bij het schrijven naar bronze versleuteld met een unieke sleutel per klant; een verwijderverzoek vernietigt simpelweg die sleutel, waarna de versleutelde data in bronze voor altijd onleesbaar blijft zonder dat de rij zelf ooit fysiek is gewijzigd — technisch nog steeds "append-only", functioneel onherstelbaar gewist. Voor de meeste organisaties is crypto-shredding de robuustere aanpak specifiek omdat het geen enkele uitzondering op de immutability-regel van bronze vereist.

Wanneer Drie Lagen Niet Genoeg Zijn

Sommige teams introduceren een vierde laag, vaak "platinum" genoemd, voor sterk verrijkte of ML-feature-klare data die verder gaat dan een standaard gold-aggregatie — bijvoorbeeld voorberekende features voor een aanbevelingsmodel die zowel zware berekening als domeinspecifieke feature-engineering vereisen. Dit is geen teken dat het medallion-patroon tekortschiet, maar een natuurlijke uitbreiding ervan: dezelfde scheiding van verantwoordelijkheden, één laag verder doorgevoerd voor een specifiek gebruiksdoel. Voer dit alleen in wanneer een concrete behoefte (zoals ML-featurestores) dat rechtvaardigt — drie lagen dekken de overgrote meerderheid van platforms afdoende, en een ongebruikte vierde laag is vooral extra onderhoud zonder voordeel.

Lineage Zichtbaar Maken over de Lagen Heen

Een vraag die zodra een platform groter wordt onvermijdelijk opduikt: "welke bronze-tabellen voeden uiteindelijk dit ene getal in het directiedashboard?" Zonder expliciete lineage is dit archeologie — het handmatig terugvolgen van elke join en elke ref() door tientallen modellen. dbt lost dit grotendeels automatisch op: omdat elk model zijn afhankelijkheden expliciet declareert via ref() in plaats van hardcoded tabelnamen, kan dbt de volledige dependency-graph genereren en visualiseren (dbt docs generate), van elke gold-tabel helemaal terug tot de bronze-bron. Op Databricks vervult Unity Catalog een vergelijkbare rol, automatisch afgeleid uit daadwerkelijk uitgevoerde queries in plaats van uit projectconfiguratie.

Dit is niet alleen handig voor debugging — het is een directe governance-vereiste zodra een organisatie moet kunnen aantonen waar een gerapporteerd cijfer vandaan komt (relevant voor financiële audits, en direct gekoppeld aan de lineage-verplichtingen uit Data Governance). Een praktische vuistregel: als je niet binnen enkele minuten met tooling — niet met tribale kennis van één senior engineer — kunt aantonen welke bronze-tabellen een specifieke gold-metric voeden, ontbreekt er een stuk volwassenheid in hoe de medallion-lagen zijn gedocumenteerd, ongeacht hoe correct de onderliggende SQL is.

Best Practices

  • Handhaaf het contract per laag strikt, ook onder tijdsdruk — een "snelle" businessregel die stiekem in staging sluipt, ondermijnt de herbouwbaarheid die de hele reden is om lagen te scheiden.
  • Materialiseer bewust per laag (view voor dunne staging, table voor silver/gold), niet uniform — zie de materialization-tabel hierboven.
  • Concentreer teststypes per laag: versheid in bronze, structuur in silver, business-logica in gold — in plaats van overal dezelfde generieke tests toe te passen.
  • Kies crypto-shredding boven tombstoning voor persoonsgegevens waar mogelijk, omdat het geen uitzondering op bronze's immutability vereist.
  • Voer een vierde laag alleen in bij een concrete, benoembare behoefte (zoals ML-featurestores), niet omdat "meer lagen netter klinkt".
  • Genereer en publiceer lineage-documentatie als onderdeel van de CI/CD-pipeline (bijvoorbeeld dbt docs generate bij elke deploy), zodat lineage nooit veroudert ten opzichte van de daadwerkelijke modelstructuur.

Veelgemaakte Fouten

  • Businesslogica die in bronze sluipt, meestal als "tijdelijke" oplossing voor een dringende deadline die nooit meer wordt teruggedraaid — waardoor bronze zijn functie als betrouwbaar vangnet verliest.
  • Elke laag hetzelfde materialiseren (bijvoorbeeld alles als table), wat onnodige opslag- en compute-kosten oplevert voor dunne staging-modellen die prima als view kunnen draaien.
  • Generieke tests overal toepassen in plaats van teststrategie te concentreren op wat elke laag daadwerkelijk moet garanderen.
  • Persoonsgegevens direct in bronze laten staan zonder verwijderstrategie, tot het moment dat het eerste AVG-verzoek binnenkomt en er geen ontworpen mechanisme is om het af te handelen.
  • Rechtstreeks vanuit gold-modellen naar bronze verwijzen "voor een extra kolom die nog niet in silver zit" — een sluipweg die de datakwaliteitsgaranties van silver omzeilt.

Performance Tips

  • Gebruik incrementele materialisatie in silver en gold zodra tabellen groeien — volledige herberekening bij elke run wordt onbetaalbaar naarmate historie opbouwt, zoals eerder beargumenteerd in Introduction to Data Engineering.
  • Beperk het aantal kolommen dat door elke laag stroomt tot wat daadwerkelijk nodig is verderop — een brede bronze-tabel hoeft niet elke kolom één-op-één door te geven aan silver als downstream niets ermee doet.
  • Plan silver-transformaties niet vaker dan nodig — als gold toch maar eens per uur ververst, heeft een silver-laag die elke vijf minuten herberekent geen enkel voordeel, alleen extra compute-kosten.
  • Monitor de laadtijd per laag apart — een trage bronze-naar-silver-stap wijst op een ander probleem (deduplicatielogica, ontbrekende clustering) dan een trage silver-naar-gold-stap (vaak join- of aggregatiecomplexiteit).

Interviewvragen

"Wat mag wel en niet in de bronze-laag gebeuren?" Let op: alleen ongewijzigd opslaan plus technische metadata; nooit businesslogica, filtering op inhoud, of updates/verwijderingen (behalve via een expliciet ontworpen mechanisme zoals tombstoning).

"Hoe vertaalt bronze/silver/gold zich naar een dbt-projectstructuur?" Let op: staging (dun, dicht bij bronze), intermediate (silver — deduplicatie, combinatie), marts (gold — business-klaar, vaak per domein) — en het besef dat deze indeling dbt's eigen conventie is, niet een verplicht onderdeel van medallion architecture zelf.

"Waarom zou je bronze als view materialiseren maar gold als table?" Let op: staging-modellen zijn dun genoeg dat herberekenen bij elke query goedkoop is; gold-tabellen worden vaak en direct door BI-tools bevraagd en moeten voorspelbaar snel zijn, wat een gematerialiseerde tabel garandeert en een view niet.

"Hoe verwerk je een AVG-verwijderverzoek als bronze onveranderlijk hoort te zijn?" Let op: tombstoning (een verwijdermarkering toevoegen die latere lagen respecteren) of crypto-shredding (versleutelde opslag waarvan de sleutel wordt vernietigd) — beide zonder de append-only-garantie van bronze te breken.

"Hoe pas je medallion architecture toe op een streaming-bron?" Let op: bronze als continu appendende ruwe stream, silver als (micro-)batch-deduplicatie, gold meestal nog steeds periodiek — niet elke laag hoeft even vers te zijn als de bron zelf binnenkomt.

"Wanneer zou je een vierde laag (platinum) toevoegen aan medallion architecture?" Let op: alleen bij een concrete behoefte zoals ML-featurestores die verder gaan dan standaard business-aggregaties — niet standaard, en het besef dat drie lagen de meerderheid van platforms afdoende dekken.

Relevante Documentatie

Samenvatting

Medallion architecture is meer dan drie namen voor drie mate van "schoonheid" — het is een strikt contract over wat elke laag wel en niet mag doen, met directe consequenties voor hoe je namespaces inricht, hoe je materialiseert, en hoe je test. dbt's eigen staging/intermediate/marts-conventie vertaalt dit contract naar een concrete projectstructuur; materialization- en teststrategie horen per laag te verschillen, niet uniform te zijn. Het patroon werkt met aanpassingen ook voor streaming-bronnen, en zelfs het ogenschijnlijk tegenstrijdige probleem van AVG-verwijdering in een onveranderlijke bronze-laag heeft ontworpen oplossingen (tombstoning, crypto-shredding) die de kernprincipes intact laten. Met dit fundament — modellering, transformatiepatronen, en nu de architectuur die ze samenbrengt — is het tijd voor het volgende hoofdstuk: dbt zelf, het gereedschap waarmee de meeste van deze patronen in de praktijk worden gebouwd.

Hulp nodig bij het bouwen van een modern dataplatform?

DataPartner365 helpt organisaties met Microsoft Fabric, Snowflake, Databricks, dbt, Azure, data-architectuur en CI/CD.

Neem contact op met DataPartner365