Volver a la biblioteca
Artículointermedio

El orquestador coordina, no transforma

El orquestador define dependencias y dispara tareas; meter transformaciones o lógica de negocio adentro es un error de diseño que escala mal

El patrón que se repite

Un equipo empieza con un DAG simple: tres tareas, dependencias claras, todo funciona. Con el tiempo, el pipeline crece. Alguien agrega una transformación "rápida" dentro de un Python operator. Otro suma validaciones. Un tercero mete lógica de negocio porque "total, ya está ahí el código".

Seis meses después, el DAG tiene 80 tareas, la mitad con código embebido, y nadie quiere tocarlo.

La confusión de fondo es sobre qué hace un orquestador y qué no debería hacer.

Qué hace un orquestador (y qué no)

Un orquestador define el flujo: qué corre, en qué orden, con qué dependencias. Eso es todo.

No es el lugar para:

  • Transformaciones de datos.
  • Lógica de negocio.
  • Procesamiento pesado.
  • Entrenamiento de modelos.

Cuando usás orquestadores tipo Airflow, Dagster o Prefect, la idea es que cada tarea invoque algo externo: un job de dbt, un script en un container, un proceso en Spark. El orquestador dispara y coordina; no ejecuta el trabajo pesado.

Meter código de transformación adentro del orquestador acopla responsabilidades que deberían estar separadas. Y ese acoplamiento tiene consecuencias concretas: el código se vuelve difícil de testear, de versionar, de reutilizar fuera del contexto del DAG.

El DAG que crece sin límite

Cuando el orquestador empieza a acumular lógica, el DAG crece. Y cuando el DAG crece sin control, aparecen dos síntomas:

El DAG monolítico: un grafo con decenas o cientos de tareas donde todo está conectado con todo. Difícil de leer, difícil de mantener, difícil de debuggear cuando algo falla en la tarea 47.

El meta-orquestador: cuando el DAG se vuelve inmanejable, alguien propone "un orquestador que orqueste los DAGs". Suena razonable, pero en la práctica estás compensando un problema de diseño con otra capa de complejidad.

Si llegás a necesitar un meta-orquestador, probablemente el problema esté antes: en cómo partiste (o no partiste) las responsabilidades.

Orquestar por activos, no solo por tareas

Hay otra forma de pensar la orquestación: en lugar de definir "tarea A dispara tarea B", definir "el activo silver depende del activo bronze".

Este enfoque, que popularizó Dagster y que Airflow incorporó después con el concepto de assets, cambia el foco de las tareas a los datos. En lugar de pensar en secuencias de ejecución, pensás en dependencias entre activos.

¿Qué ganás? Más observabilidad: sabés quién produce cada activo, quién lo consume, cuándo se actualizó. Y una forma más natural de modelar pipelines donde lo que importa es el estado de los datos, no el orden de las tareas.

No es que un enfoque sea mejor que el otro en abstracto. Pero si tu pipeline tiene muchas dependencias entre tablas o capas, orquestar por activos puede simplificar el modelo mental.

Dónde queda la lógica entonces

Si el orquestador no es el lugar de la lógica, ¿dónde va?

  • Transformaciones: en dbt, en scripts SQL, en jobs de Spark. Herramientas diseñadas para transformar datos.
  • Lógica de negocio: en la capa de transformación, donde se puede testear, documentar y versionar.
  • Procesamiento pesado: en servicios que escalen (containers, funciones serverless, clusters).

El orquestador queda liviano: define el flujo, pasa parámetros, maneja reintentos y schedules. Nada más.

Operadores: el mecanismo para delegar

Los operadores son la forma que tienen los orquestadores de invocar trabajo externo sin ejecutarlo ellos mismos. Cada tipo de operador encapsula una forma de delegación:

  • BashOperator: ejecuta un comando de shell. Útil para invocar scripts que ya existen.
  • PythonOperator: ejecuta una función Python, pero esa función debería invocar algo externo, no contener la lógica de transformación.
  • DockerOperator: ejecuta un container con la lógica empaquetada. El orquestador no necesita tener instaladas las dependencias.
  • Operadores específicos: para dbt, Spark, bases de datos, servicios cloud. Cada uno sabe cómo invocar su herramienta.

La clave es que el operador no contiene la lógica. El operador sabe cómo invocar algo que sí la contiene.

Si tu transformación es SQL, el SQL debería vivir en archivos separados o en un proyecto de transformación. El operador lo invoca, pero no lo define. Si tu transformación es Python, la lógica debería estar en un módulo aparte o en un container. El DAG importa y dispara, pero no implementa.

Cuando el código del DAG se vuelve aburrido de leer (definir tareas, definir dependencias, configurar reintentos), probablemente esté bien diseñado.

El costo de la solución rápida

Meter lógica en el orquestador suele empezar como una solución rápida. "Es una cosa puntual", "tiene que salir ya", "después lo refactorizamos".

El problema es que la solución rápida tiende a volverse permanente. Y cuando se vuelve permanente, el costo de mantenerla crece con cada tarea que se agrega.

Un DAG liviano que invoca procesos externos es más fácil de mantener, más fácil de escalar, más fácil de debuggear. La complejidad queda donde corresponde: en las herramientas diseñadas para manejarla.

En resumen

El orquestador coordina el flujo. Define dependencias, dispara tareas, maneja schedules y reintentos. Eso es lo que hace bien.

Meter transformaciones, lógica de negocio o procesamiento pesado adentro es un error de diseño que escala mal. Si el DAG crece sin control o aparece la necesidad de un meta-orquestador, el problema probablemente esté en cómo se distribuyeron las responsabilidades.

Mantené el orquestador liviano. Delegá el trabajo a las herramientas que lo hacen mejor.