1. Fundamentals
System design is deciding how the parts of a software system (clients, servers, databases, caches, queues) fit together so it meets its requirements at the scale it needs. There is no single right answer, only trade-offs you can explain. The other notes in this section: Building Blocks, Data and Consistency, Reliability Patterns, Worked Designs, Distributed Patterns, Capacity Estimation, Choosing Data Stores, Choosing a Language.
A framework for any design question
flowchart LR
A[1. Clarify requirements] --> B[2. Estimate scale]
B --> C[3. High-level design]
C --> D[4. Deep dive on 1-2 parts]
D --> E[5. Bottlenecks and wrap-up]
| Step | What to do | Example (URL shortener) |
|---|---|---|
| Clarify | Ask who uses it, which features, how big | Create short link, redirect, 100M new links/day? Expire links? |
| Estimate | Rough QPS, storage, bandwidth | ~1,200 writes/s, ~12,000 reads/s |
| High-level | Boxes and arrows, APIs, data model | Client, load balancer, web tier, cache, DB |
| Deep dive | Pick the hard part and go deep | How to generate unique short codes |
| Wrap up | Failure points, scaling, monitoring | What if the cache dies? |
- Functional requirements = what it does. Non-functional = how well (latency, availability, consistency, durability).
- State assumptions out loud; change them when the answer changes the design.
Scaling from one user to millions
flowchart TD
S1["Single server web + DB + cache together"] --> S2["Split web tier and DB tier"]
S2 --> S3["Add load balancer + many stateless web servers"]
S3 --> S4["DB replication primary writes, replicas read"]
S4 --> S5["Add cache + CDN"]
S5 --> S6["Stateless tier, session data in shared store"]
S6 --> S7["Message queue + workers for async jobs"]
S7 --> S8["Shard the database multiple data centres"]
- Vertical scaling (scale up): bigger machine. Simple, but has a ceiling and is a single point of failure.
- Horizontal scaling (scale out): more machines. Needs a load balancer and stateless servers.
- Stateless web tier: keep no session data on the server itself, so any request can go to any server and servers can be added or killed freely.
- Database scaling: replication first (read-heavy), sharding when one primary can no longer hold the writes or the data.
- Multiple data centres: route users to the nearest one with GeoDNS; replicate data across them.
Back-of-the-envelope estimation
Round numbers, powers of two, and show your working.
| Power | Value | Name |
|---|---|---|
| 2^10 | ~1 thousand | 1 KB |
| 2^20 | ~1 million | 1 MB |
| 2^30 | ~1 billion | 1 GB |
| 2^40 | ~1 trillion | 1 TB |
Latency numbers worth remembering (orders of magnitude)
| Operation | Time |
|---|---|
| Memory read | ~100 ns |
| SSD random read | ~100 µs |
| Same-datacentre round trip | ~0.5 ms |
| Disk seek (HDD) | ~10 ms |
| Cross-continent round trip | ~150 ms |
- Memory is fast, disk is slow, networks cost the most. Compress data, avoid disk seeks, minimise cross-region trips.
- A day has about 86,400 s, call it ~100,000 s, so
X per day / 100,000 = X per second.
Worked example: a photo app with 10M daily active users (the full version, with bandwidth, cache and servers, is in Capacity Estimation)
$ users = 10,000,000 / day
$ uploads per user = 2 photos / day -> 20M uploads / day
$ upload QPS = 20,000,000 / 100,000 = ~200 / s
$ peak QPS = 2 x average = ~400 / s
$ photo size = 2 MB
$ storage per day = 20M x 2 MB = 40 TB / day
$ storage 5 years = 40 TB x 365 x 5 = ~73 PB
Availability
| Availability | Downtime per year |
|---|---|
| 99% ("two nines") | ~3.65 days |
| 99.9% | ~8.8 hours |
| 99.99% | ~52 minutes |
| 99.999% | ~5 minutes |
- Components in series multiply (two 99.9% parts give ~99.8%); components in parallel (redundancy) raise it.
- Related: CAP theorem and its implications, Database Architecture, N-Tier Architecture.