System design in 60 days
A free, hands-on system design course. Sixty days of work, each day about four hours, done at whatever pace suits you, one a day or one a week. You build small, broken, real systems, break them harder, then measure what happened. Every day has reading, drills, a lab with starter code, full solutions, and example posts so you can learn in public.
Start at Day 1 Latest: Day 60 Track your progress How to follow along
Who this is for
Anyone who can write a little Python and wants to actually understand system design, not memorise answers to “design Twitter.” No prior system design knowledge is assumed. Every term is explained the first time it shows up. The labs use only Python’s standard library, so there’s nothing to install, and they run on a laptop.
Most people learn system design by watching videos about designing big systems, then freeze in an interview because they memorised an answer instead of a method. This course works the other way round. You predict a number, measure it on your own machine, and the gap between the two is the lesson. Theory shows up when you need it to explain a number you just saw.
The eight weeks
| Week | Days | Topic |
|---|---|---|
| Week 1 | 1 to 7 | Ground truth: latency, estimation, networking, queues, APIs, load balancing |
| Week 2 | 8 to 14 | Storage: B-trees, LSM trees, indexes, transactions, replication |
| Week 3 | 15 to 21 | Caching and the CDN |
| Week 4 | 22 to 28 | Async: queues, logs, idempotency, backpressure |
| Week 5 | 29 to 35 | Distributed systems and the classic papers |
| Week 6 | 36 to 42 | AI systems: inference serving, RAG, agents, token economics |
| Week 7 | 43 to 49 | Production: observability, SLOs, rate limits, cost |
| Week 8 | 50 to 60 | Synthesis, mock designs, capstone |
New days are published as they’re written. Each one shows up in the sidebar under its week.
Days so far
| Day | Topic | Lab | Posts |
|---|---|---|---|
| Day 1 | How slow is slow? Measure the storage hierarchy | Results | Posts |
| Day 2 | Estimation vs reality, a million-row database | Template | Posts |
| Day 3 | What happens when you type a URL, counted in round trips | Template | Posts |
| Day 4 | Latency, throughput and the queue | Template | Posts |
| Day 5 | Designing an API: offset vs cursor pagination | Template | Posts |
| Day 6 | More than one server: load balancing and failure | Template | Posts |
| Day 7 | Your first real design: a URL shortener | Design template | Posts |
| Day 8 | How a row sits on disk: pages, row vs column stores | Template | Posts |
| Day 9 | B-trees vs LSM trees: why one hates random writes | Template | Posts |
| Day 10 | Indexes in depth: composite, covering, and ignored | Template | Posts |
| Day 11 | Transactions and the lost update | Template | Posts |
| Day 12 | Replication and lag | Template | Posts |
| Day 13 | Partitioning and sharding: the hot shard | Template | Posts |
| Day 14 | Designing a storage layer for a messaging app | Design template | Posts |
| Day 15 | Caching and the cache-aside pattern | Template | Posts |
| Day 16 | Eviction and the working set (LRU) | Template | Posts |
| Day 17 | The thundering herd | Template | Posts |
| Day 18 | Hot keys and the celebrity problem | Template | Posts |
| Day 19 | Redis internals and pipelining | Template | Posts |
| Day 20 | The CDN and cache invalidation | Template | Posts |
| Day 21 | Designing a news feed | Design template | Posts |
| Day 22 | Sync vs async, and why queues exist | Template | Posts |
| Day 23 | The log as a primitive | Template | Posts |
| Day 24 | Kafka, partitions and consumer groups | Template | Posts |
| Day 25 | Delivery semantics and idempotency | Template | Posts |
| Day 26 | The outbox pattern | Template | Posts |
| Day 27 | Backpressure and load shedding | Template | Posts |
| Day 28 | Designing a notification system | Design template | Posts |
| Day 29 | Failure, time, and the eight fallacies | Template | Posts |
| Day 30 | CAP, for real, and PACELC | Template | Posts |
| Day 31 | Replication and quorums | Template | Posts |
| Day 32 | Consensus and Raft | Template | Posts |
| Day 33 | Logical clocks | Template | Posts |
| Day 34 | The papers: Dynamo, Bigtable, Spanner | Summaries | Posts |
| Day 35 | Designing a distributed key-value store | Design template | Posts |
| Day 36 | How LLM inference works: prefill, decode, memory-bound | Template | Posts |
| Day 37 | The KV cache and continuous batching | Template | Posts |
| Day 38 | Vector search and embeddings | Template | Posts |
| Day 39 | RAG, and why it fails at retrieval | Template | Posts |
| Day 40 | Agents, and why the token bill explodes | Template | Posts |
| Day 41 | Serving: caching, limiting and fallback | Template | Posts |
| Day 42 | Designing a production AI chat system | Design template | Posts |
| Day 43 | Observability: logs, metrics, traces | Template | Posts |
| Day 44 | SLOs and error budgets | Template | Posts |
| Day 45 | Rate limiting: token, leaky, windows | Template | Posts |
| Day 46 | Multi-tenancy and the noisy neighbour | Template | Posts |
| Day 47 | Security boundaries: signing, authz, IDOR | Template | Posts |
| Day 48 | Cost and capacity planning | Template | Posts |
| Day 49 | Designing a multi-tenant SaaS | Design template | Posts |
| Day 50 | The framework: how to run a 45-minute design | Framework sheet | Posts |
| Day 51 | Mock: a URL shortener, timed | Mock brief | Posts |
| Day 52 | Mock: a chat system like WhatsApp | Mock brief | Posts |
| Day 53 | Mock: a rate limiter and a news feed | Mock briefs | Posts |
| Day 54 | Mock: a production AI system | Mock brief | Posts |
| Day 55 | Capstone kickoff: design before code | Design doc | Posts |
| Day 56 | Capstone build: one real slice | Service + guide | Posts |
| Day 57 | Capstone load test: find the knee | Load generator | Posts |
| Day 58 | Capstone writeup: the architecture doc | Doc template | Posts |
| Day 59 | Review and gaps: close the weak spots | Review grid | Posts |
| Day 60 | The finish: present, reflect, what next | Finish | Posts |
The loop for each day
Each day is four blocks, about four hours in total. Go at your own pace.
| Block | Time | What |
|---|---|---|
| Read | 50 min | The day’s reading and videos, plus the explainer on the day page |
| Drill | 40 min | Back of the envelope math, or a timed design question, on paper |
| Build | 100 min | The lab. Predict first, fill in the TODOs, run it, explain the numbers |
| Write | 30 min | One LinkedIn post and one X thread about what you found |
The four blocks are the four boxes you tick on the progress tracker. The Write block isn’t optional and isn’t vanity. Explaining a thing you half understand to strangers is the fastest way to find the hole in your understanding.
How to follow along
- Fork the GitHub repo and clone your fork. The labs run on your own machine, because measuring your own machine is the point.
- Each day, read the day page top to bottom and do the blocks in order. Write your predictions down before you run anything. Every lab refuses to run until you do.
- Fill in the TODOs in the lab’s starter file, run it, and fill in that lab’s
RESULTS.md. If you get stuck, each lab folder has asolution.py, and each day page ends with a Solutions section: drill answers, the TODO code, and a reference run with an explanation of every number. - Write your posts. The example posts for each day are written with the reference run’s numbers. Use them for shape, then write your own with your numbers.
- Tick off the blocks on the progress tracker as you go. It saves in your browser, on your device, so it remembers where you are between visits, and it resets with one button. Alongside it, keep a short reflective log in your fork, a few lines per day:
## Day N: topic
The number that surprised me:
One thing I can't explain yet:
That last line is the most useful one. Take it into the next day’s reading, ask someone, or go back to the lab until it makes sense.
Getting around
The sidebar on the left has every week, with its days nested inside. Each day holds its lab results, drill notes and example posts. Every page in the main track has previous and next buttons at the bottom, so you can read straight through. The search box at the top covers every page.