skip to content

Diagramming with C4 and UML

Notation matters: C4 for zoomable structure, UML component, deployment and sequence diagrams where precision helps, and model-based tools such as Structurizr or PlantUML. The goal is to escape ambiguous boxes and lines where nobody knows what an arrow means.

part ofSoftware design & architectureoverview, primer and where to startread it →
on this pageshow

questions

6

In Simon Brown's C4 model for describing software architecture, what are the four levels of diagram, and what does each level show?

level: juniorimportance: must knowfreq 72%

answer

  1. Context → Container → Component → Code
  2. Map zoom: world → country → city → street
  3. Container = runnable unit, not Docker
  4. One abstraction level per diagram
  5. Level 4 usually skipped/generated

basics

~20 s

C4 is four zoom levels. Context: your system, its users, and neighbouring systems. Container: the separately runnable/deployable pieces (web app, API, database). Component: the major building blocks inside one container. Code: classes inside one component — usually skipped.

solid answer

~50 s

C4 (Context, Containers, Components, Code) is a set of hierarchical *zoom levels* over one consistent model, invented by Simon Brown. Level 1, System Context, draws a single box for the system under discussion plus the people and external systems it talks to — no internals, aimed at non-technical readers. Level 2, Container, opens that box into separately deployable or runnable units: a SPA, a mobile app, an API service, a database, a message broker; each labelled with its technology and each relationship labelled with purpose and protocol. Level 3, Component, opens exactly one container into its major logical building blocks (e.g. controllers, domain services, adapters) and their responsibilities. Level 4, Code (a UML class or ER diagram), is optional and normally generated on demand or skipped because it rots fastest. The discipline is: pick one level per diagram, never mix them, and keep every level backed by the same model.

go deeper

for a junior

Name the four levels in order and say what a box means at each. Stress that Container ≠ Docker and that Code is usually skipped.

for a middle

Add the discipline rules: one level per diagram, technology labels on containers, intent+protocol labels on arrows, a key on every diagram. Say which level you'd actually draw for your team.

for a senior

Discuss when each level pays for itself, how to keep a large microservice landscape readable (landscape diagrams, filtered views, boundaries), and how C4 relates to deployment and dynamic views.

for a principal

Frame C4 as a shared vocabulary and a governance tool: one model in version control, views generated in CI, diagrams linked from ADRs, and an explicit policy on which levels the org maintains versus regenerates or drops.

## The problem C4 solves Most "architecture diagrams" are ad-hoc boxes and lines. Two people looking at the same picture disagree about what a box *is* — is it a process? a class? a team? a server? — and about what a line *means* — a network call? an inheritance relationship? a hope? C4, created by Simon Brown, fixes this by fixing the **meaning of a box at each level** and by insisting that each diagram sits at exactly one level of abstraction. The name is the four levels: **C**ontext, **C**ontainers, **C**omponents, **C**ode. The mental model is a map application: world map → country → city → street. You do not draw streets on the world map. ## Core vocabulary (define once, use everywhere) - **Person** — a human role that uses the system (Customer, Support Agent). Not a department, not a user account. - **Software System** — the highest level of abstraction: something that delivers value to people. One of them is *your* system ("the system under description"); the others are external systems you integrate with. - **Container** — **not** a Docker container. A container is *something that must be running for the system to work*: a server-side web application, a single-page app running in a browser, a mobile app, a serverless function, a database schema, a file system, a message broker. Roughly: a separately deployable/runnable unit with its own process/runtime. - **Component** — a grouping of related functionality behind a well-defined interface, living **inside** a container, in the same process. Not separately deployable. In code terms: a package/module/namespace, not a single class. - **Code element** — classes, interfaces, tables. Level 4. ## Level 1 — System Context One box for your system in the middle, surrounded by the **people** who use it and the **external software systems** it exchanges data with. No internals at all. Audience: everybody, including non-technical stakeholders. Question answered: *what is this thing, who uses it, and what does it depend on?* Typical mistakes: putting your own microservices on it (that is level 2), putting infrastructure like a load balancer on it, drawing the org chart. ## Level 2 — Container Zoom into your system box. Show each separately runnable unit and the technology it is built with, plus the people/external systems from level 1 that talk directly to those units. Every relationship is an arrow labelled with **intent + technology**, e.g. "Reads and writes orders using [SQL/TCP]", "Sends order-placed events via [AMQP]". This is the **most valuable diagram in practice** — it is the one that tells a new engineer what actually runs, what talks to what, and over which protocol. If you only ever draw one diagram, draw this one. Typical mistakes: mixing a database *table* in with services (wrong level), omitting the technology labels, drawing bidirectional arrows with no label. ## Level 3 — Component Zoom into **exactly one** container and show its major building blocks and their responsibilities and interactions. Draw it only for containers that are complex enough to warrant it — usually one or two per system, not all of them. Typical mistakes: drawing one component diagram "for the whole system" (that mixes containers), or letting it degrade into a class diagram. ## Level 4 — Code A UML class diagram or ER diagram for one component. Optional, and Simon Brown's own advice is to skip it or generate it on demand from the IDE, because hand-drawn code diagrams are stale within days. ## Supplementary diagrams that come with C4 - **System Landscape** — many systems in an enterprise, above level 1. - **Dynamic diagram** — a collaboration/sequence-style view showing the ordered steps of one scenario across containers or components. - **Deployment diagram** — maps containers onto infrastructure nodes (regions, VMs, Kubernetes pods), showing that one container may have many instances. ## What C4 is *not* C4 is **notation-independent**. It does not prescribe shapes, colours, or a UML profile — you can render it in Structurizr, PlantUML (C4-PlantUML), Mermaid, or on a whiteboard. What it prescribes is the **abstractions** and the discipline: one level per diagram, every element titled and typed, every line labelled and directed, a legend/key on every diagram, and a title saying what the diagram is and at which level. ## Trade-offs and edge cases - **Serverless / event-driven:** functions and queues are containers; the container diagram can get crowded. Group with boundaries, or split by feature area, rather than dropping to a lower level. - **Microservices:** a system with 60 services makes an unreadable container diagram. Options: treat groups of services as separate *software systems* with a landscape diagram, or use filtered views over one model. - **Monolith:** the container diagram is boring (one app + one DB) — the component diagram is where the value is. - **Cost:** four levels for every system is over-investment. The common sweet spot is Context + Container always, Component sometimes, Code never.

  • Does 'container' in C4 mean a Docker container?
    No. It predates and is independent of Docker. A C4 container is anything that must be running for the system to work — a web app, an API process, a browser SPA, a database, a message broker. A Docker container is one possible way to *deploy* a C4 container; that mapping belongs on a deployment diagram.
  • Which C4 level do teams get the most value from, and why?
    The Container diagram. It is the first view that shows what actually runs, the technology of each part, and the protocols between them — enough for onboarding, for impact analysis, and for security/threat-modelling conversations — while still being small enough to stay accurate.
  • How do you keep a C4 diagram set consistent as the system changes?
    Back all levels with a single model (e.g. a Structurizr DSL file or C4-PlantUML includes) stored in the repo, review it in pull requests like code, and render views from it in CI so a rename or a new dependency updates every level at once.

