Quatre capacités couvrent la majorité des problèmes de qualité des données quel que soit le choix d’outillage, et toutes sont réalisables à coût de licence zéro avec les fonctionnalités natives de dbt et Elementary OSS. Ces capacités devraient être en place avant d’évaluer le paysage des outils, de comparer la détection ML vs statistique, ou de calculer le coût total de possession.
Capacité 1 : Tests de clé primaire et de clé étrangère
unique et not_null sur chaque clé primaire. relationships sur chaque clé étrangère. Ces tests capturent les pannes les plus courantes avec presque aucun effort de configuration.
models: - name: mrt__finance__payments columns: - name: payment_id data_tests: - unique - not_null - name: customer_id data_tests: - not_null - relationships: to: ref('mrt__core__customers') field: customer_id - name: order_id data_tests: - relationships: to: ref('mrt__sales__orders') field: order_idLes clés primaires dupliquées provoquent des explosions de jointures en aval — un seul customer_id dupliqué dans une table de dimension multiplie chaque jointure de table de faits, gonflant les métriques. Les clés étrangères orphelines produisent des NULLs dans les rapports qui sont difficiles à tracer. Appliquez les tests de clé primaire sans exception ; cinq minutes de configuration YAML par modèle évitent des heures de débogage en aval.
Pour les clés composites, utilisez dbt_utils.unique_combination_of_columns :
models: - name: int__daily__user_sessions data_tests: - dbt_utils.unique_combination_of_columns: combination_of_columns: - user_id - session_dateCapacité 2 : Monitoring de la fraîcheur des sources
Intégré dans dbt sans coût, la fraîcheur des sources capture le mode de défaillance le plus courant dans les pipelines de données : la non-arrivée des données.
sources: - name: raw_stripe freshness: warn_after: {count: 12, period: hour} error_after: {count: 24, period: hour} loaded_at_field: _loaded_at tables: - name: payments - name: customers - name: subscriptions
- name: raw_hubspot freshness: warn_after: {count: 6, period: hour} error_after: {count: 12, period: hour} loaded_at_field: _fivetran_synced tables: - name: contacts - name: deals - name: companiesExécutez dbt source freshness selon un planning (ou dans le cadre de votre pipeline dbt build). Quand le temps entre la valeur la plus récente de loaded_at_field et l’heure actuelle dépasse votre seuil, dbt déclenche un avertissement ou une erreur.
Définissez les seuils en fonction de votre cadence de mise à jour réelle, pas de valeurs par défaut arbitraires. Si les données Stripe se synchronisent toutes les heures, warn_after: 2 hours et error_after: 6 hours offre une marge pour les délais transitoires sans manquer les vraies pannes. Si HubSpot se synchronise toutes les 15 minutes, des seuils plus serrés sont appropriés.
L’erreur la plus courante est de configurer la fraîcheur des sources et de ne pas l’exécuter. Les vérifications de fraîcheur ne s’exécutent que lorsque vous appelez explicitement dbt source freshness — elles ne s’exécutent pas automatiquement dans le cadre de dbt run ou dbt test. Incluez-les dans votre orchestration.
Capacité 3 : Au moins un type de détection d’anomalies
Les anomalies de volume — des comptes de lignes inattendus — signalent les défaillances en amont avec une configuration minimale et offrent le meilleur rapport signal/bruit de tous les types de détection d’anomalies. Une table qui reçoit normalement 10 000 lignes par jour et qui en reçoit soudainement 200 indique presque toujours un vrai problème.
models: - name: mrt__core__orders tests: - elementary.volume_anomalies: time_bucket: period: day count: 1 anomaly_sensitivity: 3 training_period: period: day count: 14Pourquoi les anomalies de volume spécifiquement ? Parce qu’elles capturent le mode de défaillance que tous les autres types de tests manquent : les données qui ont arrêté d’arriver. Un test not_null réussit quand il n’y a aucune ligne à vérifier. Un test accepted_values réussit quand il n’y a aucune valeur à valider. Un test relationships réussit quand il n’y a aucune clé étrangère à rechercher. La détection d’anomalies de volume est le seul mécanisme qui remarque que « rien ne s’est passé » et le signale comme un problème.
Pour les équipes sur dbt natif sans Elementary, dbt_expectations.expect_table_row_count_to_be_between fournit une version plus simple :
models: - name: mrt__core__orders data_tests: - dbt_expectations.expect_table_row_count_to_be_between: min_value: 1000 max_value: 50000Le compromis est que les seuils statiques nécessitent des mises à jour manuelles à mesure que les volumes de données changent. L’approche Z-score d’Elementary s’adapte automatiquement. Mais un seuil statique qui détecte « la table est vide » est infiniment meilleur que pas de vérification de volume du tout.
Capacité 4 : Alertes dans un canal que votre équipe surveille réellement
Un test qui échoue silencieusement n’aide personne. Connectez les échecs à Slack ou à votre workflow d’incidents existant avant d’ajouter plus de tests.
Les résultats de tests qui restent dans les logs dbt jusqu’à ce qu’une partie prenante signale un problème de dashboard n’ont aucune valeur opérationnelle. La détection n’est utile que lorsqu’elle atteint quelqu’un qui peut agir dessus.
Pour Elementary OSS :
edr monitor --slack-token $SLACK_TOKEN --slack-channel-name data-alertsPour dbt Cloud, les alertes sont intégrées dans la plateforme. Pour dbt Core avec des orchestrateurs comme Dagster ou Airflow, configurez la notification en cas d’échec de test via l’alerting natif de l’orchestrateur.
La conception des alertes compte autant que leur existence :
Routez les alertes vers le bon canal. Un canal unique #data-alerts qui reçoit chaque échec de test de chaque domaine devient du bruit que tout le monde ignore. Routez les alertes de données financières vers l’équipe data finance, marketing vers le marketing.
models: your_project: marts: finance: +meta: channel: finance-data-alerts marketing: +meta: channel: marketing-data-alertsSupprimez les alertes répétées. Un échec persistant qui se déclenche toutes les heures crée de la fatigue d’alerte. Utilisez alert_suppression_interval d’Elementary pour consolider :
models: - name: mrt__finance__revenue meta: alert_suppression_interval: 24 # heuresIncluez un contexte actionnable. Une alerte qui dit « test échoué sur mrt__finance__revenue » nécessite une investigation pour comprendre l’impact. Une alerte qui inclut le propriétaire du modèle, la nature de l’échec et les modèles en aval affectés permet une réponse plus rapide.
Mettre l’ensemble en place
Une stack minimale viable complète pour un projet dbt :
# sources.yml - Capacité 2sources: - name: raw_stripe freshness: warn_after: {count: 12, period: hour} error_after: {count: 24, period: hour} loaded_at_field: _loaded_at tables: - name: payments - name: customers
# mrt__finance__payments.yml - Capacités 1, 3models: - name: mrt__finance__payments meta: owner: "@jessica.jones" channel: finance-data-alerts tests: - elementary.volume_anomalies: time_bucket: period: day count: 1 columns: - name: payment_id data_tests: - unique - not_null - name: customer_id data_tests: - not_null - relationships: to: ref('mrt__core__customers') field: customer_idCombiné avec edr monitor pour les alertes Slack (Capacité 4), cette configuration capture :
- Les données manquantes (fraîcheur)
- Les pannes structurelles (violations de clé primaire, enregistrements orphelins)
- Les défaillances silencieuses en amont (anomalies de volume)
- Et remonte tout cela dans un canal où quelqu’un agira
Cette configuration n’a aucun coût de licence et ne nécessite aucune évaluation de fournisseur. Elementary OSS plus les fonctionnalités natives de dbt couvre les quatre capacités.
Les seuils d’évolutivité indiquent quand investir au-delà de cette base. Le paysage des outils couvre dans quoi investir.