Arhitectura datelor și a sistemelor, de la zero Lecția 36 / 80

Arhitectura medallion: bronze, silver, gold

Trei straturi de rafinare a datelor pentru un lakehouse. De ce fiecare echipă de date modernă folosește o variantă a acestei denumiri, chiar și când nu o numesc 'medallion'.

Suntem acum la mijlocul Modulului 5, modulul de batch. Lecțiile precedente au construit componentele: lake-ul, warehouse-ul, orchestratorul, formatele de fișier. Lecția asta face zoom out și pune o întrebare mai simplă. Odată ce ai toată mașinăria asta, cum organizezi datele care curg prin ea? Cum arată straturile și ce promite fiecare?

Cel mai răspândit răspuns în 2026 e o variantă de arhitectură medallion: datele curg prin trei straturi, fiecare mai curatoriat decât cel anterior, fiecare numit după un metal. Bronze, silver, gold. Denumirea e inventată de Databricks, iar marketingul o face să sune mai nouă decât e, dar tiparul în sine precedă numele cu decenii. Companiile mai vechi îl numeau „raw, staging, curated”, sau „L0, L1, L2”, sau „raw, clean, serving”. Disciplina e aceeași: straturi explicite cu responsabilități explicite și o normă fermă împotriva lăsării preocupărilor unui strat să se scurgă într-altul.

Lecția asta e plimbarea atentă prin ce conține de fapt fiecare strat, de ce sunt graniţele unde sunt și când acest model întreg e exagerat.

Tiparul

Trei straturi, în ordinea fluxului:

  • Bronze: fiecare eveniment, fiecare schimbare, fiecare record din fiecare sursă, stocat exact așa cum a sosit. Fără transformare. Fără deduplicare. Fără filtrare de calitate. Append-only și imutabil.
  • Silver: stratul curățat, conformat, joinable. Recordurile sunt deduplicate, tipurile sunt corecte, schemele sunt aplicate, recordurile rele sunt filtrate. Încă în formă de sursă (aproximativ un tabel silver per entitate de sursă), dar de încredere.
  • Gold: stratul gata pentru analiză. Tabele denormalizate, agregate, în formă de business și feature stores. Mart-urile pe care le citesc dashboard-urile BI, pipeline-urile ML și consumatorii downstream.

Datele curg într-o singură direcție, de la bronze spre gold. Fiecare strat e construit din stratul de dedesubt printr-un pipeline de transformare. Dacă găsești un bug în logica silver-spre-gold, rerulezi din silver. Dacă găsești un bug în logica bronze-spre-silver, rerulezi din bronze. Bronze însuși nu e niciodată re-derivat: e sistemul de înregistrare pentru ce a sosit, iar reluarea surselor upstream e de obicei scumpă sau imposibilă.

flowchart LR
    S[Sources: apps, APIs, databases, events]
    B[(Bronze: raw, immutable)]
    SI[(Silver: cleaned, conformed)]
    G[(Gold: business-aggregate, denormalised)]
    C[Consumers: BI, ML, exports]
    S --> B --> SI --> G --> C

Diagrama aceea e arhitectura întreagă. Părțile interesante sunt regulile care guvernează ce aparține fiecărei cutii.

Bronze: recordul nemodificat

Toată treaba stratului bronze e să păstreze, fidel și pentru totdeauna, datele care au intrat. Contractul e: „dacă te uiți la bronze, vezi exact ce ne-a trimis sursa, cu timestamp-uri pentru când am primit fiecare record”.

În practică asta înseamnă:

  • Append-only: tabelele bronze cresc. Rândurile existente nu sunt actualizate. Dacă un record se schimbă upstream, noua versiune sosește ca un rând nou, nu ca o actualizare a celui vechi.
  • Schema-on-read unde se poate: payload-ul sursei e stocat ca JSON sau ca tipurile native ale sursei, iar parsing-ul mai bogat e lăsat pentru silver. Motivul e că schemele de sursă derivă, iar bronze nu ar trebui să se strice când apare un câmp nou.
  • Stocare ieftină: bronze e cel mai mare dintre cele trei straturi și cel mai puțin frecvent interogat. Trăiește pe object storage (S3, GCS, ADLS) cu cel mai ieftin tier potrivit pentru acces ocazional. Compresia e mare.
  • Partiționat după timpul de ingest: tipic ingest_date=2026-01-16, uneori și după sursă. Partiționarea pe timp îți permite să raționezi despre ce a sosit când, și-ți permite să arunci sau să arhivezi partiții vechi curat.

