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

  1. Fork the GitHub repo and clone your fork. The labs run on your own machine, because measuring your own machine is the point.
  2. 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.
  3. 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 a solution.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.
  4. 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.
  5. 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.