'Layering: staging, intermediate, marts'
Layering: staging, intermediate, marts. Lezione sul design a strati dei modelli dbt.
Cosa imparerai
- Comprendere il problema analitico e il contesto decisionale
- Applicare esempi, metriche e controlli a casi reali
Collegamenti
Layering: staging, intermediate, marts
Un warehouse diventa fragile quando ogni query pulisce, unisce e interpreta i dati a modo suo. Layering: staging, intermediate, marts introduce una disciplina semplice: separare normalizzazione, logica riusabile e prodotti dati finali, così ogni passaggio ha un proprietario e un livello di astrazione.
Una scena da cui partire
Leggi la lezione come architettura della fiducia. Il layering non serve a moltiplicare file, ma a rendere visibile dove nasce un dato, dove viene arricchito e dove diventa metrica per il business.
- Contesto: Quale decisione rende utile il concetto?
- Metodo: Quale conflitto tra team o metriche devi anticipare?
- Applicazione: Quale frase useresti per spiegarlo in riunione?
Perché tre layer (e non due, e non quattro)
Il pattern a tre layer di dbt è emerso per convergenza nella community intorno al 2020, non per dogma ma per efficacia empirica. Ogni layer ha una responsabilità precisa e NON invade quella degli altri:
Layer 1 — Staging (stg_)
Responsabilità: leggere i dati grezzi e applicare minime trasformazioni di pulizia.
- 1:1 con le tabelle sorgente.
stg_stripe__paymentsriflette la tabellapaymentsdi Stripe, colonna per colonna. - Rinominare colonne per coerenza (es.
created→created_at,id→payment_id). - Cast dei tipi (es.
amount_cents→amount_eurdividendo per 100 e castando a numeric). - Flitri di righe tecnicamente invalide, mai filtri di business (es. rimuovi righe con
id IS NULL, ma NON filtrarestatus = 'live'— quello è business logic, va in intermediate).
Cosa NON fare in staging: JOIN, aggregazioni, CASE WHEN di business, subquery. Se stai unendo due tabelle in staging, stai sbagliando layer.
Layer 2 — Intermediate (int_)
Responsabilità: trasformazioni di business complesse. È il layer più importante e il meno capito.
- JOIN tra modelli staging per creare entità di business (es.
int_orders_with_customersuniscestg_shopify__ordersestg_shopify__customers). - Logica di business centralizzata:
CASE WHEN status = 'completed' AND refunded_at IS NULL THEN 'net_revenue' ELSE 0 ENDvive QUI, non nei marts e non nelle query ad-hoc. - Aggregazioni intermedie:
int_daily_revenue_by_countrypre-calcola metriche che servono a più marts. - Flag e segmentazioni:
is_new_customer,customer_lifecycle_stage,acquisition_cohort.
Regola: se una logica di business viene usata da più di un team, DEVE stare in intermediate. Non nei marts, non nelle query ad-hoc.
Layer 3 — Marts (mrt_ o nomi di dominio)
Responsabilità: dataset pronti per il consumo da parte di strumenti BI e analyst.
- Organizzati per dominio di business:
mrt_marketing__campaign_performance,mrt_product__feature_adoption,mrt_finance__monthly_pnl. - Query semplici: i marts fanno
SELECT * FROM int_...con al massimo un filtro finale o un’ultima aggregazione. - Denormalizzati per performance di lettura: il BI tool vuole una tabella piatta, non 5 join.
Se un mart contiene logica di business complessa (CASE WHEN annidati, subquery, window function), quella logica andava in intermediate.
L’errore più costoso: confondere il layer
L’errore classico è mettere la logica di business nei marts o (peggio) nelle query ad-hoc degli analyst. Questo crea il “shadow schema”: ogni analyst ha la propria versione della stessa logica, non testata e non documentata. Quando la logica cambia (es. nuova definizione di churn), va aggiornata in 15 posti invece che in uno.
Esempio concreto: definizione di “Monthly Active User” (MAU)
Versione senza layering: ogni team scrive la propria query.
-- Team Marketing
SELECT COUNT(DISTINCT user_id) WHERE last_login > CURRENT_DATE - 30
-- Team Product
SELECT COUNT(DISTINCT user_id) WHERE event_type = 'app_open' AND event_date > '2024-01-01'
-- Team Finance
SELECT COUNT(DISTINCT user_id) FROM subscriptions WHERE status = 'active'
Versione con layering:
-- Staging: stg_app__events — 1:1 con la tabella eventi grezza
-- Intermediate: int_user_activity_flags
SELECT user_id, event_date,
CASE WHEN event_date > CURRENT_DATE - 30 THEN 1 ELSE 0 END AS is_active_30d
-- Marts: mrt_metrics__mau
SELECT DATE_TRUNC('month', event_date) AS month,
COUNT(DISTINCT CASE WHEN is_active_30d = 1 THEN user_id END) AS mau
Caso reale: il refactoring di una media company
Una media company europea con 30M MAU aveva 200+ modelli dbt, tutti marts. La struttura piatta rendeva impossibile capire le dipendenze. Il team di analytics engineering (4 persone) eseguì un refactoring in tre fasi:
-
Mappatura delle dipendenze (1 settimana): usando
dbt docse il DAG, identificarono i modelli usati da più marts. -
Estrazione in intermediate (3 settimane): per ogni logica duplicata, crearono un modello intermediate e aggiornarono i marts a referenziarlo. Zero cambi funzionali, solo riorganizzazione.
-
Test e CI enforcement (1 settimana): aggiunsero test automatici su tutti i modelli intermediate + una regola CI che rifiutava PR con modelli marts che contenevano
CASE WHENdi business (doveva essere in intermediate).
Il costo totale fu di 5 settimane-uomo. Il beneficio, documentato internamente:
- Il tempo di onboarding per nuovi analyst scese da 8 settimane a 3
- Un cambiamento nella definizione di “utente attivo” (da 30 a 28 giorni) richiese 15 minuti e zero errori (prima: 3 giorni di lavoro di 5 persone, con bug)
- Il team finance scoprì di aver usato una definizione errata di MRR per 6 mesi (il modello intermediate rese evidente la discrepanza con Stripe)
Convenzioni di naming
La community dbt ha convergito su queste convenzioni, e adottarle ti fa risparmiare ore di discussione:
stg_[source]__[table_name] → stg_stripe__payments
int_[description] → int_daily_customer_revenue
mrt_[domain]__[description] → mrt_marketing__campaign_performance
Sempre plurale per le tabelle che rappresentano collezioni di entità (payments, users), singolare per entity dimension (date_spine, country_codes). Niente abbreviazioni criptiche: int_daily_cust_rev è ambiguo tra 3 mesi; int_daily_customer_revenue no.
Riferimenti:
- dbt Labs. (2024). “Best practice guides: How we structure our dbt projects.” dbt Developer Hub.
- Hughes, C. (2022). “The Three-Layer Model: Staging, Intermediate, Marts.” dbt Developer Blog.
- Kimball, R. & Ross, M. (2013). The Data Warehouse Toolkit, 3rd ed. Wiley.
Controllo di qualità
Prima di usare layering: staging, intermediate, marts in una decisione, controlla sempre completezza, duplicati, timezone, definizioni cambiate e segmenti esclusi. Molte analisi apparentemente sofisticate falliscono perché il dato di partenza misura un comportamento diverso da quello che il team crede di osservare.
Interpretazione per segmenti
La media aggregata è solo il punto di partenza. Segmenta per canale, coorte, piano, paese, device e maturità dell’utente. Se due segmenti si muovono in direzioni opposte, la media non rappresenta nessuno dei due e può portare a una decisione sbagliata.
Decisione operativa
Ogni analisi deve terminare con una scelta possibile: continuare, fermare, iterare, investire, rimuovere o approfondire. Se layering: staging, intermediate, marts non cambia una decisione, probabilmente manca ancora il collegamento tra metrica e azione.
Problema reale
Nel dominio di analytics engineering, ‘Layering: staging, intermediate, marts’ serve a risolvere questo problema: trasformare dati grezzi in modelli testati, documentati e riusabili dal business. La lezione non va trattata come teoria isolata, ma come un modo per migliorare una scelta concreta con dati, assunzioni esplicite e controlli minimi.
Obiettivo operativo: Comprendere il problema analitico e il contesto decisionale; Applicare esempi, metriche e controlli a casi reali. Se alla fine non sai indicare quale decisione cambia, quale dato osservi e quale errore vuoi evitare, la lezione non è ancora diventata competenza applicata.
Modello concettuale
| Fase | Cosa chiarire | Output |
|---|---|---|
| Domanda | Quale scelta reale deve migliorare? | Decisione da prendere |
| Misura | Quale segnale osservabile rappresenta il problema? | Metrica o dato sorgente |
| Controllo | Quale baseline rende il risultato interpretabile? | Confronto credibile |
| Azione | Che cosa cambia dopo l’analisi? | Prossimo passo operativo |
Il modello concettuale è intenzionalmente semplice: decisione, dato, controllo, azione. Ogni approfondimento tecnico deve rafforzare almeno uno di questi quattro punti.
Formalizzazione rigorosa
Per rendere ‘Layering: staging, intermediate, marts’ analizzabile, definisci prima l’unità di lavoro: source, model, test, mart, metrica o esposizione. Poi collega questa unità a una metrica osservabile: freshness, lineage, test coverage, costo modello e fiducia stakeholder. Infine dichiara la decisione attesa: modello dbt, semantic layer, contratto, test o pipeline di release.
| Elemento | Specifica richiesta |
|---|---|
| Unità di analisi | source, model, test, mart, metrica o esposizione |
| Segnale principale | freshness, lineage, test coverage, costo modello e fiducia stakeholder |
| Baseline | Periodo precedente, gruppo comparabile, benchmark o scenario controfattuale |
| Decisione | modello dbt, semantic layer, contratto, test o pipeline di release |
| Rischio | Scambiare un numero disponibile per una prova sufficiente |
La formalizzazione e solida quando un altro analista può riprodurre la logica, criticare le assunzioni e ottenere la stessa decisione partendo dagli stessi dati.
Esempio o caso studio
Una metrica di retention viene calcolata direttamente da eventi grezzi in tre dashboard diverse. Applicare layering significa spostare pulizia in staging, logica sessione in intermediate e la metrica finale in un mart, riducendo ambiguità e duplicazione.
| Evidenza osservata | Lettura prudente | Azione consigliata |
|---|---|---|
| Il numero migliora | Potrebbe essere effetto reale o variazione normale | Cercare confronto e segmento |
| Un segmento cambia più degli altri | La media aggregata nasconde una differenza | Separare coorti o casi d’uso |
| Il costo cresce insieme al risultato | L’impatto va letto sul margine | Stimare trade-off e sostenibilità |
Lab / esercizio
Livello base
Scrivi una scheda di una pagina per ‘Layering: staging, intermediate, marts’: decisione da supportare, metrica primaria, baseline, rischio principale e azione se il segnale e confermato.
Livello intermedio
Costruisci una tabella con tre segmenti, periodi o scenari. Per ciascuno indica cosa cambia, quale spiegazione alternativa e plausibile e quale controllo useresti prima di raccomandare un azione.
Livello research-grade
Prepara un decision memo: ipotesi, dati richiesti, criteri di esclusione, controlli di qualità, soglia decisionale, rischio residuo e piano di monitoraggio dopo la decisione.
Dataset e materiali consigliati
Usa dbt, warehouse, sorgenti CRM, eventi, marts, semantic layer e lineage. Se non hai accesso a dati reali, crea un dataset sintetico con almeno 200 righe, una dimensione temporale, una dimensione segmento e una metrica di outcome.
Errore tipico da evitare
L’errore più comune e usare ‘Layering: staging, intermediate, marts’ come etichetta invece che come processo. Succede quando il team mostra un grafico senza decisione, una metrica senza baseline, o una conclusione senza indicare quale assunzione potrebbe invalidarla.
La domanda di controllo è: se questo risultato fosse instabile, quale scelta sbaglierei? Se la risposta non è concreta, manca ancora il collegamento tra analisi e azione.
Quiz o checkpoint
- Quale decisione concreta dovrebbe migliorare questa lezione?
- Quale unità di analisi rende il problema misurabile?
- Quale baseline useresti per evitare una lettura ingenua?
- Quale errore tipico potrebbe cambiare la conclusione?
- Quale output consegneresti a uno stakeholder non tecnico?
Riepilogo operativo
‘Layering: staging, intermediate, marts’ diventa utile quando produce una decisione più chiara, non quando aggiunge terminologia. Usa il framework problema, modello, formalizzazione, esempio, lab e checkpoint per trasformare la lezione in pratica verificabile. Categoria: Decisione. Difficoltà: advanced. Tempo stimato: 18 min.
Percorso collegato
Lezioni da leggere insieme
Questi collegamenti portano la lezione dentro il resto del corso: basi da riprendere, passaggi successivi e connessioni tematiche tra moduli.