Chapter 27: Key Takeaways
-
ML pipelines are directed acyclic graphs (DAGs), and the DAG structure is not a framework convenience — it is a mathematical necessity. The acyclic constraint guarantees a valid topological ordering: an execution sequence where every task runs only after its dependencies have completed. The DAG also reveals parallelism — tasks with no mutual dependency can run concurrently, often cutting pipeline duration by 30–50%. The StreamRec pipeline's parallel training of retrieval and ranking models (Stage 3) saves nearly 2 hours per run compared to sequential execution. Every orchestration framework (Airflow, Dagster, Prefect) builds on this abstraction, differing only in how the DAG is defined and what metadata is tracked alongside it.
-
Airflow, Dagster, and Prefect represent three distinct orchestration philosophies — task-centric, asset-centric, and Python-native — and the right choice depends on the team's priorities, not on any framework being universally superior. Airflow (imperative, task-centric) excels in diverse-workload environments with its 80+ provider packages and decade of production maturity. Dagster (declarative, asset-centric) excels in ML-heavy environments where data lineage, partition management, and testability are priorities — its automatic DAG inference from asset dependencies and IO manager abstraction make it particularly well-suited for pipelines that produce versioned data and model artifacts. Prefect (Python-native, decorator-based) excels when teams want to orchestrate existing Python code with minimal framework overhead. All three implement the same core concepts: DAGs, scheduling, retries, and backfill.
-
Idempotency is the single most important property of a production pipeline task, because it makes retries and backfills safe. An idempotent task can be executed multiple times with the same input and produce the same output — no duplicated data, no corrupted artifacts, no accumulated side effects. The three primary techniques are partition-based overwrites (write to a date-keyed path, overwriting on re-run), atomic writes (write to a temporary location, then rename), and deterministic artifact paths (derive paths from logical date and configuration hash, not timestamps or UUIDs). Operations that are inherently non-idempotent — notifications, counter increments, external API calls with side effects — must be isolated in non-retried tasks or use idempotency keys.
-
Failure handling is the difference between a pipeline and a script: retry policies with exponential backoff, severity-tiered alerting, dead letter queues, and SLA monitoring enable pipelines to run unattended. Exponential backoff ($d_k = d_0 \cdot 2^{k-1}$, capped at $d_{\max}$) with jitter prevents thundering herd retries. Severity-tiered alerting (P0 pages oncall; P3 is logged only) prevents alert fatigue. Dead letter queues capture bad records without halting the pipeline on partial data quality issues. SLA monitoring detects when the pipeline is at risk of breaching its completion deadline. A pipeline without these mechanisms requires a human operator — and a human operator who must check Slack at 3am is a single point of failure.
-
Backfill — reprocessing historical data intervals — is an operational necessity that must be designed for from day one, not retrofitted after the first outage. Sequential backfill is safe but slow; parallel backfill is fast but dangerous for pipelines with cross-partition dependencies (rolling-window features require chronological processing). Prioritized backfill (newest first) balances freshness with completeness. Version-tagged output paths prevent backfill from overwriting production data. The worst backfill disasters come from pipelines designed only for forward execution: hardcoded timestamps, non-partitioned outputs, and queries that always fetch "yesterday" instead of the logical date.
-
Pipeline versioning and artifact management create the provenance chain that links a production model back to its exact code, configuration, training data, and feature computation. The artifact lineage graph — git SHA, configuration version, Delta Lake table version, Feast feature set version, MLflow run ID, model registry version — must be captured at pipeline execution time and stored alongside the model. This is not bureaucracy; it is the mechanism that enables debugging ("why did the model degrade?"), reproducibility ("can I retrain this exact model?"), and regulatory compliance (MediCore's FDA audit response in under 4 hours, Case Study 2).
-
Pipeline testing at three levels — unit tests for task logic, integration tests for end-to-end data flow, and contract tests for inter-stage schemas — is the quality gate that prevents silent failures. The key enabler is separating business logic from orchestration: validation rules, feature computation, and model evaluation should be pure Python functions testable with pytest, wrapped in thin orchestration layers (Dagster assets, Airflow operators, Prefect tasks). Contract tests —
DataContractobjects that specify required columns, types, null constraints, and row count minimums — catch schema evolution bugs before they corrupt training data. StreamRec's 47 unit tests, running in 3 seconds, catch 90% of bugs before they reach the orchestrator runtime (Case Study 1).