🧠 Contexte
Tu déclares une source dans dbt (par exemple : une table dans ton data warehouse), et tu veux surveiller si elle est fraîche, c’est-à-dire :
- qu’elle a bien été mise à jour récemment
- qu’elle respecte une fréquence d’alimentation attendue
Mais parfois, une même source est alimentée par plusieurs pipelines différents :
| Exemple de table source | Processus de chargement | Fréquence |
|---|---|---|
raw.transactions | ingestion par API temps réel | toutes les 15 minutes |
| batch de consolidation backend | 1 fois par heure |
🎯 Problème : une seule définition freshness standard ne suffit pas
Si tu fais simplement :
freshness:
error_after: { count: 30, period: minute }
warn_after: { count: 15, period: minute }
→ Tu appliques une règle unique à une source potentiellement multi-origine. Tu risques :
- soit de déclencher des alertes inutiles,
- soit de ne pas détecter le vrai problème (ex : si la partie “batch” est en retard mais que les données arrivent toujours côté API).
✅ Solution : plusieurs blocs freshness avec critères différents
dbt permet de configurer plusieurs règles de fraîcheur (avec condition), dans une même source, pour mieux refléter la réalité métier.
⚠️ Attention : dbt ne supporte pas nativement plusieurs blocs freshness par source, mais tu peux contourner cela intelligemment en :
- créant plusieurs tables
sourcelogiques qui pointent vers la même table physique - ou en utilisant une macro customisée pour la validation conditionnelle selon l’heure, la partition ou l’environnement
🔧 Exemple 1 : définir deux sources logiques pour la même table physique
version: 2
sources:
- name: app_sources
schema: raw
tables:
- name: transactions_api
identifier: transactions
freshness:
warn_after: { count: 15, period: minute }
error_after: { count: 30, period: minute }
loaded_at_field: updated_at
meta:
origin: api
- name: transactions_batch
identifier: transactions
freshness:
warn_after: { count: 1, period: hour }
error_after: { count: 2, period: hour }
loaded_at_field: updated_at
meta:
origin: batch
➡️ Tu déclares deux entrées source, mais elles pointent vers la même table transactions dans le warehouse.
🧪 Tu peux ensuite surveiller chaque “flux” :
dbt source freshness --select source:app_sources.transactions_api
dbt source freshness --select source:app_sources.transactions_batch
🧩 Exemple 2 : logique conditionnelle dans une macro
Si tu veux une logique dépendante de l’heure (ex : tolérance plus large la nuit), tu peux créer un test personnalisé ou une macro :
{% macro validate_transactions_freshness(source_name, max_delay_minutes) %}
{% set now = modules.datetime.datetime.now() %}
{% set allowed_delay = modules.datetime.timedelta(minutes=max_delay_minutes) %}
{% set freshness = ... %} {# lire le MAX(updated_at) #}
{% if now - freshness > allowed_delay %}
{{ exceptions.raise_compiler_error("Freshness check failed for " ~ source_name) }}
{% endif %}
{% endmacro %}
Et tu appelles cette macro via un dbt run-operation.
✅ Avantages de cette stratégie
| Bénéfice | Détail |
|---|---|
| 🎯 Suivi précis de chaque flux de chargement | Tu sais si l’API ou le batch est en retard |
| 🧩 Une seule définition source réutilisable | Tu gardes la maintenance facile |
| 🔁 Flexibilité horaire ou métier | Tu peux adapter la règle à l’heure, au type, à l’env… |
| 🛑 Moins de fausses alertes | Chaque flux a sa propre tolérance de délai |
🧠 Résumé
| Élément | Explication |
|---|---|
freshness: | Permet de vérifier si une table source est à jour |
| Cas multi-flux | Tu dois surveiller chaque logique de chargement individuellement |
| Solution 1 | Déclarer plusieurs entrées source avec identifier commun |
| Solution 2 | Utiliser une macro conditionnelle ou personnalisée |
| Avantage | Monitoring plus fin, détection plus fiable des incidents |