Diagramming & C4
Diagrams at four zoom levels, each with one audience — and how to keep them true a year later.
One Diagram, One Question
The two habits that fix most of it: label every arrow with what actually flows and in which direction, and state the zoom level in the title. An unlabelled arrow between two boxes tells a reader nothing — is that an HTTP call, a shared database, a nightly export, or an aspiration?
The C4 Model
C4 gives four levels, each a zoom into the previous one, so a reader can choose the altitude they need.
| Level | Shows | Audience |
|---|---|---|
| 1 — Context | Your system, its users and the systems it talks to | Anyone, including non-technical |
| 2 — Container | Deployable units: apps, services, databases, queues | Engineers and operations |
| 3 — Component | The major parts inside one container | Engineers working on it |
| 4 — Code | Classes and relationships | Rarely drawn — generate it if needed |
A container in C4 is a deployable or runnable thing — a service, a single-page app, a database, a message broker — not a Docker container specifically. It is the level at which most architectural conversations actually happen.
Sequence & Flow Diagrams
Static diagrams show structure; sequence diagrams show what happens over time, which is what most incident and design discussions actually need.
| Draw one when | Because |
|---|---|
| A flow crosses several services | The ordering and failure points are the design |
| Explaining an authentication handshake | Steps and their order are the entire content |
| Documenting an incident | The timeline is the finding |
| Designing a retry or compensation path | The unhappy path is where the complexity lives |
sequenceDiagram
Client->>API: POST /orders
API->>Payments: authorise(card, amount)
Payments-->>API: authorised
API->>DB: save order (pending)
API-->>Client: 202 Accepted
Note over API,DB: capture happens asynchronously
Keeping Them True
| Practice | Effect |
|---|---|
| Diagrams as code, in the repository | They change in the same pull request as the code |
| Few diagrams, kept current | Beats many that are all slightly wrong |
| Date and owner on each | A reader can judge how much to trust it |
| Reviewed when boundaries change | The moment the container diagram becomes wrong |
| Delete rather than let rot | An absent diagram is honest; a stale one lies |
The pragmatic target for most teams is two diagrams that are always right — a context and a container view — plus sequence diagrams drawn for specific flows when they are being designed or debugged.
Interview Questions
What are the four C4 levels?
Context (system, users, external systems), container (deployable units), component (parts inside a container) and code. Levels 1 and 2 carry nearly all the value.
What is a container in C4?
A separately deployable or runnable thing — a service, a single-page app, a database, a broker. Not a Docker container specifically.
Why label every arrow?
An unlabelled arrow could be an HTTP call, a shared database, a nightly export or an intention. The label and its direction are what make the diagram a statement rather than a sketch.
Why prefer diagrams as code?
They live in the repository, diff in review, and get updated by whoever changes the system. An exported image goes stale the moment the source file is lost.
When is a sequence diagram the right tool?
When ordering and failure points are the design — cross-service flows, authentication handshakes, retry and compensation paths, and incident timelines.
What do you do with a diagram nobody maintains?
Delete it. An absent diagram is honest about the gap; a stale one is trusted and used to plan work, which is how it causes damage.