Data Engineering

Dagster : orchestrer ses pipelines data autour des assets

Pendant des années, l'orchestration de pipelines de données s'est résumée à enchaîner des tâches dans un ordre précis : extraire, transformer, charger, notifier. Cette logique fonctionne, mais elle laisse une question sans réponse : que produit réellement un pipeline ? Des tables, des fichiers, des modèles de machine learning, c'est-à-dire des données dont les équipes métier ont besoin. Savoir si une table est à jour, d'où elle vient et ce qui dépend d'elle est pourtant difficile quand l'orchestrateur ne raisonne qu'en tâches. C'est le problème que cherche à résoudre Dagster.

Équipe Blent

Publié le · 11 min de lecture

Dans cet article

Pendant des années, l'orchestration de pipelines de données s'est résumée à enchaîner des tâches dans un ordre précis : extraire, transformer, charger, notifier. Cette logique fonctionne, mais elle laisse une question sans réponse : que produit réellement un pipeline ? Des tables, des fichiers, des modèles de machine learning, c'est-à-dire des données dont les équipes métier ont besoin. Savoir si une table est à jour, d'où elle vient et ce qui dépend d'elle est pourtant difficile quand l'orchestrateur ne raisonne qu'en tâches. C'est le problème que cherche à résoudre Dagster.

Dagster est un orchestrateur open source, développé par Dagster Labs (anciennement Elementl) et conçu par Nick Schrock, l'un des créateurs de GraphQL chez Facebook. Il place la notion d'asset (un objet de données produit par du code) au centre de l'orchestration, là où Apache Airflow raisonne en DAGs de tâches. Dans cet article, nous allons explorer les concepts clés de Dagster, voir comment il s'intègre avec dbt, construire un pipeline complet, puis le comparer à Airflow et à Prefect.

Qu'est-ce que Dagster ?

Dagster est un orchestrateur de données écrit en Python, qui permet de définir, planifier, exécuter et observer des pipelines. Son idée directrice est de décrire non pas ce que le pipeline fait, mais ce qu'il produit. Chaque table, fichier ou modèle devient un software-defined asset : une fonction Python décorée qui déclare l'objet de données qu'elle fabrique et les assets dont elle dépend.

Logo Dagster

Cette approche déclarative change la manière de concevoir un pipeline. Au lieu de dessiner un graphe de tâches, on déclare un graphe d'assets, dont Dagster déduit l'ordre d'exécution. Elle apporte plusieurs bénéfices :

  • Lignage natif : les dépendances entre assets sont explicites, le graphe de lignage est donc construit automatiquement, sans outil complémentaire.
  • Observabilité centrée sur la donnée : l'interface indique, pour chaque asset, sa dernière matérialisation, ses métadonnées et l'état de ses contrôles qualité.
  • Développement local : un asset reste une fonction Python, testable comme n'importe quel code.
  • Reprise ciblée : on peut relancer un asset et ses descendants plutôt qu'un pipeline entier.

Dagster est utilisé par des entreprises comme Bayer, Vanta ou encore Mapbox, et existe en deux déclinaisons : le projet open source, auto-hébergeable, et Dagster+, l'offre managée qui ajoute notamment le déploiement hébergé, les alertes et la gestion des accès. Un projet se lance avec pip install dagster dagster-webserver, puis l'interface s'ouvre en local avec la commande dagster dev. Les versions récentes proposent aussi une CLI dédiée, dg, qui permet de scaffolder un projet et de lister ou valider ses définitions.

Les concepts clés de Dagster

Pour tirer parti de Dagster, il faut comprendre les briques qui structurent un projet.

Assets et dépendances

Un asset se définit avec le décorateur @dg.asset. Les dépendances se déduisent des paramètres de la fonction : si un asset prend en argument le nom d'un autre asset, Dagster comprend qu'il en dépend et lui transmet sa valeur.

python
import dagster as dg
import pandas as pd

@dg.asset
def raw_orders() -> pd.DataFrame:
    """Charge les commandes brutes depuis la source."""
    return pd.read_csv("data/orders.csv")

@dg.asset
def clean_orders(raw_orders: pd.DataFrame) -> pd.DataFrame:
    """Supprime les doublons et les montants négatifs."""
    df = raw_orders.drop_duplicates(subset="order_id")
    return df[df["amount"] > 0]

@dg.asset
def revenue_by_country(clean_orders: pd.DataFrame) -> pd.DataFrame:
    """Calcule le chiffre d'affaires par pays."""
    return clean_orders.groupby("country", as_index=False)["amount"].sum()

Ces trois fonctions forment un graphe : raw_orders alimente clean_orders, qui alimente revenue_by_country. L'exécution d'un asset s'appelle une matérialisation, et chaque matérialisation est historisée avec ses métadonnées. Le stockage des valeurs (fichier, base de données, bucket) est délégué à un IO manager, ce qui sépare la logique métier de l'infrastructure.

Resources, jobs, schedules et sensors

