Pipeline Anatomy: Intermediate
What you will be able to do
Many Sources, One Curated Layer
Recognize when a shared middle layer becomes necessary and design the three-layer pattern that supports many sources and many consumers.
The Combinatorial Problem
| Architecture | Pipelines Required | Consequence |
|---|---|---|
| Point-to-point: every consumer extracts directly | Sources × Consumers (e.g., 5 × 10 = 50) | Same source extracted N times, inconsistent definitions, brittle |
| Hub-and-spoke: shared curated layer | Sources + Consumers (e.g., 5 + 10 = 15) | One canonical version of each dataset, consistent definitions |
| Layered (raw + curated + serving) | Sources + (curated tables) + Consumers | Decoupling at every layer; debugging follows the layers |
The Three-Layer Pattern
Why the Middle Layer Has to Be Shared
- Three teams compute revenue three different ways
- Source schema changes break N pipelines simultaneously
- New consumers re-implement the same joins from scratch
- Debugging starts with 'whose pipeline owns this column'
- One canonical revenue definition; debates resolved in the curated layer
- Source changes break one pipeline (the extract); curated tables protect downstream
- New consumers read existing curated tables; little new pipeline work
- Debugging follows the layer boundary; ownership is clear
When to Skip the Curated Layer
- ▸Two teams report different numbers for the same metric
- ▸A schema change in a source breaks more than one downstream report
- ▸Analysts ask 'what is the right fact_orders table' and get different answers
- ▸The same five-table join shows up in multiple dashboards' SQL
ETL vs ELT
Distinguish ETL from ELT, explain why cloud warehouses shifted the default, and pick the right model per transform.
| Step | ETL | ELT |
|---|---|---|
| Extract | Pull from source into a staging area | Pull from source into the warehouse |
| Transform | Run on a separate compute layer (Spark, Python, an ETL tool) | Run inside the warehouse using SQL |
| Load | Write the transformed result to the warehouse | Already loaded; transform produces tables in the warehouse |
Why ETL Was the Default
Why ELT Took Over
When ETL Still Wins
- Transform requires non-SQL logic (ML, image, graph)
- PII must be removed before data enters the warehouse
- Source data is too large to land cheaply
- Warehouse compute is significantly more expensive than the alternative
- Cloud warehouse is in use (Snowflake, BigQuery, Redshift, Databricks)
- Transform logic is expressible in SQL or dbt models
- Warehouse compute is elastic and cost-competitive
- Multiple consumers need to inspect the raw data, not just the transformed result
The Hybrid Reality
- ▸The transform is a SQL join that has been rewritten in PySpark
- ▸Engineers maintain a separate compute cluster only for transforms
- ▸The transformed table is loaded back into the warehouse anyway
- ▸Adding a column requires a code change in two systems
- Default to ELT when the warehouse can do the work
- Use ETL for genuinely non-SQL workloads (ML, image, graph, redaction)
- Document which transforms are ETL and which are ELT in the architecture diagram
- Treat ETL versus ELT as a one-time architectural decision; revisit per-transform
- Maintain a Spark cluster for SQL-shaped work because of historical inertia
- Hide the choice in tooling; future maintainers need to see where transforms run
The four roles every pipeline has: a source produces data, transforms reshape it, storage holds it, and a consumer reads it. Data flows left to right.
The DAG: Why Dependencies Form
Read a pipeline as a DAG, identify nodes and edges, and explain why cycles cannot exist in a valid pipeline graph.
Anatomy of a DAG
| Term | Meaning | In a Pipeline |
|---|---|---|
| Node | A unit of work | An extract, a transform, a load, a quality check |
| Edge | A dependency between nodes | B runs after A; B reads what A produced |
| Directed | Edges have direction | Data and dependency flow one way; no read-back |
| Acyclic | No cycles allowed | Cannot have A depends on B depends on C depends on A |
Why Cycles Are Forbidden
- ▸A transform reads from a table that another transform overwrites later in the same run
- ▸A circular foreign key in the data model leaks into the pipeline as a circular dependency
- ▸Two teams add an edge each, neither aware that the new edges close a loop
- ▸A backfill script is added to the production DAG and creates a self-reference
What a DAG Is Not
Reading a DAG
Topological Order: How the Orchestrator Knows What to Run
DAG Boundaries
Reading a Real Pipeline Diagram
Read a real production pipeline diagram with multiple sources, multiple consumers, branches, and joins, and identify cadence, failure behavior, and ownership.
The Diagram
Annotation: Cadence
| Edge | Cadence | Why |
|---|---|---|
| Postgres orders -> raw.orders | Hourly | App writes continuously; hourly is the freshness bar set by finance |
| Stripe API -> raw.payments | Every 15 minutes | Finance needs near-real-time revenue; rate limit allows this cadence |
| Salesforce CRM -> raw.accounts | Daily at 2am | CRM data changes slowly; once a day is more than enough |
| Mobile events Kafka -> raw.events | Continuous (micro-batch every 5 min) | Volume is too high for hourly; streaming consumers expect sub-hour freshness |
Annotation: Failure Behavior
Annotation: Ownership
- ▸The four roles for every box (source, transform, storage, consumer)
- ▸The direction of data flow on every edge
- ▸The cadence of each edge (hourly, daily, continuous, event-triggered)
- ▸The failure behavior at each transform (retry, fail-fast, fail-open)
- ▸The owner of every node so on-call knows who is paged
How to Draw One
One Source, Two Different Consumers
Design a pipeline that serves a dashboard and a feature store from the same source by splitting at the curated layer rather than at ingestion.
The Source
Consumer 1: The Executive Dashboard
Consumer 2: The Feature Store
What the Two Consumers Share
What the Two Consumers Need Differently
| Property | Dashboard | Feature Store |
|---|---|---|
| Output shape | One row per user per day | One row per user, with dozens of feature columns |
| Freshness bar | Daily by 7am Pacific | Daily by 6am, before model training |
| Lookback window | Most recent day; weekly and monthly aggregates pre-computed | Rolling 7, 30, 90 days for every user |
| Compute cost shape | Small daily aggregation | Large rolling-window scan over 90 days |
| Failure tolerance | Stale dashboard for one morning is acceptable | Stale features cause model decisions on outdated data; tighter SLA |
Why the Split Belongs in the Curated Layer, Not Earlier
- Each consumer maintains its own Kafka offsets
- Schema changes coordinated across two consumer teams
- Bot filtering implemented twice, possibly differently
- Backfill requires both consumers to be replayed
- One ingestion job manages Kafka offsets
- Schema changes handled in the single raw landing job
- Bot filtering implemented once in the curated layer
- Backfill replays raw, then both transforms compute from the same data
> A growth-stage company has eight sources, fifty-three transforms, and one hundred dashboards. The architecture diagram on the wall looks like a circuit board. Two engineers have quit because the on-call rotation is unpredictable. The new head of data engineering is asked: 'What is the smallest set of changes that would make this system operable again?'
When one pipeline becomes many, the question is not what to build but how the pieces fit
- Category
- Pipeline Architecture
- Difficulty
- intermediate
- Duration
- 30 minutes
- Challenges
- 0 hands-on challenges
Topics covered: Many Sources, One Curated Layer, ETL vs ELT, The DAG: Why Dependencies Form, Reading a Real Pipeline Diagram, One Source, Two Different Consumers
Lesson Sections
- Many Sources, One Curated Layer (concepts: paMedallion)
A first pipeline is one source, one transform, one consumer. The vocabulary is small enough to fit on a napkin. A real production environment has many of each, and the question changes from 'what should this pipeline do' to 'how do these pipelines fit together so each one does not solve the same problem in a slightly different way.' The answer is almost always a shared middle layer that every pipeline writes to and reads from. Without that shared layer, the same data ends up extracted three time
- ETL vs ELT (concepts: paEltVsEtl)
The two acronyms ETL and ELT differ by a single letter, but the architectural implications are large. ETL extracts data from sources, transforms it on a separate compute layer, and loads the transformed result into the destination. ELT extracts the data, loads it into the destination warehouse first, and runs the transforms inside that warehouse. The order is the entire difference, and that order changes which system bears the cost of the transform work. Why ETL Was the Default Before cloud ware
- The DAG: Why Dependencies Form (concepts: paDagOrchestration)
A pipeline with one transform is a line: source, transform, destination. A pipeline with several transforms that depend on each other is a graph. The data engineering term for the structure is a directed acyclic graph, abbreviated DAG. Directed because data flows one way. Acyclic because no transform may depend, directly or indirectly, on its own output. Every modern orchestration tool, from Airflow to Dagster to Prefect, models pipelines as DAGs because the structure has the right properties: i
- Reading a Real Pipeline Diagram (concepts: paDagOrchestration)
A diagram from a real production environment is denser than the toy diagrams of the beginner tier. It has multiple sources, multiple consumers, branches, joins, and a layered middle. The same reading skills apply, but the eye has to be trained to find the structure. The exercise below walks through a real-shaped diagram and names every element. The Diagram Four sources on the left. Four raw landing zones in S3, partitioned by date or hour. Four curated tables in Snowflake (fct_orders, fct_sessio
- One Source, Two Different Consumers (concepts: paMedallion)
A common architecture problem is one rich source feeding two consumers with different needs. The example here is a single Kafka topic of user activity events being read by two consumers: a daily executive dashboard and a machine learning feature store that powers churn prediction. The same event stream, two completely different shapes at the edge. The Source Each event is small, semi-structured, and produced at a rate of roughly five thousand per second at peak. The Kafka topic has thirty-day re