System Design from Zero
· Jerwin Arnado · 8 min read ·
You can build a working app — the form saves, users log in, it looks fine on your laptop — and still freeze when someone asks, “okay, how would this hold up with ten thousand people using it at once?” That gap, between “it runs” and “it holds up,” is what this whole series is about.
But the rest of the series assumes you already know what a load balancer is, what “stateless” means, why a cache can quietly bite you. This chapter doesn’t assume any of that. If those words already feel comfortable, skip straight to the real introduction — you won’t miss a thing. If they don’t, you’re in the right place. Nothing below asks for more than “I’ve built a small app that talks to a database.”
A system is just boxes and arrows
Strip away the jargon and every architecture diagram is the same two things: boxes and arrows. A box is something that does work or holds data. An arrow is one box asking another for something over a network. That’s the entire vocabulary of the whitespace on a whiteboard.
The whole of system design is three questions about those boxes and arrows: what are the boxes, where do they live, and what happens when an arrow fails? Everything with an intimidating name — CAP, quorums, idempotency, the stuff later in this series — is just detail hanging off those three questions. Keep the picture that simple in your head and the scary parts have somewhere to land.
The four boxes you’ll meet everywhere
Almost every system you’ll build starts as four boxes. Picture opening a real app — say Lucas Clinic, a booking system I run — and watching your appointments load:
- The client — the browser or phone in front of the user. It’s a box too. It runs the frontend and it is the one place you don’t control: it might be on airport wifi, an eight-year-old Android, or a laptop with forty tabs open.
- The server (the app) — code sitting on a computer somewhere that answers requests. In my case that’s Laravel — PHP that turns “give me my appointments” into an actual answer. This is where your business logic lives.
- The database — where data rests when nothing is running. Turn every server off, turn them back on, and the data is still there. That permanence is the whole point. For me that’s MySQL.
- The network — the arrows themselves. The internet between the client and your server, and the local link between your server and its database. Beginners forget it’s even a box on the diagram, and it’s the least reliable one of all. Half of this series is really about the network misbehaving.
Everything grander — caches, load balancers, queues, read replicas — is a variation on one of these four, or a helper bolted between them. Learn the four and the rest is remixing.
What actually happens when you load a page
Here’s the whole trip, start to finish, when you type an address and hit enter. No step is complicated on its own:
- Your browser needs to find the server. It asks DNS — the internet’s phone book — to
turn
app.lucas.clinicinto an actual address. - The browser sends a request across the network: “GET me the appointments page.”
- The server receives it, runs your code, and realizes it needs data.
- The server sends its own request to the database: “SELECT the appointments for this user.”
- The database finds the rows and sends them back.
- The server takes that data, builds the response (HTML, or JSON for an app), and sends it back across the network.
- The browser renders it, and the user finally sees their appointments.
Seven hops, and every single one takes time. Add them up and you get latency — how long the user waited. Notice how many of those hops cross the network, the unreliable box. Notice that the database step is often the slowest. Those two observations are the seed of nearly every optimization in this series — and the next chapter puts real numbers on each hop so you stop guessing which one to worry about.
The scary words, in one line each
These are the terms that make system-design writing feel gatekept. Each one points at a small, sensible idea. You don’t need to understand them yet — just know the words aren’t hiding anything clever:
- Latency vs throughput — how fast one request feels, versus how many requests you can handle per second. Two different clocks, and you tune them differently. → the physics
- Cache — a fast copy of an answer you already computed, kept close by so you don’t redo slow work. The catch is the copy can go stale. → caching
- Load balancer — a box that sits in front of several identical servers and hands each incoming request to whichever one is free. → load balancing
- Stateless — a server that remembers nothing between one request and the next. Sounds like a limitation; it’s actually the trick that lets you run ten copies of it at once. → scaling
- API — the menu of requests a server agrees to answer, and the shape of each reply. → APIs
- Queue — an inbox for work to do later, so the user isn’t stuck waiting on the slow parts. → sync vs async
Six words. Six simple ideas. Every one gets a full chapter later — this is just so the vocabulary stops being a wall.
Bigger box, or more boxes
When your app gets popular, there are exactly two directions to go, and it’s worth knowing their names on day one:
- Vertical scaling — buy a bigger box. More CPU, more RAM, a faster disk. It’s the easy button, it works further than beginners expect, and it has a hard ceiling: eventually you can’t buy a bigger single machine.
- Horizontal scaling — add more boxes. Ten modest servers instead of one giant one. This is how everything large is actually built, and it’s where the interesting problems live — because now the boxes have to agree with each other.
Almost every hard topic in this series exists because someone chose more boxes, and the moment you have more than one box, they can disagree, fall out of sync, or fail one at a time. Scaling and statelessness is where that story really begins.
Why “it depends” is the honest answer
New engineers want the right stack — the one correct answer, the architecture that wins. Here’s the uncomfortable truth this series is built on: there isn’t one. Every choice buys you something and charges you for it somewhere else. A cache buys speed and charges you in staleness. More boxes buy capacity and charge you in complexity. The senior skill isn’t memorizing the “right” design — it’s knowing the handful of dials, which way each one turns, and which one this product can afford to spend.
That’s the thesis the next chapter unpacks properly, as five axes you’re always trading between. Once it clicks, the intimidating diagrams stop being magic and start being choices — ones you’re allowed to make.
How to read from here
- Total beginner? Go front to back, starting with the real introduction. Each chapter builds on the last.
- Comfortable with the vocabulary, fuzzy on the tradeoffs? Jump straight to the five axes and keep going.
- Just want to see how the boxes get wired in practice? The companion thirteen-layer stack tour is the how; this series is the why and when. Read them side by side.
Conclusion
System → boxes (do work / hold data) + arrows (requests over a network)
4 boxes → client · server · database · the network between them
A page → find server (DNS) → request → server → database → response → render
Latency → the sum of all those hops; the network + the DB are usually the slow ones
Growth → bigger box (vertical, has a ceiling) or more boxes (horizontal, gets interesting)
Truth → no right stack; every dial buys one thing and spends another
System design looks like a body of secret knowledge from the outside. It isn’t. It’s four boxes, some arrows that sometimes fail, and the judgment to know which trade your product needs. You already have the boxes — you’ve built an app. The rest of this series is just learning the dials. Next: how to think about system design, and the five axes every decision trades between.