learn-data-engineering-with-phoebe / Builder session 10 of 10
Learn Data Engineering with Phoebe · Builder track · Session 10 of 10

Capstone: the whole pipeline

Ten sessions of pieces, assembled into one running pipeline. Today you build Daybreak's production-shaped pipeline end to end: extract from the source, land it as Parquet, transform it defensively, store it partitioned, and serve the exact table the warehouse loads. Every stage you learned separately, now wired together and running live in this tab. This is the pipeline that feeds a warehouse.

🔴 Builder track Practitioners: DE · analysts · DS · PMs Runs in your browser · DuckDB 60 min · capstone
0-6 · Brief & recap 6-18 · Extract + land 18-48 · Transform + serve 48-60 · Wrap & next
Part 0

The brief

Daybreak's warehouse (built in the sibling course) needs a reliable feed. That is what you deliver today. The brief is simple to state and real to build: take raw source data and produce a clean, served table the warehouse can load - through the same stages a petabyte pipeline uses, just at a scale that runs in a browser. Three demos take you across the whole lifecycle, each self-contained because the database is fresh every run.

Live - presented in session Self-study - read after class ▶ Live pipeline - editable & runnable Official sources covered
★ What you prove today That you can build the pipeline that feeds a warehouse: extract from a source you do not control, land raw data safely, transform it defensively and idempotently, store it partitioned, and serve the clean output the warehouse loads. The full data engineering lifecycle, in one runnable pipeline you built yourself.
Part 1 · the whole pipeline, one picture

Architecture recap: b2 through b9 5 min live

Everything you learned as a separate session is one stage of a single pipeline. Here is the whole thing, with the session that taught each stage marked. Today's demos walk it left to right, from Daybreak's source to the served table the warehouse picks up. This is a doing session - read the map once, then build.

Source to warehouse, stage by stage Source OLTP Extract b2 b3 b6 Land b4 Parquet Transform b5 b9 Store b7 b8 Serve b10 Warehouse learn-data-warehouse loads this DE owns everything left of the warehouse: extract, land, transform, store, serve. The warehouse models what you serve (star schema, SCDs). Scheduling and monitoring live in learn-dataops.
🔍 Click to zoom - the full pipeline b2 to b9, assembled and served to the warehouse in b10
LiveHow the three demos map to the pipeline3 min

The build splits cleanly across the lifecycle:

  • Demo 1 - Extract + land: pull three source tables and write each to Parquet. The ingestion and storage stages (b2-b4).
  • Demo 2 - Transform defensively: parse and clean, quarantine bad rows, join for revenue, build an idempotent daily table. The transform stage with b9's reliability seams.
  • Demo 3 - Serve: build the final clean table and write it as a partitioned Parquet dataset the warehouse loads. The serving stage and the handoff (b7-b10).

Each demo re-seeds a fresh database, so each one re-extracts what it needs. That is realistic - a real run starts from the source too.

Demo 1 of 3

Extract + land ★ 12 min · everyone builds

The ingestion and storage stages. Extract three source tables - orders, order_items, customers - and write each to a Parquet file in the landing zone, then read them back with a counts summary to prove the data now lives outside the source system.

Extract: read each source table straight from Daybreak's OLTP system.

Land: COPY each to its own Parquet file - the raw landing zone, untouched.

Verify: read the files back and count rows per table. The data has left the source.

-- EXTRACT + LAND: pull three source tables, write each to Parquet
COPY (SELECT * FROM orders)      TO 'orders.parquet'      (FORMAT PARQUET);
COPY (SELECT * FROM order_items) TO 'order_items.parquet' (FORMAT PARQUET);
COPY (SELECT * FROM customers)   TO 'customers.parquet'   (FORMAT PARQUET);

-- read the landing zone back with a counts summary
SELECT 'orders'      AS table_name, count(*) AS rows FROM 'orders.parquet'
UNION ALL
SELECT 'order_items', count(*)                FROM 'order_items.parquet'
UNION ALL
SELECT 'customers',   count(*)                FROM 'customers.parquet'
ORDER BY table_name;
Why land raw, untouched, first The landing zone keeps a faithful copy of the source before you change anything. If a transform is wrong, you re-run from the landed files - no need to hit the source again. This raw-first layer is why b4 taught Parquet before b5 taught transforms.
Demo 2 of 3

