ML pipeline orchestration coordinates the execution of complex, multi-step ML workflows - data ingestion, feature engineering, training, evaluation, and deployment. Good orchestration ensures reproducibility, handles failures gracefully, and provides visibility into pipeline execution.
Where It Is Used
Pipeline orchestration powers production ML across industries:
- Training pipelines: Scheduled model retraining with data validation
- Feature pipelines: Regular feature computation and materialization
- Batch inference: Scheduled predictions on new data
- Data pipelines: ETL for ML datasets
- Deployment pipelines: Model validation and promotion
- Monitoring pipelines: Drift detection and alerting
Every production ML system needs orchestration as complexity grows beyond single scripts.
Typical Pipeline Structure
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Ingest │────▶│ Validate │────▶│ Transform │
│ Data │ │ Data │ │ Features │
└─────────────┘ └─────────────┘ └─────────────┘
│
▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Deploy │◀────│ Evaluate │◀────│ Train │
│ Model │ │ Model │ │ Model │
└─────────────┘ └─────────────┘ └─────────────┘
Typical pipeline stages: 1. Data ingestion: Pull data from sources 2. Data validation: Check schema, distributions, quality 3. Feature engineering: Transform raw data to features 4. Training: Model training with hyperparameter tuning 5. Evaluation: Metrics computation, comparison to baseline 6. Validation: Model quality gates before deployment 7. Deployment: Push model to serving infrastructure 8. Monitoring: Track model performance post-deployment
What You Do in Practice
- Define pipeline DAG - Tasks and dependencies
- Choose orchestrator - Airflow, Kubeflow, Prefect based on needs
- Implement tasks - Modular, testable components
- Configure scheduling - Cron expressions, triggers
- Handle dependencies - Task ordering, data dependencies
- Implement error handling - Retries, alerts, fallbacks
- Add observability - Logging, metrics, lineage
- Test pipelines - Unit tests, integration tests
- Version control - Pipeline code in git
- Monitor execution - Dashboards, alerts
Baseline First
Start with Airflow - the most widely adopted orchestrator:
from airflow import DAG
from airflow.operators.python import PythonOperator
from datetime import datetime, timedelta
default_args = {
'owner': 'ml-team',
'retries': 2,
'retry_delay': timedelta(minutes=5),
}
with DAG(
'ml_training_pipeline',
default_args=default_args,
schedule_interval='0 6 * * *', # Daily at 6 AM
start_date=datetime(2024, 1, 1),
catchup=False,
) as dag:
def extract_data():
# Pull data from source
pass
def validate_data():
# Check data quality
pass
def train_model():
# Train and save model
pass
def evaluate_model():
# Compute metrics
pass
extract = PythonOperator(task_id='extract_data', python_callable=extract_data)
validate = PythonOperator(task_id='validate_data', python_callable=validate_data)
train = PythonOperator(task_id='train_model', python_callable=train_model)
evaluate = PythonOperator(task_id='evaluate_model', python_callable=evaluate_model)
extract >> validate >> train >> evaluate
Why Airflow baseline: - Industry standard, large community - Rich ecosystem of operators - Good UI for monitoring - Handles complex dependencies
Orchestrator Options
| Tool | Best For | Pros | Cons |
|---|---|---|---|
| Airflow | General orchestration | Mature, flexible, large community | Complex setup, not ML-native |
| Kubeflow Pipelines | Kubernetes-native ML | ML-focused, good for training | Requires Kubernetes |
| Prefect | Modern Python workflows | Easy to use, good local dev | Smaller community |
| Dagster | Data-centric pipelines | Strong typing, testing | Newer |
| Argo Workflows | Kubernetes jobs | Lightweight, K8s native | Not ML-specific |
| MLflow Pipelines | ML experiments | Integrated with MLflow | Less flexible |
| Vertex AI Pipelines | GCP ML | Managed, integrated | GCP lock-in |
| SageMaker Pipelines | AWS ML | Managed, integrated | AWS lock-in |
Decision guide: - General data + ML? → Airflow - Kubernetes-first, ML focus? → Kubeflow - Modern Python, simpler setup? → Prefect - Cloud-native, managed? → Vertex/SageMaker Pipelines
Kubeflow Pipelines Example
from kfp import dsl
from kfp.dsl import component, pipeline
@component
def load_data() -> str:
# Load and return data path
return "/data/training.csv"
@component
def train_model(data_path: str) -> str:
# Train model and return model path
return "/models/model.pkl"
@component
def evaluate_model(model_path: str) -> float:
# Evaluate and return metric
return 0.95
@pipeline(name='ml-training-pipeline')
def training_pipeline():
data_task = load_data()
train_task = train_model(data_path=data_task.output)
eval_task = evaluate_model(model_path=train_task.output)
Pipeline Design Patterns
Idempotency: Tasks should produce same results when re-run.
def train_model(run_id: str):
# Use run_id for deterministic outputs
model_path = f"/models/{run_id}/model.pkl"
if exists(model_path):
return model_path # Skip if already exists
# ... training logic
Data passing: - Small data: XCom (Airflow), outputs (Kubeflow) - Large data: Write to storage, pass paths
Conditional execution:
with dag:
check_task = check_data_quality()
with conditional(check_task.output == 'pass'):
train_task = train_model()
with conditional(check_task.output == 'fail'):
alert_task = send_alert()
Parallel execution:
# Fan-out pattern
with dag:
prepare = prepare_data()
# Train multiple models in parallel
models = []
for config in ['xgboost', 'lightgbm', 'catboost']:
train = train_model(config=config)
prepare >> train
models.append(train)
# Fan-in: select best
select = select_best_model()
models >> select
Evaluation and Monitoring
| Metric | Description | Target |
|---|---|---|
| Success rate | % successful runs | > 99% |
| Duration | Pipeline run time | Within SLA |
| Task latency | Per-task duration | Identify bottlenecks |
| Retry rate | Tasks requiring retry | < 5% |
| Data freshness | Age of output data | Within requirements |
Monitoring approach: - Dashboard with run history - Alerts on failures - SLA monitoring - Resource utilization tracking
Failure Modes and Debugging Checklist
- [ ] Dependency failures: Upstream task failed
- [ ] Resource exhaustion: OOM, disk full
- [ ] Timeout: Task exceeded time limit
- [ ] Data issues: Missing or corrupt input data
- [ ] Concurrency conflicts: Multiple runs interfering
- [ ] Scheduling drift: Runs delayed, backlog growing
- [ ] Configuration errors: Wrong parameters, paths
- [ ] Infrastructure issues: Cluster unavailable
Production Checklist
Before deployment: - [ ] Pipeline tested end-to-end - [ ] Error handling implemented - [ ] Retries configured appropriately - [ ] Timeouts set for all tasks - [ ] Logging comprehensive - [ ] Alerts configured - [ ] Documentation complete
After deployment: - [ ] Run success rate monitored - [ ] Duration tracked against SLA - [ ] Resource usage monitored - [ ] Alerts responding correctly - [ ] Logs accessible for debugging - [ ] Backfill process documented
Best practices: - [ ] Tasks are idempotent - [ ] Data dependencies explicit - [ ] Secrets managed securely - [ ] Pipeline versioned in git - [ ] Testing in staging environment
Tools and Stack
| Category | Tools |
|---|---|
| Orchestrators | Airflow, Kubeflow, Prefect, Dagster |
| Containerization | Docker, Kubernetes |
| Data validation | Great Expectations, Pandera |
| Experiment tracking | MLflow, W&B |
| Monitoring | Prometheus, Grafana, DataDog |
| CI/CD | GitHub Actions, GitLab CI |
Example Mini-Case
Scenario: E-commerce company needs daily model retraining pipeline for recommendation system.
Requirements: - Daily retraining on new user interactions - Data validation before training - Model evaluation against baseline - Automated deployment if metrics pass - Alerting on failures
Architecture with Airflow:
┌─────────────────────────────────────────────────────────┐
│ Daily Training DAG │
├─────────────────────────────────────────────────────────┤
│ extract_data → validate_data → feature_engineering │
│ ↓ │
│ train_model → evaluate_model → deploy_if_better │
│ ↓ │
│ notify_on_failure (trigger on any failure) │
└─────────────────────────────────────────────────────────┘
Implementation highlights:
# Evaluation with deployment gate
def evaluate_and_deploy(**context):
new_metrics = evaluate_model()
baseline_metrics = get_baseline_metrics()
if new_metrics['auc'] > baseline_metrics['auc'] * 0.99:
deploy_model()
update_baseline_metrics(new_metrics)
return 'deployed'
else:
alert_team('Model did not meet quality threshold')
return 'skipped'
Results: - Pipeline runs daily at 6 AM - Average duration: 45 minutes - Success rate: 99.2% - Model freshness: < 24 hours - Automated deployment: 85% of runs
Related Pages
- Index: ML Field Guide
- MLOps Foundations
- Feature Stores
- Model Monitoring
Further Reading
Try it live
Everything above runs in your browser — open MLOps Lab — Watch Model Drift Get Caught (or Not) and change the parameters while it is running. Nothing is installed, nothing is uploaded, the whole model lives in one tab.
▶ Open MLOps Lab — Watch Model Drift Get Caught (or Not) simulation