Python, de la zero Lecția 41 / 60

Orchestrare: Airflow, Prefect, Dagster - peisajul din 2026

Cand cron nu mai e suficient, ce face efectiv un orchestrator si cei trei contestatari pentru pipeline-urile tale de date.

Scrii un script Python care trage de la un API, transformă cu pandas, încarcă în Postgres. Funcționează. Îl programezi cu cron. Câteva săptămâni totul e bine. Apoi un job eșuează la 3 dimineața și afli marți după-amiază, fiindcă cron nu îți spune. Apoi un job depinde de altul și cron nu știe de dependențe, așa că îți încrucișezi degetele despre timing. Apoi ai zece joburi și nu mai ții minte ce rulează când. Apoi cineva întreabă „chiar s-a terminat încărcarea de marți?” și nu ai nimic să-i arăți.

Acela e momentul în care ai nevoie de un orchestrator. Lecția asta parcurge peisajul din 2026, Airflow, Prefect, Dagster, întrebarea managed-vs-self-hosted, și se termină cu un arbore de decizie simplu.

Ce face efectiv un orchestrator

Cron face un singur lucru: rulează o comandă la un anumit moment. Tot restul îl construiești singur, prost. Un orchestrator face restul:

  • Programare cu calendare, intervale, expresii cron, declanșatori de eveniment.
  • Dependențe: „rulează B doar după ce A reușește.”
  • Retries: „dacă eșuează, încearcă din nou de 3 ori cu exponential backoff.”
  • Stare și istoric: fiecare execuție logată, fiecare rezultat inspectabil.
  • Observabilitate: un UI care arată ce a rulat, ce a eșuat, cât a durat, cu loguri în care poți da click.
  • Alerting: spune-mi pe Slack când ceva eșuează.
  • Backfills: „rerulează acest pipeline pentru fiecare zi din martie.”
  • Gestionarea resurselor: pool-uri, cozi, limite de concurență per task.

Poți construi toate astea peste cron și bash și un tabel de metadate Postgres. Oamenii o fac, în fiecare an, și în fiecare an regretă. Orchestratorul e lucrul care există ca tu să nu trebuiască să construiești asta.

Când ai nevoie de unul

Pragul onest: undeva pe la 5-10 joburi cu dependențe, sau un singur job destul de important încât să trebuiască să afli în câteva minute când se strică. Sub asta, cron + un script care îți trimite email la eșec e suficient. Peste asta, abordarea făcută în casă începe să muște.

Semne că ai trecut linia:

  • Nu poți spune dintr-o privire ce joburi au rulat azi.
  • Înlănțui joburi cu && în cron și te rogi în privința runtime-ului.
  • Backfill pe un interval de date înseamnă să scrii scripturi unice.
  • Eșecurile sunt observate de oameni, nu de sisteme.
  • „A rulat asta?” e o întrebare grea de răspuns.

Dacă două dintre astea sunt adevărate, ai nevoie de un orchestrator.

Airflow, statesman-ul mai în vârstă

Airflow a ieșit din Airbnb în 2014. E orchestratorul de date open-source dominant, punct. Dacă te alături unei echipe de date stabilite, șansele sunt mari să întâlnești Airflow în prima săptămână.

Conceptul central e DAG-ul, directed acyclic graph, un fișier Python care declară task-urile și dependențele lor:

from datetime import datetime, timedelta
from airflow import DAG
from airflow.operators.python import PythonOperator

def extract():
    # pull from API, write to S3
    ...

def transform():
    # read S3, transform, write back
    ...

def load():
    # read S3, load to Postgres
    ...

with DAG(
    dag_id="daily_etl",
    start_date=datetime(2026, 1, 1),
    schedule="0 3 * * *",  # 3am daily
    catchup=False,
    default_args={"retries": 3, "retry_delay": timedelta(minutes=5)},
) as dag:
    e = PythonOperator(task_id="extract", python_callable=extract)
    t = PythonOperator(task_id="transform", python_callable=transform)
    l = PythonOperator(task_id="load", python_callable=load)
    e >> t >> l

Operatorul >> declară dependența: extract înainte de transform înainte de load. Airflow parsează DAG-ul, programează fiecare task, le rulează în ordine, reîncearcă la eșec și îți arată totul într-un UI web.

