Start Here
Foundations taught you how data systems work. This course teaches the daily craft of using that knowledge to build pipelines that are correct, maintainable, and trusted. It's the most hands-on course so far — by the end, the components of a real data platform will be sitting in your repo.
What "the craft" is
There's a gap between knowing how a database works and being a data engineer, and this course is that gap. The craft is the set of repeatable skills you apply every day:
- Modeling — shaping data so it's correct, queryable, and keeps its history.
- Moving — getting data in reliably, including capturing every change.
- Transforming — turning raw data into clean, business-ready tables with tested, version-controlled code.
- Storing — choosing where data lives: a warehouse, a lakehouse, a stream.
- Scheduling — running it all on time, in the right order, recovering from failure.
- Proving — testing and monitoring so people can trust the numbers.
Course 3 asked "how does this work?" This course asks "how do I build it well?" Those are different skills. A person can ace a database-internals quiz and still write a fragile pipeline. The craft is judgment — applied repeatedly until it's instinct — and you only get it by building.
The arc of the course
The chapters follow the path data takes through a platform, the same journey you mapped in Course 2's mental model — now you build each stage:
Modeling comes first on purpose: if the shape of your data is wrong, no amount of good tooling downstream will save you. We design, then move, then transform, then operate.
The running example
To keep the course coherent, we build around one familiar scenario: a small GPU-rental marketplace (the same world as the senior Systems Design reference, scaled down to your laptop). It has just enough richness to exercise every skill:
- A
rentalssource table in Postgres (customers renting GPUs by the hour) — the same one you seeded in Course 2. - Reference data that changes over time (GPU prices, customer tiers) — perfect for slowly-changing dimensions.
- A stream of usage events — perfect for the streaming chapter.
You'll model it, ingest it, transform it through medallion layers, store it in a lakehouse, schedule it, and test it. Each chapter adds one real capability to your mini-griddp repo.
What you'll use
Everything is the free, local stack from Course 2 — now put to serious work:
| Tool | Role in this course | Chapters |
|---|---|---|
| Postgres | The source / OLTP system you ingest from | 01, 05, 06 |
| DuckDB | Your analytics warehouse & lakehouse query engine | 02–04, 08 |
| dbt | Version-controlled SQL transformations | 04, 07, 11 |
| Parquet + a table format | Lakehouse storage | 08 |
| Redpanda (Kafka API) | Your streaming bus | 09 |
| Dagster | Orchestration — scheduling & dependencies | 10 |
If anything here is unfamiliar, it was installed in Course 2; revisit that course's setup chapters as needed.
How these chapters work
Same rhythm as before, but heavier on building. Each chapter teaches a concept, then has you do it — write the model, run the pipeline, see the result. Watch for the Setup boxes (what to have running), the runnable code blocks (type them), the "✓ You should see" checkpoints (confirm before moving on), and the "✓ Check yourself" + exercise at the end. Commit your work to mini-griddp as you go — this is the course where your portfolio really starts to take shape.
✓ Check yourself
- Can you name the six skills that make up "the craft"?
- Do you see why modeling comes before moving and transforming?
- Is your Course 2 stack (Postgres + DuckDB, your
mini-griddprepo) still working? If not, fix that first.
Exercise — Warm up your environment (5 minutes)
Before chapter 01, confirm your stack is alive: bring up Postgres, confirm the rentals table from Course 2 still has rows, and confirm DuckDB runs.
# from your mini-griddp repo
docker compose up -d # start Postgres
docker compose exec -T postgres \
psql -U postgres -c "SELECT count(*) FROM rentals;" # should print a count
python -c "import duckdb; print(duckdb.sql('SELECT 42').fetchone())" # (42,)You should see a row count from Postgres and (42,) from DuckDB. If either fails, revisit Course 2, Chapter 05 — a working stack is the prerequisite for everything here.
Next
We start where every good platform starts: with the shape of the data. First, the relational modeling and normalization that keep a transactional source clean. → Data Modeling I — Relational & Normalization