How-To
Data Pipeline ETL MLOps

How to Build Scalable AI Data Pipelines

Step-by-step guide to building production-ready data pipelines for machine learning.

Emma Richardson
4 min read
How to Build Scalable AI Data Pipelines

Data pipelines are the foundation of machine learning systems. This guide shows you how to build scalable, maintainable pipelines.

Architecture Overview

A complete data pipeline includes:

Data Sources → Ingestion → Processing → Validation → Storage → ML Model

Step 1: Define Data Requirements

Document what your model needs:

Data Requirements:
  - Source: User activity logs
  - Format: JSON
  - Volume: 1M records/day
  - Latency: Real-time
  - Schema:
    - user_id: string
    - action: enum
    - timestamp: datetime
    - metadata: object

Step 2: Implement Data Ingestion

From Databases

import pandas as pd
from sqlalchemy import create_engine

# Connect to database
engine = create_engine('postgresql://user:password@localhost/dbname')

# Read data
df = pd.read_sql_query('SELECT * FROM events', engine)

From APIs

import requests

def fetch_from_api(url, params):
    response = requests.get(url, params=params)
    data = response.json()
    return data

From Files

# Read CSV
df = pd.read_csv('data.csv')

# Read JSON
df = pd.read_json('data.jsonl', lines=True)

# Read Parquet
df = pd.read_parquet('data.parquet')

Step 3: Data Processing

Cleaning

def clean_data(df):
    # Remove duplicates
    df = df.drop_duplicates()
    
    # Handle missing values
    df = df.fillna(method='forward_fill')
    
    # Remove outliers
    Q1 = df['value'].quantile(0.25)
    Q3 = df['value'].quantile(0.75)
    IQR = Q3 - Q1
    df = df[(df['value'] > (Q1 - 1.5 * IQR)) & (df['value'] < (Q3 + 1.5 * IQR))]
    
    return df

Transformation

def transform_data(df):
    # Convert types
    df['timestamp'] = pd.to_datetime(df['timestamp'])
    
    # Create features
    df['hour'] = df['timestamp'].dt.hour
    df['day_of_week'] = df['timestamp'].dt.dayofweek
    
    # Normalize
    from sklearn.preprocessing import StandardScaler
    scaler = StandardScaler()
    df[['value']] = scaler.fit_transform(df[['value']])
    
    return df

Step 4: Data Validation

def validate_data(df):
    # Check schema
    assert set(df.columns) == EXPECTED_COLUMNS
    
    # Check data types
    for col, dtype in EXPECTED_TYPES.items():
        assert df[col].dtype == dtype
    
    # Check for missing values
    assert df.isnull().sum().sum() == 0
    
    # Check value ranges
    assert (df['value'] >= MIN_VALUE).all()
    assert (df['value'] <= MAX_VALUE).all()
    
    return True

Step 5: Store Processed Data

# Store in Parquet (efficient)
df.to_parquet('processed_data.parquet')

# Store in database
df.to_sql('processed_events', engine, if_exists='append')

# Store in data warehouse
df.to_csv('s3://bucket/data/processed_data.csv')

Step 6: Orchestrate Pipeline

Using Apache Airflow:

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

dag = DAG(
    'data_pipeline',
    default_args={'owner': 'ml_team'},
    schedule_interval='@daily',
    start_date=datetime(2026, 1, 1)
)

ingest_task = PythonOperator(
    task_id='ingest_data',
    python_callable=fetch_from_source,
    dag=dag
)

process_task = PythonOperator(
    task_id='process_data',
    python_callable=process_data,
    dag=dag
)

validate_task = PythonOperator(
    task_id='validate_data',
    python_callable=validate_data,
    dag=dag
)

ingest_task >> process_task >> validate_task

Step 7: Monitor Pipeline Health

class PipelineMonitor:
    def __init__(self):
        self.metrics = {}
    
    def record_metric(self, name, value):
        self.metrics[name] = value
    
    def check_health(self):
        # Check data freshness
        assert age_of_data < MAX_AGE
        
        # Check data completeness
        assert completeness > MIN_COMPLETENESS
        
        # Check data quality
        assert quality_score > MIN_QUALITY

Tools and Technologies

ToolPurposeUse Case
AirflowOrchestrationComplex workflows
PrefectOrchestrationModern/flexible
dbtTransformationSQL-based
Apache SparkProcessingLarge-scale
PandasProcessingMedium-scale

Best Practices

  1. Idempotency: Pipeline can be re-run safely
  2. Monitoring: Track pipeline health continuously
  3. Error Handling: Graceful failures with alerts
  4. Documentation: Clear data lineage and ownership
  5. Version Control: Track schema changes
  6. Testing: Validate data at each step
  7. Incremental Processing: Only process new data

Scalability Considerations

  • Volume: Use distributed systems (Spark, Dask)
  • Velocity: Stream processing (Kafka, Flink)
  • Variety: Handle multiple data formats
  • Cost: Use cost-effective storage (S3, GCS)

Common Pitfalls

  • No monitoring: Can’t detect data quality issues
  • Hard-coded paths: Breaks with environment changes
  • No error handling: Pipeline fails silently
  • No data versioning: Can’t reproduce results

Conclusion

Well-designed data pipelines are essential for successful ML systems. Invest in proper architecture, monitoring, and tooling to ensure reliable data flow.