Week 1 · Ingest anything › Day 1
Day 1. The shape of a data platform
By the end of today you can
- Draw the six stages of the pipeline and name a tool for each
- Explain ETL vs ELT and when each wins
- Explain raw, staging and mart layers and why raw is immutable
- Generate the course data and describe what arrives each morning
1. Why this matters
When an interviewer says "walk me through a pipeline you built", they are not asking for a tool list. They want to hear that you understand where data comes from, what can go wrong at each hop, and how you'd know. Today you build that mental map. Everything in the next 48 days hangs on it.
2. The six stages
| Stage | Question it answers | Core tool in this course | Alternatives you'll meet |
|---|---|---|---|
| Ingest | What arrived, from where, when? | Python (imaplib / Microsoft Graph, pathlib, paramiko, requests) | dlt, Airbyte, Meltano, rclone |
| Clean | Is it typed, valid, de-duplicated? | Polars, DuckDB, pandera, Claude Code | pandas, Great Expectations, Soda |
| Orchestrate | What runs when, in what order, and what happens on failure? | Dagster | Airflow, Prefect, Mage, Kestra, cron |
| Load | Where does it live permanently? | Azure SQL Database | Postgres, DuckDB/MotherDuck, ClickHouse, Snowflake, BigQuery |
| Model | What shape makes questions easy and answers consistent? | SQL + dbt | SQLMesh, plain views |
| Deliver | Who sees what, how, and how often? | Power BI | Metabase, Superset, Evidence, emailed PDFs |
Two things run across all six: observability (logs, freshness, row counts, lineage) and governance (who can see what, where secrets live, how changes are reviewed).
3. ETL vs ELT
ETL transforms before loading: Python cleans the file, then writes finished tables. ELT loads raw data first, then transforms inside the warehouse with SQL. Modern teams mostly do ELT with a Python edge: Python handles what SQL is bad at (parsing emails, Excel, encodings, APIs), loads lightly-typed raw tables, and SQL/dbt does the business logic where it's visible, testable and fast.
Maths and principle
Principle: a pipeline is a composition of functions, and you want each function to be pure (same input, same output) so you can rerun any step safely.
Equation: \(\text{mart} = M(S(R(\text{source}, t)))\) where \(R\) = land raw at time \(t\), \(S\) = standardise, \(M\) = model. If \(R\) is stored immutably, you can recompute \(S\) and \(M\) any time without going back to the source.
Analogy: in physics you keep the raw detector readings and re-run calibration when you find a better constant. You never overwrite the readings. Where it breaks: sources that only give you "current state" (a product price table) lose history unless you snapshot it.
Try it: a bug in \(S\) was live for 10 days. With immutable raw, how many source re-pulls do you need to fix history? (Zero: rerun S and M over the 10 raw partitions.)
4. Layers: raw → staging → marts
- Raw (bronze / landing): an exact copy of what arrived, plus metadata (source, received time, file hash). Append-only. Never edited.
- Staging (silver): one cleaned, typed table per source entity. Column names standardised, duplicates removed, bad rows quarantined.
- Marts (gold): star schemas and aggregates shaped for questions:
fct_sales,dim_store,dim_date.
The 5-year lens
The raw layer is your alibi. When finance says "your dashboard said $41,200 for store R107 but the store says $43,900", you need to show exactly which files you received, when, and what was in them. Teams that skip raw end up arguing from memory. Also: storage is cheap, re-requesting data from a vendor is not, and some sources (emails, API windows) can't be re-pulled at all after 30–90 days.
5. What a morning looks like
At 06:00 the sales emails start arriving. At 06:30 the POS exports sync to the shared drive. The hotel PMS pushes its extract to SFTP around 04:00, but sometimes the upload is still running at 06:00. The ad API's numbers for yesterday keep changing until about noon (late conversions). Reports must be in managers' inboxes by 08:00.
That timeline is the real design brief. It decides your schedules, sensors, freshness checks and the "data as of" label on every report.
Lab: generate and explore the course data (about 2 hours)
- Create a folder
~/p2dand copystarter/generate_data.pyinto it. - Make a virtual environment and install basics:
python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate pip install pandas numpy openpyxl python generate_data.py --start 2026-09-01 --days 30 --out ./data - Explore each landing area and fill in this table in a file
notes/sources.md:
| Source | Path | Format | Grain (one row = ?) | Arrives | Faults you can spot |
|---|---|---|---|---|---|
| Retail sales | landing/email_inbox |
.eml with CSV/XLSX | ? | ? | ? |
| QSR POS | landing/shared_drive/qsr/<date> |
CSV | ? | ? | ? |
| Hotel PMS | landing/sftp/hotel |
pipe-delimited | ? | ? | ? |
| Ads | landing/api/ads |
paginated JSON | ? | ? | ? |
- Open one
.emlin a text editor. Find the headers, the MIME boundary and the base64 attachment. - Draw the six-stage diagram for this company on paper or in excalidraw.com. Photograph it into
notes/.
Ship
git init, commit notes/sources.md and your diagram: docs: map sources and pipeline stages.
Go deeper
- Joe Reis & Matt Housley, Fundamentals of Data Engineering (O'Reilly), chapters 1–3: the lifecycle model this course follows.
- Dagster docs, "What is an asset?" (skim now; Week 3 goes deep).
Check yourself
1. A vendor API only keeps 30 days of history. Your cleaning code had a bug for 45 days. What design would have saved you?
With raw stored, you just rerun the clean and model steps over the stored responses. The API window no longer matters.
2. Which job belongs in Python rather than SQL in a typical ELT design?
SQL is great at set logic on tables. Parsing MIME emails, Excel files and APIs is Python's job.
3. What is the "grain" of the hotel PMS extract?
Look at the data: cancelled bookings reappear with the same booking_id. That makes it a change feed, which you'll upsert in Week 3.