Motivul pentru regula strictă „fără transformare” e replayability. Dacă logica silver-spre-gold are un bug care îți corupe dashboard-urile de trei luni, repari logica și rerulezi silver și gold din bronze, iar înapoi capeți cele trei luni corectate. Dacă bronze a transformat date în liniște, nu poți face asta: input-ul bug-ului s-a pierdut. Bronze e singurul strat care stochează istorie ce nu poate fi reconstruită, și de aceea trebuie să stocheze totul, chiar și recordurile pe care le suspectezi greșite.

Celălalt motiv e auditabilitatea. Când un regulator, o investigație de customer-support sau o revizuire de securitate întreabă „ce ne-a trimis de fapt sursa în dimineața zilei de 3”, bronze e răspunsul. Silver și gold nu sunt, pentru că au filtrat și remodelat deja datele.

Silver: stratul de încredere

Silver e stratul care zice „poți face join pe aceste tabele și să nu-ți faci griji”. Concret, asta înseamnă că s-au întâmplat câteva lucruri:

  • Deduplicare. Același record de sursă poate să fi sosit de două ori în bronze (din cauza livrării at-least-once, lecția 16). Silver colapsează duplicatele după cheie.
  • Type casting. Stringul "2026-01-16T12:00:00Z" devine timestamp. Stringul "42" devine integer. customer_id-ul din blob-ul JSON devine o coloană tipată.
  • Aplicarea schemei. Tabelele silver au o schemă declarată. Recordurile care nu se potrivesc sunt trimise într-un tabel de carantină pentru inspecție, nu eliminate în liniște.
  • Filtrare de calitate. Recordurile cu chei primare null, timestamp-uri imposibile sau valori în afara intervalelor agreate sunt eliminate și logate.
  • Conformare. Codurile de țară sunt normalizate la ISO-3166. Codurile de monedă sunt normalizate la ISO-4217. ID-urile de client din surse diferite sunt mapate la ID-ul canonic de client unde e posibil. Aceeași entitate de business referită în două moduri devine aceeași valoare în silver.

Silver e încă în mare parte în formă de sursă. Dacă sursele tale sunt un serviciu de orders și un serviciu de customers, încă ai un silver.orders și un silver.customers, încă nu un gold.customer_360 denormalizat. Forma se schimbă de la payload-uri brute la tabele curate, dar granițele entităților rămân aproximativ unde le-au pus sursele.

Silver e stratul pe care data scientists downstream și analiștii ad-hoc ar trebui să aibă voie să-l interogheze. Primesc tabele curate, joinable, cu coloane documentate și tipuri previzibile. Nu primesc surprizele bronze-ului (JSON brut, rânduri duplicate, drift de schemă) și încă nu au opiniile puternice ale gold-ului (o anumită agregare, un anumit grain, un anumit set de reguli de business coapte înăuntru).

Gold: forma de business

Gold e unde trăiește logica de business. Un tabel gold răspunde la o întrebare specifică pe care cineva din business o pune efectiv. „Câte comenzi am expediat săptămâna asta, pe regiune, pe categorie de produs?” „Care e lifetime value-ul fiecărui client, refresh-uit nocturn?” „Care e vectorul de feature pentru acest user, gata pentru modelul de recomandare?”

Tabelele gold sunt:

  • Denormalizate. Instinctul relațional (o entitate per tabel, joinuită la cerere) e greșit aici. Un tabel gold e un tabel lat per întrebare, joinuit și agregat în avans.
  • Agregate la grain-ul potrivit. Un tabel daily-orders-by-region e la un rând per (data, regiune), nu la un rând per comandă. Un tabel user-features e la un rând per user, cu orice agregate de fereastră glisantă are nevoie modelul.
  • Optimizate pentru tiparul de query. Partiționate, clustered, sortate pentru dashboard-urile sau modelele care le citesc. Dacă un dashboard va scana după event_date și va grupa după region, tabelul gold e partiționat după event_date și clustered după region.
  • Versionate și stabile contractual. Consumatorii downstream (unelte BI, pipeline-uri ML, exporturi) iau dependențe pe formele tabelelor gold, iar schimbarea acelor forme e o schimbare disruptivă. Tabelele gold primesc aceeași disciplină de stabilitate API ca API-urile publice.

De obicei nu există o singură schemă gold. În schimb există gold_finance, gold_marketing, gold_ml_features, fiecare deținută de echipa care o consumă, fiecare cu propriile tabele tunate la întrebările acelei echipe. Gold e plural.

De ce trei straturi, nu două sau patru

