The course
Four modules, worked in order. Each ends with code you wrote and tests that pass.
4 modules24 steps6 hr 56 min
01 · Foundations
OverviewReliability, scalability and maintainability, defined precisely enough to argue about — and to measure.
The thing you draw as one box on the architecture diagram is six systems in a trenchcoat, and you are the one holding it together.
A reliable system is not one where nothing goes wrong. It is one where things go wrong constantly and the user never finds out.
"It needs to scale" is not a requirement. A load parameter is: a number that, if it doubled, would force you to change the design.
Response time is a distribution, not a number. Once you see that, tail latency stops being a nerdy detail and becomes the thing your users actually experience.
Most of what a system costs is spent after it is built. Operability, simplicity and evolvability are the three things that decide how much.
Turn a pile of raw response times into the summary an on-call engineer can act on — and the SLO verdict that follows from it.
Written exercises with worked answers, for the questions code cannot ask.
02 · Data Models
OverviewThe shape you force your data into decides what is easy, what is slow, and what is impossible. Choose it on purpose.
Every layer of a system hides the one below it. The data model is the layer you cannot hide, because it decides which future questions are cheap to ask.
Objects in memory are trees. Relational tables are not. Everything people love and hate about ORMs lives in that gap.
Every document model eventually grows a reference, then a second one, then an application-level join loop. This is the oldest argument in databases and it has already happened twice.
Declarative queries hide the access path — which is exactly why the database can get faster while your code stays still.
Some questions are about the connections rather than the things. Once traversal depth becomes a variable, both documents and tables start straining.
Answer the questions a relational schema struggles with — reachability at unknown depth, shortest paths, and overlapping tenures — by walking edges yourself.
Written exercises with worked answers, for the questions code cannot ask.
03 · Storage
OverviewWhat a database actually does with your bytes — logs, indexes, B-trees, LSM-trees — and why the answer depends on whether you are writing or reading.
Two lines of shell make a real database. Understanding exactly why it becomes unusable is the whole of this module in miniature.
Keep a map from key to file offset and reads become one seek. Then count how much memory that map needs, and try a range query.
One change — keep each segment sorted by key — fixes the memory limit and the range-query limit at once, and gives you the LSM-tree.
The other answer to the same problem — update pages in place instead of merging logs — and the three amplifications that decide which one you want.
The checkout page and the Monday-morning dashboard want opposite physical layouts. That is why most companies run two databases and copy data between them.
The two-line database, done properly — append-only log, in-memory index, tombstones, and compaction that never mutates what it has already written.
Sorting bought a sparse index and a streaming merge. Write both, including the tombstone rule that stops deleted records rising from the dead.
Written exercises with worked answers, for the questions code cannot ask.
04 · Encoding
OverviewData outlives the code that wrote it. How to change a schema on a Tuesday without taking the site down.
For the length of a deploy, old code and new code run side by side against the same data. Everything about schema change follows from that one fact.
Text formats are readable, universal, and quietly expensive. Knowing exactly which of those costs matter to you is the whole decision.
One idea — identify fields by number, not by name — is what makes a binary format safe to evolve. Everything Protobuf and Avro do follows from it.
Through a database, through a service, through a message queue — compatibility looks different in each, and the differences are all about who upgrades when.
Build the format from lesson 3 — varints, tags, length prefixes — then use it to reproduce the silent data-loss bug and fix it.
Written exercises with worked answers, for the questions code cannot ask.