A data pipeline moves and transforms data: from sources, through stages, to destinations. The patterns that work in production differ from the textbook ETL examples. Real pipelines must handle failures, late-arriving data, schema changes, retries, and observability.
This page covers the patterns that hold up.
Most pipelines have:
The most important property. Running the same pipeline twice should produce the same result.
Why it matters:
Idempotency requires:
Anti-patterns:
Most pipelines partition by date:
data/
events/
date=2026-04-25/
date=2026-04-26/
date=2026-04-27/
Each partition is independent. Re-running just 2026-04-26 doesn't affect other dates. Failures isolate to specific partitions.
Partition keys vary:
Real-world data arrives late. An event from 2026-04-25 might appear in your source on 2026-04-27.
Strategies:
The right approach depends on data volume and timeliness requirements. Most pipelines need to handle late data; pretending it doesn't exist produces incorrect analytics.
Source data structure changes. Field added, type changed, field renamed.
Patterns:
For data lakes (S3 + Parquet), schema-on-read is common. For warehouses, schema-on-write.
Either way, plan for schema changes. They will happen.
The scheduler that runs pipelines, manages dependencies, retries failures.
The dominant choice. DAG (Directed Acyclic Graph) of tasks; Python-based.
Pros: powerful; large community; many operators. Cons: heavyweight; UI is dated; running it well requires real ops investment.
Modern alternatives. Python-based; emphasize developer ergonomics; cleaner UIs.
For warehouse-resident transformations. Different role than orchestration; sometimes paired with Airflow. See DbtAndAnalyticsEngineering.
AWS Step Functions, GCP Cloud Composer (managed Airflow), Azure Data Factory. Less ops; cloud-specific.
For most teams, managed Airflow or one of the modern alternatives is the right choice.
Pipelines fail in subtle ways. Without observability, failures are silent.
Required:
Tools: dbt has tests; Great Expectations and Soda for explicit data quality; OpenLineage for cross-tool lineage.
Without these, "is the pipeline OK?" is unanswerable.
Re-running pipelines for past data. Common reasons:
Designing for backfill:
Backfills that take a week to plan are common. Designing for them up front saves time.
Two paradigms:
Pipelines run on a schedule. Daily, hourly, every 15 minutes. Process accumulated data.
Pros: simpler; recovery is easier; tooling is mature. Cons: latency = batch interval.
Pipelines run continuously. Each event processed as it arrives.
Pros: low latency. Cons: complex; harder to debug; harder to backfill.
Most pipelines should be batch. Stream when latency genuinely matters (real-time fraud, real-time recommendations).
The "Lambda architecture" — batch + streaming both running the same logic — has fallen out of favor; modern systems use one or the other.