Apache Airflow en 2026 : orchestration de pipelines, DAG et questions d'entretien
Maîtriser Apache Airflow 3.2 avec ce tutoriel pratique : écriture de DAG avec le Task SDK, patterns d'orchestration de pipelines, partitions d'assets et vraies questions d'entretien pour les postes de data engineering en 2026.

Apache Airflow 3.2 constitue l'évolution la plus marquante de la plateforme d'orchestration open source depuis la refonte architecturale de la version 3.0. Avec plus de 10 millions de téléchargements mensuels sur PyPI et une adoption dans des entreprises allant d'Airbnb à Spotify, Airflow reste l'outil de référence pour construire, planifier et superviser des pipelines de données. Ce tutoriel couvre l'écriture de DAG avec le nouveau Task SDK, les patterns d'orchestration de pipelines et les questions d'entretien qui reviennent sur les postes de data engineering.
Airflow 3.2, publié en avril 2026, introduit les partitions d'assets pour une planification data-aware granulaire, le support natif de l'asynchrone dans le PythonOperator, et les déploiements multi-équipes. Tous les imports de DAG passent désormais par le namespace stable airflow.sdk introduit avec Airflow 3.0.
Écriture de DAG avec le Task SDK d'Airflow
Airflow 3.0 a introduit le Task SDK, un package autonome qui découple les définitions de DAG des composants internes d'Airflow. L'objectif : écrire des DAG portables et stables d'une version à l'autre, capables de survivre aux mises à jour d'Airflow sans modification de code. Tous les objets centraux — DAG, dag, task, BaseOperator, Connection, Variable — résident maintenant sous airflow.sdk.
Les anciens chemins d'import (airflow.decorators.task, airflow.models.dag.DAG) fonctionnent toujours dans la 3.2 mais sont marqués comme dépréciés et seront retirés dans une version future.
# etl_daily_revenue.py
import pendulum
from airflow.sdk import dag, task
@dag(
schedule="@daily",
start_date=pendulum.datetime(2026, 1, 1, tz="UTC"),
catchup=False,
tags=["finance", "etl"],
)
def etl_daily_revenue():
@task()
def extract_transactions() -> list[dict]:
# Pulls raw transactions from the payments API
import requests
response = requests.get("https://api.internal/payments/daily")
return response.json()["transactions"]
@task(multiple_outputs=True)
def transform(transactions: list[dict]) -> dict:
# Aggregates by currency and computes totals
totals = {}
for tx in transactions:
currency = tx["currency"]
totals[currency] = totals.get(currency, 0) + tx["amount"]
return {"totals": totals, "count": len(transactions)}
@task()
def load(totals: dict, count: int):
# Inserts aggregated row into the warehouse
from warehouse import insert_revenue_summary
insert_revenue_summary(totals=totals, transaction_count=count)
raw = extract_transactions()
result = transform(raw)
load(result["totals"], result["count"])
etl_daily_revenue()Le décorateur @dag remplace le gestionnaire de contexte traditionnel with DAG(...). Le décorateur @task transforme de simples fonctions Python en tâches Airflow, avec une sérialisation XCom prise en charge automatiquement. L'appel à transform(raw) déclare une dépendance — Airflow construit les arêtes du DAG à partir du graphe d'appels de fonctions.
Mapping dynamique de tâches pour des charges variables
Les DAG statiques échouent dès que le nombre d'éléments à traiter change d'une exécution à l'autre. Le mapping dynamique de tâches, stable depuis Airflow 2.4 et affiné dans la branche 3.x, résout ce problème en générant les tâches à l'exécution via .expand().
# etl_multi_region.py
import pendulum
from airflow.sdk import dag, task
@dag(
schedule="@hourly",
start_date=pendulum.datetime(2026, 1, 1, tz="UTC"),
catchup=False,
tags=["regional", "etl"],
)
def etl_multi_region():
@task()
def get_regions() -> list[str]:
# Returns the active regions from config
return ["us-east-1", "eu-west-1", "ap-southeast-1"]
@task()
def process_region(region: str) -> dict:
# Processes events for a single region
from data_processor import aggregate_events
return aggregate_events(region)
@task()
def merge_results(results: list[dict]):
# Combines all regional outputs into a single report
from reporter import publish_global_report
publish_global_report(results)
regions = get_regions()
# .expand() creates one mapped task instance per region
processed = process_region.expand(region=regions)
merge_results(processed)
etl_multi_region()À l'exécution, Airflow crée trois instances parallèles de process_region — une par région. Si une quatrième région apparaît demain, aucune modification du code du DAG n'est nécessaire. La tâche merge_results attend que toutes les instances mappées se terminent avant de s'exécuter.
Par défaut, Airflow plafonne les tâches mappées à 1024 instances par mapping. Cette limite se modifie avec max_map_length dans la configuration du DAG lors du traitement de jeux de données plus volumineux.
Partitions d'assets : planification data-aware dans Airflow 3.2
Avant Airflow 3.2, la planification data-aware opérait au niveau de l'asset : lorsqu'un DAG producteur mettait à jour un asset, tous les DAG consommateurs se déclenchaient, quelle que soit la tranche de données modifiée. Les partitions d'assets corrigent ce comportement en permettant une granularité au niveau de la partition.
Prenons un scénario où trois DAG en amont produisent des statistiques de joueurs horaires pour différentes ligues sportives. Un DAG analytique en aval ne devrait se déclencher que lorsque les trois ligues ont publié leurs données pour la même heure.
# downstream_analytics.py
import pendulum
from airflow.sdk import dag, task
from airflow.timetables.assets import CronPartitionTimetable
# Define partitioned assets with hourly granularity
nba_stats = Asset("s3://datalake/nba/hourly/", partitions=CronPartitionTimetable("0 * * * *"))
epl_stats = Asset("s3://datalake/epl/hourly/", partitions=CronPartitionTimetable("0 * * * *"))
nfl_stats = Asset("s3://datalake/nfl/hourly/", partitions=CronPartitionTimetable("0 * * * *"))
@dag(
# Triggers only when all three assets have matching partition
schedule=(nba_stats & epl_stats & nfl_stats),
start_date=pendulum.datetime(2026, 1, 1, tz="UTC"),
catchup=False,
)
def unified_sports_analytics():
@task()
def aggregate_all_leagues(**context):
partition = context["partition"]
# Process only the specific hourly slice across all leagues
from analytics import build_cross_league_report
build_cross_league_report(partition=partition)
aggregate_all_leagues()
unified_sports_analytics()La planification partitionnée élimine les exécutions de pipeline redondantes. Le DAG en aval ne se déclenche que lorsque la partition exacte dont il a besoin est disponible sur toutes les sources en amont — ni avant, ni sur des données partielles.
Prêt à réussir tes entretiens Data Engineering ?
Entraîne-toi avec nos simulateurs interactifs, fiches express et tests techniques.
Tâches asynchrones natives pour les charges intensives en E/S
Airflow 3.2 ajoute le support natif de l'asynchrone dans le PythonOperator. Auparavant, exécuter des opérations d'E/S concurrentes (des milliers d'appels d'API, des téléchargements de fichiers par lots) imposait d'écrire des opérateurs deferrable personnalisés. Désormais, il suffit de passer directement une fonction async.
# async_file_download.py
import asyncio
import aiohttp
from airflow.sdk import dag, task
import pendulum
@dag(
schedule="@daily",
start_date=pendulum.datetime(2026, 1, 1, tz="UTC"),
catchup=False,
tags=["async", "download"],
)
def async_file_download():
@task()
async def download_files():
urls = [f"https://data.source/files/{i}.csv" for i in range(500)]
async with aiohttp.ClientSession() as session:
# Downloads 500 files concurrently instead of sequentially
tasks = [fetch_and_save(session, url) for url in urls]
results = await asyncio.gather(*tasks)
return {"downloaded": len(results)}
download_files()
async def fetch_and_save(session: aiohttp.ClientSession, url: str):
async with session.get(url) as resp:
content = await resp.read()
filename = url.split("/")[-1]
with open(f"/data/downloads/{filename}", "wb") as f:
f.write(content)
return filename
async_file_download()L'approche asynchrone télécharge 500 fichiers en parallèle via un seul slot de worker, contre 500 appels HTTP séquentiels dans la version synchrone. Pour les charges limitées par les E/S, cela se traduit par des gains de vitesse d'un ordre de grandeur sans provisionner de workers supplémentaires.
Architecture d'Airflow : composants et flux d'exécution
Comprendre l'architecture d'Airflow est indispensable à la fois pour l'exploiter en production et pour répondre aux questions d'entretien. Cinq composants interagissent lors de chaque exécution de DAG :
- Scheduler — Parse les fichiers de DAG, résout les dépendances et place les tâches en file d'attente. Dans Airflow 3.x, le scheduler fonctionne de façon stateless face à la base de métadonnées.
- Executor — Détermine où les tâches s'exécutent.
LocalExecutorgère les installations sur une seule machine.CeleryExecutorrépartit la charge sur des nœuds workers.KubernetesExecutorlance un pod par tâche. - Workers — Exécutent le code réel des tâches. Avec la nouvelle Task Execution API d'Airflow 3.0, les workers communiquent via un contrat stable, ce qui autorise l'exécution dans des conteneurs, des environnements edge ou des runtimes externes.
- Base de métadonnées — PostgreSQL (recommandé) ou MySQL. Stocke les définitions de DAG, les états des tâches, les valeurs XCom, les identifiants de connexion et les journaux d'audit.
- Serveur web — L'interface d'Airflow pour superviser les exécutions de DAG, inspecter les logs, déclencher des exécutions manuelles et gérer les connexions.
À éviter en production : SequentialExecutor, qui exécute une seule tâche à la fois et n'existe que pour le développement. Pour les environnements Kubernetes-natifs, KubernetesExecutor offre l'isolation la plus forte puisque chaque tâche dispose de son propre pod avec des ressources et des dépendances indépendantes.
Airflow vs Prefect vs Dagster en 2026
Airflow affronte deux alternatives sérieuses. Le bon choix dépend de la taille de l'équipe, de l'infrastructure existante et des types de pipelines à construire.
| Caractéristique | Airflow 3.2 | Prefect 3.x | Dagster 1.9 |
|---|---|---|---|
| Définition de DAG | Décorateurs Python (airflow.sdk) | Décorateurs Python (@flow, @task) | Décorateurs Python (@asset, @op) |
| Planification | Cron, asset-aware, partition-aware | Cron, événementielle | Cron, basée sur sensors, asset-aware |
| Modèle d'exécution | Scheduler centralisé + workers distribués | Hybride (serveur + work pools) | dagster-daemon centralisé |
| Tâches dynamiques | Tâches mappées via .expand() | Boucles Python natives | Partitions dynamiques |
| Support asynchrone | Natif en 3.2 | Natif depuis la 2.0 | Opérations d'E/S asynchrones |
| Isolation multi-équipes | Intégrée (expérimentale en 3.2) | Basée sur les workspaces (Cloud) | Branch deployments |
| Taille de la communauté | La plus large (35k+ étoiles GitHub) | En croissance (18k+ étoiles) | En croissance (12k+ étoiles) |
| Cas d'usage idéal | Pipelines complexes, multi-équipes, infrastructure établie | Petites équipes recherchant une itération rapide | Organisations centrées sur les assets de données |
L'avantage d'Airflow réside dans son écosystème : plus de 80 packages de providers couvrant chaque service cloud, base de données et API majeurs. Prefect excelle sur l'expérience développeur avec moins de code répétitif. Le modèle asset-centric de Dagster convient aux équipes qui raisonnent en termes de produits de données plutôt qu'en séquences de tâches.
Questions d'entretien : Apache Airflow pour data engineers
Les questions suivantes reflètent ce que les responsables du recrutement et les ingénieurs seniors posent lors des entretiens de data engineering dans les entreprises qui exploitent Airflow en production.
Qu'est-ce qu'un DAG, et comment Airflow l'utilise-t-il ?
Un DAG (Directed Acyclic Graph) définit un workflow comme une collection de tâches reliées par des dépendances, garantie sans référence circulaire. Airflow parse les fichiers Python du dossier dags/, construit le graphe de dépendances, et le scheduler détermine l'ordre d'exécution. Chaque exécution de DAG crée un objet DagRun rattaché à une date logique. La contrainte « acyclique » garantit que le scheduler peut toujours trouver un ordre d'exécution valide — la tâche A s'exécute avant la tâche B, jamais l'inverse simultanément.
Comment fonctionne XCom, et quand faut-il l'éviter ?
XCom (cross-communication) transmet de petites quantités de données entre tâches. Une tâche pousse une valeur de retour vers XCom ; les tâches en aval la récupèrent. Le Task SDK s'en charge automatiquement lors du passage des valeurs de retour entre tâches décorées. XCom stocke les données dans la base de métadonnées par défaut, ce qui le rend inadapté aux gros jeux de données (au-delà de quelques Ko). Pour transférer de grandes données, il faut recourir à un stockage externe (S3, GCS) et ne faire transiter que le chemin de référence par XCom.
Expliquez la différence entre schedule, start_date et catchup.
Le paramètre schedule (renommé depuis schedule_interval dans Airflow 3.x) définit la fréquence d'exécution du DAG : une chaîne cron, un timedelta, un objet timetable ou un déclencheur d'asset. start_date fixe la date logique la plus ancienne pour laquelle une exécution de DAG peut être créée. catchup=True (valeur par défaut) crée des exécutions de DAG pour tous les intervalles manqués entre start_date et l'instant présent. Fixer catchup=False indique au scheduler d'ignorer les intervalles passés et de ne planifier qu'à partir de l'heure courante. Un pattern de production courant : catchup=False pour les DAG opérationnels et catchup=True pour les backfills historiques.
En quoi le KubernetesExecutor diffère-t-il du CeleryExecutor ?
CeleryExecutor maintient un pool de processus workers longue durée reliés par un broker de messages (Redis ou RabbitMQ). Les tâches sont mises en file et s'exécutent sur les workers disponibles. KubernetesExecutor crée un nouveau pod Kubernetes pour chaque tâche, en utilisant l'image Docker et les besoins en ressources de la tâche. Celery offre une latence plus faible (pas de surcoût de démarrage de pod) et convient bien aux charges homogènes. KubernetesExecutor procure une isolation plus forte, un contrôle des ressources par tâche, et supprime le besoin de gérer un pool de workers statique — idéal pour les charges hétérogènes où les tâches ont des dépendances et des besoins mémoire différents.
Quelles stratégies existent pour gérer les échecs de tâches ?
Airflow propose plusieurs mécanismes de gestion des échecs. retries et retry_delay configurent les tentatives automatiques avec backoff exponentiel. on_failure_callback déclenche une logique personnalisée (alertes Slack, incidents PagerDuty) lorsqu'une tâche échoue. trigger_rule contrôle la réaction des tâches en aval — all_success (par défaut), one_success, all_failed ou none_failed_min_one_success. Pour les problèmes d'infrastructure transitoires, le paramètre retry_exponential_backoff=True augmente le temps d'attente entre les tentatives. Les SLA (devenus Deadline Alerts en 3.x) surveillent la durée d'exécution et déclenchent des callbacks lorsque les tâches dépassent le temps d'exécution attendu.
Bonnes pratiques de production pour les déploiements Airflow
Faire tourner Airflow de façon fiable à grande échelle exige de l'attention sur plusieurs patterns opérationnels qui vont au-delà de l'écriture de DAG corrects.
Tâches idempotentes. Chaque tâche devrait produire le même résultat lorsqu'elle est exécutée plusieurs fois avec les mêmes entrées. Utiliser INSERT ... ON CONFLICT ou MERGE plutôt qu'un simple INSERT. Partitionner les données de sortie par date logique. Cela garantit des tentatives et des backfills sûrs, sans duplication de données.
DAG petits et ciblés. Mieux vaut résister à la tentation de construire des DAG monolithiques comportant des dizaines de tâches. Découper les pipelines complexes en plusieurs DAG reliés par des assets (anciennement datasets). Des DAG plus petits se parsent plus vite, sont plus faciles à déboguer et autorisent le redémarrage partiel d'un pipeline.
Gestion des connexions. Stocker tous les identifiants dans le gestionnaire de connexions d'Airflow ou dans un backend de secrets externe (AWS Secrets Manager, HashiCorp Vault). Ne jamais coder en dur les identifiants dans les fichiers de DAG. Airflow 3.x chiffre les champs de connexion au repos dans la base de métadonnées.
Supervision et alerting. Exporter les métriques d'Airflow vers Prometheus ou StatsD. Suivre scheduler_heartbeat, dag_processing.total_parse_time et executor.queued_tasks. Airflow 3.2 ajoute les traces OpenTelemetry pour une observabilité de bout en bout des pipelines.
En préparation d'un entretien de data engineering portant sur l'orchestration de pipelines ? SharpSkill propose des questions d'entretien Airflow dédiées et des modules de pratique qui reproduisent des scénarios réels issus d'environnements de production.
Passe à la pratique !
Teste tes connaissances avec nos simulateurs d'entretien et tests techniques.
Conclusion
- Airflow 3.2 introduit le Task SDK (
airflow.sdk) comme API stable pour l'écriture de DAG — migrer les imports dès maintenant pour éviter les ruptures dans les versions futures - Les partitions d'assets permettent une planification data-aware au niveau de la partition, en éliminant les déclenchements de pipeline redondants sur des mises à jour de données partielles
- Le support natif de l'asynchrone dans le PythonOperator gère les charges intensives en E/S (téléchargements par lots, fan-outs d'API) sans opérateurs deferrable personnalisés
- Le mapping dynamique de tâches via
.expand()s'adapte à la taille variable des charges à l'exécution, sans modification du code du DAG - La préparation aux entretiens doit couvrir le fonctionnement des DAG, les arbitrages entre executors (Celery vs Kubernetes), les limites de XCom et les patterns d'idempotence
- Les déploiements de production tirent profit de DAG petits et idempotents, d'une gestion des secrets externe et de l'export de métriques vers des plateformes d'observabilité
Passe à la pratique !
Teste tes connaissances avec nos simulateurs d'entretien et tests techniques.
Tags
Partager
Articles similaires

Apache Spark avec Python : construire des pipelines de données étape par étape
Tutoriel pratique PySpark couvrant les opérations DataFrame, la construction de pipelines ETL et les fonctionnalités de Spark 4.0. Inclut des exemples de code prêts pour la production destinés aux data engineers qui préparent leurs entretiens techniques.

Top 25 Questions d'Entretien Data Engineering en 2026
Les questions d'entretien data engineering les plus fréquentes en 2026 : SQL avancé, pipelines temps réel, architecture lakehouse, Spark, Airflow et optimisation des coûts cloud.

dbt en 2026 : transformations de données, tests et questions d'entretien
Tutoriel pratique sur dbt (data build tool) : transformations SQL, modélisation par couches, stratégies de test et vraies questions d'entretien pour les postes de data engineering en 2026.