03 · Reading and Drawing Architecture Diagrams Well (the C4 Model)
Last chapter you learned to think a system through. This chapter solves the next problem: how to turn the system in your head into a diagram anyone gets at a glance. More than half of an architect's job isn't designing — it's communicating. And the diagram is the workhorse of communication.
Why an architect must be able to draw
First, correct a misconception: drawing an architecture diagram is not for looks, nor to check a box — it's for the plainest thing imaginable: making others see the same system you see.
Picture this: the system in your head is clear. You know exactly how the data flows, who depends on whom, where the boundaries are. But it's locked inside your head. Your product manager doesn't know it; your backend colleagues each have their own understanding; the frontend thinks it's something else entirely. So ten people carry ten slightly different systems in their heads — and this is the root of nearly every project's chaos.
The job of an architecture diagram is to "pour" the system out of your head and put it on the table, so everyone speaks to the same picture. Its value lies in alignment:
No diagram: With a diagram:
System in System in Everyone
product's backend's looking at the
head head same picture
│ │ │
▼ ▼ ▼
"I assumed" "I assumed" "We're talking
↘ ↙ about the
conflict, rework same thing"In one line: an architect's output isn't just "thinking it through," it's "making the team clear on it too." Having thought it through but being unable to explain it is, in team collaboration, nearly the same as not having thought it through. Knowing how to draw is how you turn an individual's judgment into a team's consensus — that's the architect's core work, not an add-on skill.
What's more, drawing is itself a form of thinking. When you try to draw the system in your head, you often discover "huh, which of these two actually calls the other?" or "I haven't really thought through the boundary here." The diagram forces you to think the fuzzy parts clear. Not being able to draw it is usually a sign you haven't thought it through.
First, look at what a "bad diagram" looks like
Before learning to draw well, get to know the bad smells. You've surely seen this kind of diagram: a pile of colorful boxes, dense arrows crisscrossing every which way, and after staring for ages you have no idea what it's trying to say. A bad diagram is worse than no diagram, because it manufactures the illusion of "we communicated" while everyone still understands something different.
Bad diagrams usually commit these sins:
┌─────────────────────────────────────────────────────────────┐
│ The four cardinal sins of bad diagrams │
├─────────────────────────────────────────────────────────────┤
│ ① No boundaries Every box flat on one plane; you can't │
│ tell which ones live in the same process / │
│ machine / trust domain. │
│ │
│ ② Directionless A line is just a line — you don't know if │
│ arrows A calls B or B calls A, nor what runs over │
│ the line (data? call? event?). │
│ │
│ ③ Mixed levels In one diagram, "the entire payment │
│ of abstraction system" and "some utility function" are │
│ drawn at the same level. Concepts of wildly │
│ different sizes mixed together; the reader │
│ can't tell what granularity to use. │
│ │
│ ④ Too many boxes Forty rectangles crammed onto one page, │
│ information overload, and the reader just │
│ gives up. │
└─────────────────────────────────────────────────────────────┘The third sin, "mixed levels of abstraction," is the most insidious and the most lethal, so it's worth one more sentence. It's like a map that draws both "all of China" and "a specific building in your neighborhood" — two things differing by a vast scale, put together, leave the reader with no idea how high a vantage point to take.
The opposite of a bad diagram is exactly curing these four sins: clear boundaries, arrows that show direction and meaning, one abstraction level per diagram, and a controlled number of boxes. So is there a ready-made method that helps us do all this systematically? Yes, and it's called the C4 model.
The C4 model: viewing a system in layers, like using a map app
The core idea of the C4 model is exactly like your experience using a map app.
When you look up a route, you don't view everything at the same zoom level: first the "map of China" to see where the cities are, zoom in to the "city map" to see the main roads, zoom in again to the "street map" to see exactly how to get there. Each level shows only the information it should — one bit more is clutter, one bit less is emptiness.
C4 splits architecture diagrams into four such "zoom levels," from the most macro to the most micro:
Zoom level C4 layer What it shows For whom
🌍 Map of China → ① Context The whole system + Everyone
its surroundings (incl. non-
(users, external technical)
systems)
│
▼ zoom in, dive inside "our system"
🏙️ City map → ② Container Which "independently Technical team
runnable big blocks" (architects, ops,
the system is made of tech leads)
│
▼ zoom in, dive inside "one container"
🛣️ Street map → ③ Component Which modules a Engineers who
single container is build this part
made of
│
▼ zoom in, dive inside "one component"
🏠 Building map → ④ Code How classes/functions (rarely drawn,
are organized leave it to the IDE)The name C4 comes from these four layers' initials: Context, Container, Component, Code.
Its greatest contribution is curing the third sin of bad diagrams head-on — "mixed levels of abstraction." Because it forces you to: one diagram stays at exactly one zoom level. Either you draw the whole system's overview, or you dive into one block to see its internals — never both in one diagram.
Let's go layer by layer. Focus on mastering the first two layers (Context and Container), because they're the ones used most in daily work and the ones that best reflect architectural judgment.
Layer ①: Context — for everyone
This is the most zoomed-out layer. In this diagram, your entire system is just one box in the middle (yes, the whole system is a single box, with no internal detail drawn at all), and around it you draw: who uses it (users, various roles), and which external systems it interacts with (payment gateway, email service, third-party login…).
It answers the highest-level question: "What is this system for? How does it interact with the outside world?"
Context diagram example: an "online bookstore"
┌──────────┐ ┌──────────────┐
│ Customer │ │ Publisher │
│ (user) │ │ system │
└────┬─────┘ │ (external, │
│ browse, order │ supplies) │
▼ └──────▲───────┘
┌─────────────────────────────────────────┴────┐
│ │
│ O n l i n e B o o k s t o r e │
│ (what we're building, internals hidden) │
│ │
└──────┬──────────────────────────┬─────────────┘
│ initiate payment │ send order emails
▼ ▼
┌──────────────┐ ┌──────────────┐
│ Payment │ │ Email │
│ gateway │ │ service │
│ (external) │ │ (external) │
└──────────────┘ └──────────────┘For whom: everyone — including product managers, the boss, customer support — anyone who doesn't write code but needs to understand "what role this system plays in the ecosystem." The beauty of this diagram is that it contains not a single technical term, so non-technical people can read it too, making it especially good for aligning on "what exactly are we building."
Layer ②: Container — for the technical team
Take that "whole system" box in the middle of the previous layer, zoom in, and dive inside — what you see is the Container layer.
Here, "Container" does not mean a Docker-style container (don't let the name fool you). In C4 it means "a big block that can run and deploy independently" — like a frontend app, a backend service, a database, a cache. The test is simple: is it a process or store that can start and deploy on its own? If so, it's a Container.
This layer answers: "What independently runnable big blocks make up our system internally? How do they communicate? Where does the data live?"
Container diagram example: zooming into the "online bookstore system" above
┌──────────┐
│ Customer │
└────┬─────┘
│ HTTPS
▼
┌─────────────────────────────────────────────────────────┐
│ Online bookstore (dashed = system boundary; all inside ┊
┊ is "ours") ┊
┊ ┊
┊ ┌──────────────┐ call API ┌───────────────┐ ┊
┊ │ Web frontend │ ────────────────▶ │ Backend │ ┊
┊ │ (browser app) │ ◀──────────────── │ service │ ┊
┊ └──────────────┘ return JSON │ (biz logic) │ ┊
┊ └───┬───────┬───┘ ┊
┊ │ │ ┊
┊ read/write orders│ │ cache hot items
┊ & products ▼ ▼ ┊
┊ ┌──────────┐ ┌────────┐ ┊
┊ │ Database │ │ Cache │ ┊
┊ └──────────┘ └────────┘ ┊
└──────────────────────────────────────────────────────────┘For whom: the technical team — architects, tech leads, ops. Because this layer maps directly onto "deployment" and "operations": each Container is usually a unit to deploy, to monitor, and possibly to scale. This is also the layer where architectural judgment is densest — "split into how many services," "how to shard the database," "should we add a cache" — most of the trade-offs from the last chapter show up in this diagram.
💡 You may have noticed: every template's "architecture overview diagram" in this repo is basically drawn at the Container layer. Take that diagram in Section 4 of the AI chat product template: the "ingress layer, orchestration layer, inference service, session store, vector retrieval" — each is an independently runnable big block, making it a textbook Container diagram. Learn to read Container diagrams and you'll be able to read nearly every overview diagram in this repo.
Layer ③: Component — for those who build this part
Zoom in once more, dive into one Container (say, the "backend service" above), and look at the modules that compose its internals — like "order module," "product module," "user-auth module" — and how they collaborate.
Component diagram example: zooming into the single "backend service" container
┌──────────────────────────────────────────────────┐
│ Backend service (zoom in on its internals) │
│ │
│ ┌────────────┐ ┌────────────┐ │
│ │ Order │ ───▶ │ Inventory │ │
│ │ module │ │ module │ │
│ └─────┬──────┘ └─────┬──────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌────────────┐ ┌────────────┐ │
│ │ Payment │ │ Data │ ──▶ (to DB) │
│ │ integration│ │ access │ │
│ └────────────┘ └────────────┘ │
└────────────────────────────────────────────────────┘For whom: the engineers who will build this Container. It helps a single team agree internally on "how to split this code into modules and who owns what." Note: you only need to draw a Container's Component diagram when that Container is complex enough to be worth breaking down — for simple ones, don't bother.
Layer ④: Code — usually not drawn
The last layer gets down to how specific classes and functions are organized.
Honestly, this layer rarely needs to be hand-drawn. Because the code itself, and the relationship diagrams an IDE auto-generates, are the most accurate and most real-time "Code diagram" — draw one by hand and it goes stale the moment the code changes. So the C4 model itself says: draw the Code layer only occasionally as needed; skip it most of the time.
This is plain engineering wisdom in itself: don't hand-maintain a document that "goes stale the moment the code changes." Your energy should go to the Context and Container layers — the ones that are "relatively stable, yet most in need of communication."
The basic elements of drawing: just three
C4 looks fancy, but the "brushes" actually in your hand come down to just three things. Nail down what these three mean, and your diagram won't be a mess.
┌─────────┐
│ Box │ = a "thing with a responsibility."
└─────────┘ It must answer "what do you do?" A system, a service,
a module — any of them works, but in one diagram, all
boxes must be at the same "scale."
───▶ = arrow = a "relationship."
Key: ① always has a direction (who initiates);
② always has a label (does the line carry a
"call"? "data"? "event"?)
Directionless, label-less lines are the #1 source of
bad diagrams.
┌ ─ ─ ─ ─ ┐
┊ Boundary ┊ = a "dividing line."
└ ─ ─ ─ ─ ┘ Encircles "things that belong together." It may be:
• a deployment boundary (these run on the same
machine/cluster)
• a trust boundary (inside is what we trust; all input
from outside is untrusted)
• a system boundary (which parts are "ours," which are
external)Of these three, beginners most often overlook the "boundary," and it's precisely the one that best reflects architectural thinking. A single boundary often means both "where it deploys" and "how far trust extends" — for instance, the line that AI template kept stressing last chapter, "any external data re-entering the system is untrusted," is, on a diagram, a trust boundary separating "our system" from "external input." Where you draw the boundary is often where the security and deployment decisions live.
A few principles that instantly improve your diagrams
Write these five down and stick them by your monitor. They directly cure the "four sins" above:
One diagram, one abstraction level. This is the soul of C4 and the most important one. Don't suddenly stuff a concrete function into a diagram of the whole system. Either it's all "big blocks," or it's all "modules" — no mixing. (Cures sin ③)
Always label arrows with direction and meaning. Every line must answer two questions: "Who calls whom?" "For what?" Write a few words beside it — "call API," "read/write data," "send event." An unlabeled line is an unconsidered dependency. (Cures sin ②)
Control the number of boxes (7±2). A person can grasp about 7 things at a glance. Once a diagram exceeds 9 boxes, consider whether you should abstract up a level, or split it into two diagrams. Feed information in layers, not all at once. (Cures sin ④)
Draw Context first, then drill down. Always start from the most macro diagram, confirm "the system's relationship with the outside world" is aligned, then dive in to draw Containers. Top-down — don't plunge straight into the details of some component, or you'll easily miss the forest for the trees.
Diagrams are for humans, not machines. Constantly ask yourself: "Who's my reader? Do they need this information?" Keep technical jargon out of a Context diagram for the boss; don't drop the key data flow from a Container diagram for engineers just to keep it tidy. Always draw for your reader.
Practical ASCII diagramming tips
This repo uses plain-text (ASCII) diagrams throughout — because they display anywhere, drop straight into Markdown and code comments, and let you see what changed via a text diff: plain but extremely practical. Here are a few tips to get you going:
① Box: enclose with box-drawing characters
┌─────────┐ horizontal ─ vertical │ corners ┌ ┐ └ ┘
│ Service A│ cross ┼ tees ┬ ┴ ├ ┤
└─────────┘
② Arrow: make the direction clear
──▶ ◀── ▲ ▼ one-way dependency
◀──▶ or one line each way two-way interaction (e.g. "request/response")
③ Boundary: distinguish dashed from solid
┌─────────┐ solid box: a concrete thing
└─────────┘
┌ ─ ─ ─ ─ ┐ dashed box: a boundary (system/trust/deployment)
┊ ┊
└ ─ ─ ─ ─ ┘
④ Add text beside the arrow, saying what the line does (most important!)
A ───call API───▶ B
A ◀──return result─ BA few small reminders:
- Draw on scratch paper or a whiteboard first, get the layout clear, then transcribe to ASCII. ASCII is harder to edit than a quick freehand sketch, so "think first, draw second" matters even more.
- Use alignment and whitespace well. Align boxes on the same level horizontally and spread them out vertically, and the diagram becomes far cleaner. A cramped ASCII diagram's readability falls off a cliff.
- Don't chase pixel perfection. An ASCII diagram's goal is to "make the structure and relationships clear," not to be art. If it lets people see how data flows and who depends on whom, it's a success.
You don't have to memorize these characters from scratch. The best way to learn is to "copy" straight from this repo's templates — see how the AI chat product template overview uses boxes and arrows, imitate it, and a few tries in you'll be fluent.
Hands-on practice
Watching without practicing won't teach you to draw. Here's a concrete exercise, and I strongly recommend actually doing it:
Exercise:
- Open
templates/and pick any system that interests you (e.g. e-commerce, social feed, real-time chat…).- Don't look at its overview diagram yet! Read only its opening "one-line positioning" and "core needs," then draw, by yourself, a Context diagram for it: one box in the middle is this system, and around it are the users and the external systems it interacts with. Pen and paper or ASCII, either is fine.
- As you draw, deliberately apply this chapter's principles: do the boxes use just one abstraction level? Are the arrows labeled with direction and meaning? Did you encircle the system boundary?
- Once drawn, compare against the template's architecture overview diagram (which is a Container diagram).
When comparing, focus on feeling two things:
- Is your Context diagram (the farthest view) and its Container diagram (one level in) exactly one "zoom level" apart? — Feel the power of C4's layering: the "whole system as one box" you drew, zoomed in, becomes that cluster of collaborating big blocks in the template.
- Are there any "external systems" or "internal big blocks" in the template overview that you didn't think of? Why does it need that thing? — This question loops right back to Chapter 02's "why." Drawing isn't just drawing — it forces you to re-understand every decision in the system.
📌 Real-world cases: the C4 model isn't our invention
The C4 model used in this chapter comes from the methodology of the same name proposed by Simon Brown, and is today one of the industry's de facto standards for drawing architecture diagrams.
- 📎 Official: c4model.com — has the fuller four-layer definitions, notation conventions, and many real examples.
- The overview diagrams of this repo's 21 templates are basically all drawn at C4's Container layer — learn to read it and you can read nearly every system in the repo.
Chapter summary
- The essence of drawing is "alignment," making everyone on the team see the same system. More than half of an architect's job is communication, and the diagram is its workhorse; having thought it through but being unable to explain it ≈ not having thought it through. And drawing itself forces you to think the fuzzy parts clear.
- The four cardinal sins of bad diagrams: no boundaries, directionless arrows, mixed levels of abstraction, too many boxes. Of these "mixed levels of abstraction" is the most lethal — like a map drawing both an entire country and your apartment building.
- The C4 model is like a map app's zoom levels, in four layers: Context (the whole system + surroundings, for everyone) → Container (independently runnable big blocks, for the technical team) → Component (modules inside a container, for developers) → Code (rarely drawn). Its soul: one diagram stays at one zoom level.
- This repo's overview diagrams are basically all Container-layer diagrams. Learn to read them and you can read nearly every system in the repo.
- The brushes of drawing are only three: box (a thing with a responsibility), arrow (a relationship labeled with direction and meaning), boundary (the dividing line of deployment/trust/system). Beginners most overlook the boundary, which best reflects architectural thinking.
- Five principles: one abstraction level per diagram, label arrows with direction and meaning, control box count (7±2), Context first then drill down, always draw for your reader.
Here, the first part, "build the mindset," is complete: you know why architectural judgment is worth more and more (01), have a framework for thinking a system through (02), and have learned to draw your ideas out and explain them clearly (03).
But you might ask: do I have to think from scratch every time? For the classic hard problems my predecessors faced, are there ready-made "moves" I can reuse?
Yes. The next part, "master the toolbox," is here to deal you those cards — the repeatedly battle-tested "patterns" an architect carries, each one a standard answer to a class of problem.
👉 Continue: 04 · The Ten Core Architecture Patterns