Les autres briques servent à configurer et à déclencher l'exécution :

  • Resources : objets de configuration réutilisables, comme une connexion à un data warehouse ou une clé d'API, injectés dans les assets et remplaçables par des mocks en test.
  • Jobs : sélection d'assets à matérialiser ensemble, par exemple tous ceux d'un domaine métier.
  • Schedules : déclenchement d'un job selon une expression cron.
  • Sensors : déclenchement en réaction à un événement, comme l'arrivée d'un fichier ou la matérialisation d'un autre asset.
python
import dagster as dg

# Job regroupant les assets du domaine ventes
sales_job = dg.define_asset_job(
    name="sales_job",
    selection=dg.AssetSelection.assets("raw_orders", "clean_orders", "revenue_by_country"),
)

# Exécution tous les jours à 6h
daily_schedule = dg.ScheduleDefinition(job=sales_job, cron_schedule="0 6 * * *")

# Déclenchement dès qu'un nouveau fichier est déposé
@dg.sensor(job=sales_job)
def new_file_sensor(context: dg.SensorEvaluationContext):
    import os
    if os.path.exists("data/orders.csv"):
        mtime = os.path.getmtime("data/orders.csv")
        yield dg.RunRequest(run_key=str(mtime))

Le run_key du sensor évite de lancer deux fois le même run pour un même fichier : tant que la date de modification ne change pas, aucune nouvelle exécution n'est créée. Tous ces éléments sont ensuite regroupés dans un objet dg.Definitions, point d'entrée unique que Dagster charge pour construire le projet.

Partitions et asset checks

Les partitions découpent un asset en tranches, le plus souvent temporelles. Elles permettent de traiter un jour de données à la fois, de relancer uniquement une tranche en échec ou de faire un backfill de l'historique depuis l'interface.

python
import dagster as dg

daily = dg.DailyPartitionsDefinition(start_date="2026-01-01")

@dg.asset(partitions_def=daily)
def daily_events(context: dg.AssetExecutionContext) -> None:
    """Charge les événements du jour correspondant à la partition."""
    day = context.partition_key  # ex. "2026-03-14"
    context.log.info(f"Chargement des événements du {day}")

Les asset checks ajoutent des contrôles qualité attachés à un asset, visibles directement dans l'interface à côté de son état de fraîcheur. Ils jouent un rôle proche des data contracts : vérifier qu'une donnée respecte les attentes avant que ses consommateurs ne l'utilisent.

python
@dg.asset_check(asset=clean_orders)
def no_null_order_id(clean_orders: pd.DataFrame) -> dg.AssetCheckResult:
    """Vérifie qu'aucune commande n'est sans identifiant."""
    nulls = int(clean_orders["order_id"].isna().sum())
    return dg.AssetCheckResult(passed=nulls == 0, metadata={"null_count": nulls})

À lire : découvrez notre formation Data Engineer

Intégration native avec dbt

L'un des points forts de Dagster est son intégration avec dbt, portée par le package dagster-dbt. Plutôt que de lancer dbt comme une commande opaque, Dagster importe chaque modèle dbt en tant qu'asset. Le graphe de dépendances dbt (les fonctions ref() et source()) est lu depuis le fichier manifest.json et fusionné avec les assets Python.

python
from pathlib import Path
import dagster as dg
from dagster_dbt import DbtCliResource, DbtProject, dbt_assets

# Projet dbt situé à côté du code Dagster
dbt_project = DbtProject(project_dir=Path(__file__).parent / "dbt_project")
dbt_project.prepare_if_dev()

@dbt_assets(manifest=dbt_project.manifest_path)
def dbt_models(context: dg.AssetExecutionContext, dbt: DbtCliResource):
    """Exécute `dbt build` et remonte chaque modèle comme asset."""
    yield from dbt.cli(["build"], context=context).stream()

Le résultat est un graphe unifié : un asset Python qui charge les données brutes alimente directement les modèles dbt staging, puis marts, puis un asset de machine learning situé en aval. Les tests dbt remontent comme des asset checks, et les équipes d'analytics engineering gardent leur workflow SQL habituel tout en profitant de l'orchestration, des partitions et de l'observabilité de Dagster.

Cette intégration répond à une limite fréquente des déploiements dbt : l'absence de visibilité sur ce qui se passe avant et après la transformation. Avec Dagster, le même graphe relie l'ingestion, la transformation SQL et les usages en aval.

Observabilité et lignage intégrés

Dans Dagster, l'observabilité n'est pas un module à brancher après coup : elle découle du modèle d'assets. L'interface web, appelée Dagster UI, expose un catalogue d'assets où l'on consulte pour chacun sa description, son propriétaire, son historique de matérialisations et ses métadonnées (nombre de lignes, aperçu, durée).

Le lignage des données est visible sous forme de graphe interactif, au niveau de l'asset et non de la tâche. En cas d'incident, on identifie rapidement les assets en amont qui ont échoué et ceux en aval qui sont impactés. Les politiques de fraîcheur et les conditions d'automatisation permettent par ailleurs de déclarer qu'un asset doit être à jour dans un délai donné, ou qu'il doit se recalculer dès que ses parents changent, sans écrire de cron pour chaque pipeline.