Like zooming a map app: the world map shows countries (context), the country map shows cities (containers), the city map shows streets (components), the street view shows house numbers (code). Nobody draws house numbers on the world map.

saying these in an interview costs you the question

  • Saying a C4 container means a Docker container
  • Putting your own services on the System Context diagram
  • Mixing users, containers, and classes on one diagram
  • Hand-maintaining level 4 code diagrams instead of generating or skipping them
  • Believing C4 mandates specific shapes or colours — it is notation-independent

context

open as a page

Why are typical "boxes and lines" architecture diagrams ambiguous, and what concrete rules make a diagram self-explanatory to someone who was not in the room when it was drawn?

level: middleimportance: must knowfreq 58%

basics

~20 s

Because nothing says what a box or a line means: a box could be a service, a class, or a team; a line could be an HTTP call, a dependency, or data ownership. Fix it with titles, typed/labelled boxes, directed labelled arrows, a key, and one abstraction level.

open as a page

Which UML diagram types remain genuinely useful for describing software architecture, what does each one express, and how do they relate to C4?

level: middleimportance: should knowfreq 45%

basics

~20 s

Mainly three: component diagrams (units of functionality and the interfaces they provide/require), deployment diagrams (which artefacts run on which nodes), and sequence diagrams (the ordered messages of one scenario over time). They map onto C4's component, deployment, and dynamic views.

open as a page

What is the difference between diagram-based tools and model-based ("diagrams as code") tooling such as PlantUML and Structurizr, and what do you gain and lose by adopting a single-model approach?

level: seniorimportance: should knowfreq 36%

basics

~20 s

Drawing tools store pictures, so the same service exists five times and updates get missed. Model-based tools store one definition of elements and relationships, then render multiple views from it. PlantUML is scripted-per-diagram text; Structurizr holds a real model with views.

open as a page

As a technical leader, how do you stop architecture diagrams from becoming stale and misleading across many teams — which diagrams do you maintain, which do you generate, and which do you deliberately throw away?

level: principalimportance: should knowfreq 22%

basics

~20 s

Keep few diagrams, store them as text beside the code, and review them in the same pull request as the change. Generate the volatile low-level ones from code and infrastructure; throw away workshop sketches; delete anything nobody maintains rather than leaving it wrong.

open as a page

Beyond the four static C4 levels, what do C4's supplementary dynamic and deployment diagrams add, and what question does each answer that a container diagram cannot?

level: seniorimportance: nice to knowfreq 24%

basics

~20 s

A container diagram shows what exists and what talks to what, but not order or placement. A dynamic diagram numbers the steps of one scenario over time; a deployment diagram maps containers onto infrastructure nodes, showing environments and how many instances run.

open as a page