Transform defensively ★ 15 min · everyone builds

The transform stage, hardened with b9's reliability seams. The database is fresh, so this box re-extracts quickly first, then parses dates defensively, keeps only completed orders, joins to items for revenue, and builds an idempotent daily table. Run the whole box twice - the counts stay identical, proving the write is safe to repeat.

Re-extract: land orders and items again (fresh DB), the realistic start of any run.

Clean: TRY_CAST the date so bad values drop out, filter to completed orders.

Build idempotently: CREATE OR REPLACE the daily_revenue table. Re-running replaces, never doubles.

-- re-extract (fresh DB): land orders + items
COPY (SELECT * FROM orders)      TO 'orders.parquet'      (FORMAT PARQUET);
COPY (SELECT * FROM order_items) TO 'order_items.parquet' (FORMAT PARQUET);

-- defensive clean: parse dates, drop unparseable rows, keep completed
CREATE OR REPLACE TABLE clean_orders AS
SELECT order_id, customer_id,
       TRY_CAST(order_date AS DATE) AS order_date,
       status, channel
FROM 'orders.parquet'
WHERE TRY_CAST(order_date AS DATE) IS NOT NULL
  AND status = 'completed';

-- join to items for revenue, aggregate to a daily table (idempotent)
CREATE OR REPLACE TABLE daily_revenue AS
SELECT o.order_date                                AS day,
       round(sum(oi.quantity * oi.unit_price), 2)  AS revenue,
       count(DISTINCT o.order_id)                  AS orders
FROM clean_orders o
JOIN 'order_items.parquet' oi ON o.order_id = oi.order_id
GROUP BY o.order_date;

-- run twice - these numbers do not change
SELECT count(*) AS days, round(sum(revenue), 2) AS total_revenue FROM daily_revenue;
Real world

Idempotency is what lets a pipeline be re-run safely. When a nightly job fails halfway and someone re-triggers it at 6am, CREATE OR REPLACE means the target is rebuilt cleanly, not double-counted. This one habit turns a fragile pipeline into one DataOps can schedule and retry without fear.

✗ APPEND on re-run job fails halfway, re-triggered appends again on top of itself revenue is double-counted ✓ CREATE OR REPLACE re-triggered at 6am, safely target rebuilt cleanly counts identical, run once or twice Run the box twice - the counts stay identical, proving the write is safe for DataOps to retry.
🔍 Click to zoom - CREATE OR REPLACE is what lets DataOps retry without fear
Demo 3 of 3

Serve ★ 15 min · everyone builds

The serving stage and the handoff. Build the final clean served table - daily revenue by channel - then write it as a partitioned Parquet dataset (one folder per month) and read one partition back. This is exactly the output learn-data-warehouse's loader picks up. The DE job ends here.

Serve: build the final clean table the warehouse consumes - revenue by day and channel.

Partition: COPY it out partitioned by month, the layout that keeps warehouse loads fast (b7).

Hand off: read one month's partition back - the exact slice the warehouse loader reads.

-- SERVE: build the final clean table the warehouse will load
CREATE OR REPLACE TABLE served AS
SELECT CAST(o.order_date AS DATE)                         AS day,
       strftime(CAST(o.order_date AS DATE), '%Y-%m')      AS month,
       o.channel,
       round(sum(oi.quantity * oi.unit_price), 2)         AS revenue
FROM orders o
JOIN order_items oi ON o.order_id = oi.order_id
WHERE o.status = 'completed'
GROUP BY day, month, o.channel;

-- write March's partition to its own Parquet file (hand-partitioned by month)
COPY (SELECT * FROM served WHERE month = '2026-03')
  TO 'served_2026_03.parquet' (FORMAT PARQUET);

