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.
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.
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.
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;
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;
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.
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;
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.
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:
- 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.
Take it off the page ◐ 45-60 min total
- Install real DuckDB (duckdb.org) and rebuild the capstone on your laptop - the same three scripts, running natively.
- Point the served Parquet dataset at a real object store (an S3 or GCS bucket) instead of a local folder, and read a partition back from there.
- Swap Daybreak for a source of your own: a CSV export, an app database dump. Run it through extract, land, transform defensively, serve.
- Add a schema check to Demo 2 that fails loudly if the source drops a key column, then hand the whole thing to a teammate to run.
- Write the one-paragraph runbook a DataOps engineer would need to schedule your pipeline: what it reads, what it writes, and how to tell it succeeded.
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:
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).