Les métadonnées s'enrichissent depuis le code avec context.add_output_metadata ou en retournant un objet dg.MaterializeResult, ce qui permet de suivre des indicateurs métier (volume traité, taux de valeurs manquantes) directement dans l'interface.

Dagster face à Airflow et Prefect

Dagster, Airflow et Prefect couvrent le même besoin mais reposent sur des philosophies différentes. Le tableau suivant résume les différences principales.

CritèreDagsterAirflowPrefect
Unité centraleAsset (donnée produite)Tâche dans un DAGFlow et tâches Python
LignageNatif, au niveau des assetsLimité, via des datasetsLimité
Intégration dbtModèles importés comme assetsVia opérateurs ou CosmosVia intégration dédiée
Tests locauxSimples, assets = fonctionsPlus lourdsSimples, flows = fonctions
Maturité et écosystèmeRécent, en croissanceTrès large, référence historiqueRécent, en croissance

Airflow reste l'outil le plus répandu, avec un écosystème de providers très large et une grande base d'ingénieurs qui le connaissent. Il convient bien aux organisations dont les pipelines existants sont nombreux et stables, même si ses versions récentes ont introduit la notion d'assets pour se rapprocher de ce modèle. Prefect privilégie la simplicité : on transforme du code Python en workflow avec quelques décorateurs, sans imposer de modèle de données.

Dagster se distingue lorsque le pipeline sert surtout à produire des données consommées par d'autres équipes. Son modèle demande un petit effort initial de conception (penser en assets plutôt qu'en tâches), mais il apporte en échange le lignage, le catalogue et les contrôles qualité dans un seul outil. Dans la pratique, le choix dépend moins des fonctionnalités que de la culture de l'équipe : une équipe très orientée code applicatif sera à l'aise avec Prefect, une équipe qui gère un parc de pipelines hérités restera sur Airflow, et une équipe data orientée produit de données trouvera dans Dagster un cadre naturel.

À découvrir : notre formation Data Engineer

Exemple de pipeline complet

Assemblons les éléments précédents dans un projet cohérent. Le point d'entrée regroupe assets, job, schedule, sensor et resources dans un seul objet Definitions :

python
import dagster as dg
from dagster_dbt import DbtCliResource

defs = dg.Definitions(
    assets=[raw_orders, clean_orders, revenue_by_country, dbt_models],
    asset_checks=[no_null_order_id],
    jobs=[sales_job],
    schedules=[daily_schedule],
    sensors=[new_file_sensor],
    resources={"dbt": DbtCliResource(project_dir="dbt_project")},
)

La mise en route suit ensuite un cycle court :

bash
# Valider les définitions du projet
dg check defs

# Lancer l'interface locale sur http://localhost:3000
dg dev

# Matérialiser tous les assets depuis la CLI
dg launch --assets "*"

Dans l'interface, le graphe affiche les assets Python et les modèles dbt dans un même schéma. On peut matérialiser un sous-ensemble, consulter les résultats des checks, puis activer le schedule et le sensor pour passer en exploitation. En production, le projet se déploie généralement dans un conteneur, sur Kubernetes ou via Dagster+, avec les mêmes définitions que celles utilisées en local.

Pour les équipes qui partent de zéro, une bonne pratique consiste à démarrer avec quelques assets critiques, à leur ajouter des checks dès le départ, puis à étendre progressivement le graphe, en y intégrant les modèles dbt et les sources externes (par exemple un entrepôt comme Snowflake).

À découvrir : notre formation Analytics Engineer

Conclusion

Dagster propose une manière différente de penser l'orchestration : au lieu d'enchaîner des tâches, on déclare les données que l'on veut produire et leurs dépendances. Cette approche par software-defined assets donne au lignage, à l'observabilité et aux contrôles qualité une place native, là où les orchestrateurs classiques demandent d'assembler plusieurs outils.

Ses concepts (assets, jobs, schedules, sensors, partitions) forment un ensemble cohérent, et son intégration avec dbt en fait un choix naturel pour les équipes qui combinent ingestion Python et transformations SQL. Face à Airflow et à Prefect, il ne s'impose pas partout, mais il apporte un vrai avantage lorsque les pipelines alimentent des produits de données partagés.

Pour un Data Engineer ou un Analytics Engineer, comprendre ce modèle centré sur les assets est une compétence différenciante : même si l'on reste sur un autre orchestrateur, cette logique influence déjà l'évolution des outils du marché et la façon de concevoir des plateformes data fiables et observables.

Pour aller plus loin

D'autres articles Data Engineering

Approfondir le sujet

Formation Data Engineering

Apprenez à concevoir des pipelines robustes, du stockage à la mise à disposition.

  • Spark
  • Airflow
  • Data warehouse
  • Streaming