Ai putea să ai doar bronze și gold, și să sari peste mijloc. Oamenii o fac, în companii mici. Problema e că gold trebuie atunci să facă totul: curățare, conformare, deduplicare și agregare, totul într-o singură transformare. Pipeline-ul devine un încâlcit. Tabelele gold ale a două echipe refac aceeași muncă de curățare în feluri ușor diferite și sunt în liniște în dezacord. Un bug în pasul de curățare apare în unele tabele gold și nu în altele. Logica de curățare și logica de agregare sunt amestecate în același SQL, iar dezîncâlcirea lor mai târziu e dureroasă.

Silver rezolvă asta fiind suprafața partajată de curățare. Curățarea se întâmplă o dată, în silver, iar fiecare tabel gold construiește pe asta. Granița e răspunsul la „unde am încredere în date”. Contractul pe silver e „joinable și curat”, iar gold se poate baza pe asta fără să o refacă.

Ai putea avea de asemenea patru sau cinci straturi: o zonă de aterizare brută înainte de bronze, un strat „platinum” deasupra gold, un „feature store” separat paralel cu gold. Oamenii fac asta și poate funcționa. Costul e că mai multe straturi înseamnă mai multe locuri unde aceeași logică poate trăi în două dintre ele, și mai multe dezacorduri despre care strat deține care transformare. Trei e punctul dulce pentru majoritatea echipelor. Adaugi straturi când durerea de a nu le avea e reală, nu pentru că simetria diagramei e atrăgătoare.

Disciplina: nu lăsa straturile să se scurgă

Tiparul medallion e ușor de desenat și greu de impus. Cele două moduri de eșec pe care le văd cel mai des:

Logică de business care se strecoară în bronze. Cineva scrie un job de ingest care „curăță” formatul ciudat de timestamp al sursei pe drum, „pentru că e mai ușor aici”. Acum bronze nu mai e o înregistrare fidelă a ce a sosit. Șase luni mai târziu, când parser-ul de timestamp se dovedește că are un bug, stringurile originale au dispărut. Rezistă. Bronze e exponatul de muzeu: privește dar nu atinge.

Recorduri brute care se scurg în gold. Cuiva îi trebuie un dashboard rapid, interoghează direct din bronze și-l livrează. Acum există un consumator în formă de gold care citește dintr-un strat care nu a fost niciodată gândit să fie orientat spre consumator, fără garanții de calitate, cu drift de schemă care va strica în liniște dashboard-ul data viitoare când sursa se schimbă. Construiește o reprezentare silver a ce are nevoie dashboard-ul și pune-l să citească de acolo. Scurtătura se compune.

Disciplina e de obicei formatul de tabel lakehouse (Delta, Iceberg, Hudi) plus controlul de acces: doar pipeline-ul silver poate scrie în tabele silver, doar pipeline-ul gold poate scrie în tabele gold, iar bronze e read-only după ingest. Formatul și permisiunile impun ce diagrama doar sugerează.

Când să nu medallion-izezi

Medallion-ul e potrivit când ai un lake sau lakehouse real, surse multiple, consumatori multipli și o cantitate netrivială de date. Dacă nu, straturile sunt overhead care nu-ți cumpără nimic.

Cazuri în care un singur strat e de ajuns:

  • Seturi de date foarte mici. Dacă tot „warehouse-ul” tău e câteva sute de megabytes de date refresh-uite nocturn în Postgres, ai pur și simplu o schemă staging și o schemă prod. Stratul bronze adaugă cost de stocare și complexitate de pipeline pentru niciun beneficiu.
  • OLTP pur. Dacă nu ai deloc un lake, iar analiza ta constă într-un pumn de view-uri materializate peste baza de date tranzacțională, nu ai nevoie de medallion. Ai nevoie de view-uri bune.
  • Sisteme streaming-first. Pipeline-urile real-time, unde datele trebuie să curgă de la sursă la consumator în secunde, nu au timp pentru trei salturi batch. Arhitectura Kappa (Modulul 6, lecția 47) e o formă complet diferită: o sursă streaming a adevărului și materializări de pe ea. Medallion e forma batch; Kappa e forma streaming; arhitectura lambda e compromisul nefericit.

Declanșatorul pentru adoptarea medallion-ului e de obicei al doilea consumator. De îndată ce două echipe vor să interogheze aceleași date și una dintre ele face curățare pe care ar trebui s-o facă și cealaltă, ai problema în formă de silver. De îndată ce trei echipe vor agregări diferite ale acelorași date curate, ai problema în formă de gold. Construiește stratul care rezolvă durerea pe care o ai efectiv, nu pe cel pe care diagrama spune că ar trebui să-l ai.

Lecția următoare e despre formatele de tabel care fac toată această arhitectură posibilă la scară lakehouse: Delta Lake, Apache Iceberg și Apache Hudi.

Caută