-- read that partition back - the slice the warehouse loader picks up
SELECT * FROM 'served_2026_03.parquet'
ORDER BY day, channel;
This is the handoff line The partitioned served_revenue dataset is where data engineering stops and the warehouse begins. The warehouse course models this into facts and dimensions; you have delivered it clean, partitioned, and ready to load. Pipeline done.
Part 3 · what you know, and where next

Wrap: the whole lifecycle, built 4 min live

You built the data engineering lifecycle end to end, on a real engine, against a source you did not control. That is the job. Here is what you now hold, how it pairs with the executive a-track twin, and honestly where this course stops.

Self-studyWhere to go next, and the honest gaps3 min read

The builder track (b1-b10) gave you the hands; the executive a-track gives leaders the same lifecycle as decisions and tradeoffs without the SQL. Together they cover the craft and the judgement. From here:

Needs other tooling orchestration, DAGs CI/CD, monitoring, alerting live Spark and Kafka clusters What b1 to b10 built extract from a live source transform defensively, idempotently partition and serve to the warehouse The pipeline logic transfers to every tool and scale; orchestration and monitoring live in learn-dataops.
🔍 Click to zoom - the pipeline logic transfers, orchestration lives elsewhere
  • learn-data-warehouse: models the served table you just built into star schemas, SCDs, and marts. It picks up exactly where b10 stops.
  • learn-dataops: schedules, monitors, tests, and deploys the pipeline you built. It operates what you engineered.
  • learn-sql: the query language underneath every demo here, taught from the ground up.
The honest gap list This course did not cover orchestration (scheduling, DAGs), CI/CD, production monitoring and alerting, or live Spark and Kafka clusters - those need infrastructure a browser cannot host, and they live in learn-dataops. What you built is the pipeline logic itself, which is the part that transfers to every tool and every scale.
Homework

Take it off the page ◐ 45-60 min total

Source material

Official sources covered

This capstone assembles the working core of the DeepLearning.AI Data Engineering Professional Certificate (Joe Reis) and Reis & Housley's Fundamentals of Data Engineering into one end-to-end build. Certificates, cloud labs, and videos stay on the official platforms. This page covers:

Fundamentals of Data Engineering (Reis & Housley) - the full lifecycleAll demos · generation to serving, assembled end to end
DLAI Introduction to Data Engineering - M4: an end-to-end pipelineDemos 1-3 · the complete extract-land-transform-serve build
DLAI Source Systems + Storage & Queries - appliedDemos 1, 3 · extraction, Parquet landing, partitioned serving
Check yourself

Three questions before you go 🎯 ◐ 90 seconds

1 · What is the stage order of the pipeline you built today?

You extract from the source, land it raw as Parquet, transform it defensively, store it partitioned, and serve the clean table. Same generation-to-serving lifecycle from b1, now built end to end.

2 · Why land raw data as Parquet before transforming it?

The raw landing zone preserves the source as-received. If a transform is wrong, you rebuild from the landed files instead of re-extracting - cheaper, safer, and kinder to a source you do not control.

3 · Which stage is the handoff to the warehouse?

Serving is where data engineering ends. The clean, partitioned served_revenue dataset is the front door of the warehouse, which then models it into facts and dimensions (learn-data-warehouse).

The pipeline in 8 lines · pin this

1 · ExtractPull data out of the source system you do not control. Taught in b2 (connect) and b3 (ingestion).
2 · Land as ParquetWrite raw data to columnar files, untouched, as the base for everything after. Taught in b4.
3 · TransformClean, cast, join, and aggregate the landed data into trustworthy shapes. Taught in b5.
4 · Stream / CDCCapture change as it happens for sources that never sit still. Taught in b6.
5 · Store partitionedLay files out by a key (month) so reads scan only what they need. Taught in b7.
6 · Process at scaleOne machine crushes most data; reach for a cluster last. Taught in b8.
7 · Defend the seamsQuarantine bad rows, assert schema, make writes idempotent. Taught in b9.
8 · Serve to warehouseDeliver the clean, partitioned table the warehouse loads. Built in b10 - the handoff line.