Apache Airflow en 2026: orquestación de pipelines, DAG y preguntas de entrevista
Dominar Apache Airflow 3.2 con este tutorial práctico: escritura de DAG con el Task SDK, patrones de orquestación de pipelines, particiones de assets y preguntas reales de entrevista para puestos de data engineering en 2026.

Apache Airflow 3.2 representa la evolución más significativa de la plataforma de orquestación de código abierto desde la renovación arquitectónica de la versión 3.0. Con más de 10 millones de descargas mensuales en PyPI y adopción en empresas que van desde Airbnb hasta Spotify, Airflow sigue siendo la herramienta dominante para construir, programar y monitorear pipelines de datos. Este tutorial cubre la escritura de DAG con el nuevo Task SDK, los patrones de orquestación de pipelines y las preguntas de entrevista que aparecen en los puestos de data engineering.
Airflow 3.2, lanzado en abril de 2026, introduce las particiones de assets para una programación data-aware granular, el soporte asíncrono nativo en el PythonOperator y los despliegues multiequipo. Todas las importaciones de DAG usan ahora el namespace estable airflow.sdk introducido en Airflow 3.0.
Escritura de DAG con el Task SDK de Airflow
Airflow 3.0 introdujo el Task SDK, un paquete independiente que desacopla las definiciones de DAG de los componentes internos de Airflow. El objetivo: escribir DAG portables y estables entre versiones que sobrevivan a las actualizaciones de Airflow sin cambios de código. Todos los objetos centrales — DAG, dag, task, BaseOperator, Connection, Variable — residen ahora bajo airflow.sdk.
Las rutas de importación heredadas (airflow.decorators.task, airflow.models.dag.DAG) todavía funcionan en la 3.2, pero están marcadas como obsoletas y se eliminarán en una versión futura.
# 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()El decorador @dag reemplaza al gestor de contexto tradicional with DAG(...). El decorador @task convierte funciones Python sencillas en tareas de Airflow, con la serialización XCom gestionada automáticamente. Llamar a transform(raw) declara una dependencia — Airflow construye las aristas del DAG a partir del grafo de llamadas de funciones.
Mapeo dinámico de tareas para cargas variables
Los DAG estáticos fallan cuando el número de elementos a procesar cambia entre ejecuciones. El mapeo dinámico de tareas, estable desde Airflow 2.4 y refinado en la rama 3.x, resuelve esto generando las tareas en tiempo de ejecución mediante .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()En tiempo de ejecución, Airflow crea tres instancias paralelas de process_region — una por región. Si mañana aparece una cuarta región, no se necesita ningún cambio en el código del DAG. La tarea merge_results espera a que todas las instancias mapeadas terminen antes de ejecutarse.
Por defecto, Airflow limita las tareas mapeadas a 1024 instancias por mapeo. Este límite se modifica con max_map_length en la configuración del DAG al procesar conjuntos de datos más grandes.
Particiones de assets: programación data-aware en Airflow 3.2
Antes de Airflow 3.2, la programación data-aware operaba a nivel de asset: cuando un DAG productor actualizaba un asset, todos los DAG consumidores se disparaban sin importar qué porción de datos había cambiado. Las particiones de assets corrigen esto al habilitar una granularidad a nivel de partición.
Consideremos un escenario donde tres DAG ascendentes producen estadísticas horarias de jugadores para distintas ligas deportivas. Un DAG analítico descendente solo debería dispararse cuando las tres ligas hayan publicado datos para la misma hora.
# 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 programación particionada elimina las ejecuciones de pipeline redundantes. El DAG descendente solo se dispara cuando la partición exacta que necesita está disponible en todas las fuentes ascendentes — ni antes, ni sobre datos parciales.
¿Listo para aprobar tus entrevistas de Data Engineering?
Practica con nuestros simuladores interactivos, flashcards y tests técnicos.
Tareas asíncronas nativas para cargas intensivas en E/S
Airflow 3.2 añade soporte asíncrono nativo en el PythonOperator. Antes, ejecutar operaciones de E/S concurrentes (miles de llamadas a API, descargas de archivos por lotes) exigía escribir operadores deferrable personalizados. Ahora basta con pasar directamente una función 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()El enfoque asíncrono descarga 500 archivos en paralelo a través de un único slot de worker, frente a 500 llamadas HTTP secuenciales en la versión síncrona. Para cargas limitadas por E/S, esto se traduce en mejoras de velocidad de un orden de magnitud sin aprovisionar workers adicionales.
Arquitectura de Airflow: componentes y flujo de ejecución
Comprender la arquitectura de Airflow es esencial tanto para operarlo en producción como para responder preguntas de entrevista. Cinco componentes interactúan durante cada ejecución de DAG:
- Scheduler — Parsea los archivos de DAG, resuelve las dependencias y encola las tareas para su ejecución. En Airflow 3.x, el scheduler opera sin estado contra la base de metadatos.
- Executor — Determina dónde se ejecutan las tareas.
LocalExecutorgestiona instalaciones en una sola máquina.CeleryExecutordistribuye entre nodos workers.KubernetesExecutorlevanta un pod por tarea. - Workers — Ejecutan el código real de las tareas. Con la nueva Task Execution API de Airflow 3.0, los workers se comunican mediante un contrato estable, lo que permite la ejecución en contenedores, entornos edge o runtimes externos.
- Base de metadatos — PostgreSQL (recomendado) o MySQL. Almacena las definiciones de DAG, los estados de las tareas, los valores XCom, las credenciales de conexión y los registros de auditoría.
- Servidor web — La interfaz de Airflow para monitorear las ejecuciones de DAG, inspeccionar logs, disparar ejecuciones manuales y gestionar conexiones.
Conviene evitar SequentialExecutor en producción: ejecuta una sola tarea a la vez y existe únicamente para desarrollo. Para entornos nativos de Kubernetes, KubernetesExecutor ofrece el aislamiento más fuerte, ya que cada tarea obtiene su propio pod con recursos y dependencias independientes.
Airflow vs. Prefect vs. Dagster en 2026
Airflow compite con dos alternativas significativas. La elección correcta depende del tamaño del equipo, la infraestructura existente y los tipos de pipelines que se construyen.
| Característica | Airflow 3.2 | Prefect 3.x | Dagster 1.9 |
|---|---|---|---|
| Definición de DAG | Decoradores Python (airflow.sdk) | Decoradores Python (@flow, @task) | Decoradores Python (@asset, @op) |
| Programación | Cron, asset-aware, partition-aware | Cron, basada en eventos | Cron, basada en sensors, asset-aware |
| Modelo de ejecución | Scheduler centralizado + workers distribuidos | Híbrido (servidor + work pools) | dagster-daemon centralizado |
| Tareas dinámicas | Tareas mapeadas con .expand() | Bucles Python nativos | Particiones dinámicas |
| Soporte asíncrono | Nativo en 3.2 | Nativo desde la 2.0 | Operaciones de E/S asíncronas |
| Aislamiento multiequipo | Integrado (experimental en 3.2) | Basado en workspaces (Cloud) | Branch deployments |
| Tamaño de la comunidad | El más grande (35k+ estrellas en GitHub) | En crecimiento (18k+ estrellas) | En crecimiento (12k+ estrellas) |
| Mejor ajuste | Pipelines complejos, multiequipo, con infraestructura establecida | Equipos pequeños que buscan iteración rápida | Organizaciones centradas en assets de datos |
La ventaja de Airflow reside en su ecosistema: más de 80 paquetes de providers que cubren cada servicio en la nube, base de datos y API principales. Prefect destaca en la experiencia de desarrollo con menos código repetitivo. El modelo asset-centric de Dagster encaja con equipos que piensan en términos de productos de datos más que en secuencias de tareas.
Preguntas de entrevista: Apache Airflow para data engineers
Las siguientes preguntas reflejan lo que los responsables de contratación y los ingenieros senior preguntan durante las entrevistas de data engineering en empresas que ejecutan Airflow en producción.
¿Qué es un DAG y cómo lo usa Airflow?
Un DAG (Directed Acyclic Graph) define un flujo de trabajo como una colección de tareas con dependencias, garantizado sin referencias circulares. Airflow parsea los archivos Python de la carpeta dags/, construye el grafo de dependencias y el scheduler determina el orden de ejecución. Cada ejecución de DAG crea un objeto DagRun vinculado a una fecha lógica. La restricción «acíclico» garantiza que el scheduler siempre pueda encontrar un orden de ejecución válido: la tarea A se ejecuta antes que la tarea B, nunca al revés de forma simultánea.
¿Cómo funciona XCom y cuándo debe evitarse?
XCom (cross-communication) transmite pequeñas cantidades de datos entre tareas. Una tarea empuja un valor de retorno a XCom; las tareas descendentes lo recuperan. El Task SDK se encarga de esto automáticamente al pasar valores de retorno entre tareas decoradas. XCom almacena los datos en la base de metadatos por defecto, lo que lo hace inadecuado para conjuntos de datos grandes (cualquier cosa por encima de unos pocos KB). Para transferir grandes volúmenes de datos conviene usar almacenamiento externo (S3, GCS) y pasar únicamente la ruta de referencia a través de XCom.
Explique la diferencia entre schedule, start_date y catchup.
El parámetro schedule (renombrado desde schedule_interval en Airflow 3.x) define con qué frecuencia se ejecuta el DAG: una cadena cron, un timedelta, un objeto timetable o un disparador de asset. start_date fija la fecha lógica más temprana para la que se puede crear una ejecución de DAG. catchup=True (valor por defecto) crea ejecuciones de DAG para todos los intervalos perdidos entre start_date y el momento actual. Fijar catchup=False indica al scheduler que ignore los intervalos pasados y programe solo desde el tiempo actual en adelante. Un patrón común en producción: catchup=False para los DAG operativos y catchup=True para los backfills históricos.
¿En qué se diferencia el KubernetesExecutor del CeleryExecutor?
CeleryExecutor mantiene un pool de procesos workers de larga duración conectados mediante un broker de mensajes (Redis o RabbitMQ). Las tareas se encolan y se ejecutan en los workers disponibles. KubernetesExecutor crea un nuevo pod de Kubernetes para cada tarea, usando la imagen Docker y los requisitos de recursos de la tarea. Celery ofrece menor latencia (sin sobrecarga de arranque de pod) y funciona bien para cargas homogéneas. KubernetesExecutor proporciona un aislamiento más fuerte, control de recursos por tarea y elimina la necesidad de gestionar un pool de workers estático: ideal para cargas heterogéneas donde las tareas tienen distintos requisitos de dependencias y memoria.
¿Qué estrategias existen para manejar los fallos de tareas?
Airflow ofrece varios mecanismos de manejo de fallos. retries y retry_delay configuran reintentos automáticos con backoff exponencial. on_failure_callback dispara lógica personalizada (alertas de Slack, incidentes de PagerDuty) cuando una tarea falla. trigger_rule controla cómo responden las tareas descendentes: all_success (por defecto), one_success, all_failed o none_failed_min_one_success. Para problemas de infraestructura transitorios, el parámetro retry_exponential_backoff=True aumenta el tiempo de espera entre reintentos. Los SLA (ahora Deadline Alerts en la 3.x) monitorean la duración de ejecución y disparan callbacks cuando las tareas superan el tiempo de ejecución esperado.
Buenas prácticas de producción para despliegues de Airflow
Ejecutar Airflow de forma fiable a escala exige atención a varios patrones operativos que van más allá de escribir DAG correctos.
Tareas idempotentes. Cada tarea debería producir el mismo resultado cuando se ejecuta varias veces con las mismas entradas. Conviene usar INSERT ... ON CONFLICT o MERGE en lugar de un simple INSERT. Particionar los datos de salida por fecha lógica. Esto garantiza reintentos y backfills seguros sin duplicación de datos.
DAG pequeños y enfocados. Conviene resistir la tentación de construir DAG monolíticos con decenas de tareas. Dividir los pipelines complejos en varios DAG conectados mediante assets (antes datasets). Los DAG más pequeños se parsean más rápido, son más fáciles de depurar y permiten reinicios parciales del pipeline.
Gestión de conexiones. Almacenar todas las credenciales en el gestor de conexiones de Airflow o en un backend de secretos externo (AWS Secrets Manager, HashiCorp Vault). Nunca codificar credenciales en los archivos de DAG. Airflow 3.x cifra los campos de conexión en reposo en la base de metadatos.
Monitoreo y alertas. Exportar las métricas de Airflow a Prometheus o StatsD. Hacer seguimiento de scheduler_heartbeat, dag_processing.total_parse_time y executor.queued_tasks. Airflow 3.2 añade trazas de OpenTelemetry para una observabilidad de pipeline de extremo a extremo.
¿Preparando una entrevista de data engineering que cubre la orquestación de pipelines? SharpSkill ofrece preguntas de entrevista de Airflow dedicadas y módulos de práctica que replican escenarios reales de entornos de producción.
¡Empieza a practicar!
Pon a prueba tu conocimiento con nuestros simuladores de entrevista y tests técnicos.
Conclusión
- Airflow 3.2 introduce el Task SDK (
airflow.sdk) como API estable para la escritura de DAG: conviene migrar las importaciones ahora para evitar rupturas en versiones futuras - Las particiones de assets habilitan una programación data-aware a nivel de partición, eliminando los disparos de pipeline redundantes ante actualizaciones de datos parciales
- El soporte asíncrono nativo en el PythonOperator maneja cargas intensivas en E/S (descargas por lotes, fan-outs de API) sin operadores deferrable personalizados
- El mapeo dinámico de tareas con
.expand()se adapta al tamaño variable de las cargas en tiempo de ejecución, sin cambios en el código del DAG - La preparación para entrevistas debe cubrir el funcionamiento de los DAG, los compromisos entre executors (Celery vs. Kubernetes), las limitaciones de XCom y los patrones de idempotencia
- Los despliegues de producción se benefician de DAG pequeños e idempotentes, una gestión de secretos externa y la exportación de métricas a plataformas de observabilidad
¡Empieza a practicar!
Pon a prueba tu conocimiento con nuestros simuladores de entrevista y tests técnicos.
Etiquetas
Compartir
Artículos relacionados

Apache Spark con Python: construir pipelines de datos paso a paso
Tutorial práctico de PySpark que cubre operaciones con DataFrame, construcción de pipelines ETL y las novedades de Spark 4.0. Incluye ejemplos de código listos para producción orientados a data engineers que preparan entrevistas técnicas.

Top 25 Preguntas de Entrevista para Ingenieros de Datos en 2026
Guía completa con las 25 preguntas más importantes para entrevistas de ingeniería de datos en 2026. Incluye SQL avanzado, pipelines ETL/ELT, streaming con Kafka, Spark, orquestación y arquitecturas lakehouse.

dbt en 2026: transformaciones de datos, pruebas y preguntas de entrevista
Tutorial práctico de dbt (data build tool): transformaciones SQL, modelado por capas, estrategias de pruebas y preguntas reales de entrevista para roles de data engineering en 2026.