Pro: ecosistem enorm. Fiecare furnizor cloud, bază de date, unealtă SaaS și message broker de care ai auzit are un operator sau hook Airflow. Testat în luptă la scară uriașă. Multe joburi recrutează pentru el. Oferta managed de la Astronomer înlătură cea mai mare parte a durerii operaționale.

Contra: instalare grea. Baza de date de metadate, scheduler, webserver, executor, workers, chiar și setup-ul minim are mai multe părți în mișcare. Modelul „fișierul DAG e cod Python” înseamnă că logica de orchestrare și logica de business tind să se amestece. UI-ul s-a îmbunătățit în Airflow 2 și 3, dar tot pare deceniul trecut. DAG-urile dinamice, unde structura depinde de date la runtime, au fost adăugate ulterior și se simte.

Folosește Airflow când: ești într-un loc care deja îl folosește, sau ai nevoie de lățimea integrărilor, sau vrei povestea cea mai sigură de hiring.

Prefect, alternativa pythonică

Prefect a fost lansat în 2018 cu o pitch simplă: ia ce a făcut bine Airflow (programare, retries, observabilitate) și rescrie-l pentru oamenii cărora chiar le place Python.

from prefect import flow, task
import httpx
import pandas as pd

@task(retries=3, retry_delay_seconds=60)
def extract(url: str) -> dict:
    return httpx.get(url).json()

@task
def transform(data: dict) -> pd.DataFrame:
    return pd.DataFrame(data["records"])

@task
def load(df: pd.DataFrame) -> None:
    df.to_sql("records", "postgresql://...", if_exists="append")

@flow(name="daily_etl")
def daily_etl(url: str):
    raw = extract(url)
    clean = transform(raw)
    load(clean)

if __name__ == "__main__":
    daily_etl.serve(name="daily", cron="0 3 * * *")

Observă diferența. Task-urile sunt funcții decorate. Flow-ul e o funcție Python obișnuită care le apelează, iar graful de dependențe e ce implică apelurile. Dacă extract returnează o valoare pe care transform o consumă, Prefect știe că transform depinde de extract. Fără operatori >>, fără apeluri set_upstream. Pur și simplu se citește.

Pro: API mai curat, DAG-urile dinamice sunt first-class, UI-ul e cu adevărat modern, bucla locală de dezvoltare e rapidă. Prefect Cloud gestionează scheduler-ul, deci rulezi doar workers. Mai ușor de învățat dacă vii proaspăt.

Contra: ecosistem mai mic decât Airflow. Mai puține integrări preconstruite înseamnă mai multe „doar scrie o funcție”, ceea ce e bine, până când voiai un operator Snowflake testat în luptă. Mai puțin comun în anunțurile de joburi, deși acel decalaj se închide.

Folosește Prefect când: începi de la zero, vrei un API mai prietenos, nu ai nevoie de o integrare specifică Airflow, echipa ta valorizează experiența developerului.

Dagster, contestatarul conștient de date

Dagster (2019+) ia o altă unghi. Airflow și Prefect orchestrează task-uri. Dagster orchestrează assets, tabelele, fișierele, modelele și rapoartele pe care le produc task-urile tale.

from dagster import asset, Definitions
import httpx
import pandas as pd

@asset
def raw_records() -> dict:
    return httpx.get("https://api.example.com/data").json()

@asset
def clean_records(raw_records: dict) -> pd.DataFrame:
    return pd.DataFrame(raw_records["records"])

@asset
def loaded_records(clean_records: pd.DataFrame) -> None:
    clean_records.to_sql("records", "postgresql://...", if_exists="append")

defs = Definitions(assets=[raw_records, clean_records, loaded_records])

Argumentele funcțiilor sunt dependențele. clean_records ia raw_records ca argument, deci Dagster știe să materializeze raw_records întâi. Unitatea de muncă nu e „rulează acest task”, e „asigură-te că acest asset e proaspăt.” Rulează un job și Dagster își dă seama de setul minim de assets de reconstruit.

Schimbarea asta sună mică, dar reformulează totul. Primești lineage gratis, Dagster știe că loaded_records depinde de clean_records care depinde de raw_records și o arată în UI ca un graf. Primești typing, assets-urile au tipuri și Dagster le verifică. Primești partial runs, „reconstruiește doar downstream-ul acestui asset” e încorporat. Poți exprima partiții (un asset per zi, per regiune, per tenant) ca un concept first-class în loc de un hack la runtime.

Pro: model data-native, tipuri și teste de calitate software-engineering, lineage out of the box, se integrează frumos cu dbt și Spark, Dagster Cloud e o ofertă managed curată.

Contra: opinionated. Modelul de assets e un mod diferit de a gândi, iar dacă munca ta nu se potrivește (antrenare ML de lungă durată, message-driven event handlers, orice care nu produce într-adevăr un „tabel”), poate părea forțat. Comunitate mai mică decât Airflow și mai puțini ingineri angajabili îl cunosc.

Folosește Dagster când: munca ta e fundamental despre producerea și împrospătarea de assets de date, îți pasă de lineage și tipuri, echipa ta e de acord cu modelul.

Self-hosted vs managed

Pentru toate cele trei, oferta managed înlătură cea mai mare parte a durerii operaționale. În termeni aproximativi 2026:

  • Astronomer: Airflow managed. Implicit dacă ai ales Airflow și nu vrei să-l rulezi singur.
  • Prefect Cloud: Prefect scheduler managed. Tu rulezi workers (adesea serverless) și Prefect rulează creierul.
  • Dagster Cloud: Dagster managed, cu opțiuni hibride (codul tău, control plane-ul lor) și serverless.
  • Databricks Workflows / Snowflake Tasks: orchestratori încorporați în platforme de date. Merită dacă trăiești complet acolo; limitativ dacă nu.
  • Cloud-native: AWS Step Functions, GCP Cloud Composer (care e doar Airflow managed), Azure Data Factory. Merită știut că există; de obicei nu cea mai bună experiență de dezvoltator Python.

Self-hosting îți dă control, costă bani în ore de inginerie și e bine dacă ai o echipă de platformă. Managed îți dă înapoi acele ore la prețul de niște USD lunari. Pentru o echipă mai mică de zece, managed aproape întotdeauna câștigă.

Arborele de decizie

O versiune scurtă care mi-a servit bine:

  1. Câteva joburi, fără dependențe, o echipă prietenoasă care citește email-uri. Cron + scripturi care trimit email la eșec. Nu over-engineerui.
  2. Zeci de joburi, dependențe reale, ai fost mușcat de eșecuri tăcute. Alege un orchestrator managed. Dacă ai alegere liberă și o echipă mică: Prefect pentru ușurință, Dagster dacă munca ta e asset-shaped, Airflow dacă vrei povestea cea mai sigură de hiring.
  3. Sute de joburi, dependențe complexe, mai multe echipe, nevoi de reglementare. Self-host unul dintre cele trei pe baza skill-urilor echipei. Airflow câștigă la integrări și hiring; Dagster câștigă la semantica datelor; Prefect câștigă la simplitate operațională.
  4. Ești deja pe o platformă. Dacă datele tale trăiesc în Databricks, folosește Workflows. Dacă trăiesc în Snowflake, Tasks plus dbt e adesea suficient. Nu adăuga un orchestrator doar fiindcă poți.

Meta-punctul onest: orchestratorul e rareori cea mai importantă decizie. Calitatea pipeline-ului, idempotență, observabilitate, testare, granițe sensate între extract / transform / load, contează mult mai mult decât unealta care îl învelește. Un pipeline curat pe Airflow bate unul mizerabil pe Dagster, de fiecare dată.

Unde mergem mai departe

În lecția următoare și finală a acestui modul, construim un pipeline real cap la cap. API public, transformare cu pandas, încărcare într-o bază de date, programat, monitorizat, idempotent. Vom începe cu cron fiindcă e răspunsul corect pentru dimensiune și vom indica unde ai trece la unul dintre orchestratorii de mai sus.

Lumea orchestratorilor e mai mare decât această lecție, Airbyte, Mage, Argo Workflows, Temporal, Kestra, Windmill toți merită menționați și nu primesc. Cei trei pe care i-am acoperit sunt mainstream-ul data-engineering în 2026. Alege unul, învață-l bine și vei recunoaște forma celorlalți.


Citări: docs Airflow, docs Prefect, docs Dagster. Consultat 2026-05-01.

Caută