The C4 model
C4 is a set of abstractions for describing system structure at four levels of zoom. It's notation-independent — the ideas work equally well whether you're drawing boxes and arrows, building formal specifications, or sketching on a whiteboard. The name comes from the four main zoom levels: Context, Container, Component, and Code. Each level shows the inside of one thing from the level above, so you can start with a single box and progressively zoom in without ever mixing abstractions on one canvas.
If you only take one idea away: C4 is about how the system is arranged, not how it behaves or where it runs. Behavior is F4; infrastructure is deployment.
The four levels
graph TD L1["`**Context (C1)** Who uses the system? What does it depend on?`"] L2["`**Container (C2)** What are the major runnable parts?`"] L3["`**Component (C3)** How is one container arranged inside?`"] L4["`**Code (C4)** Classes and sequences — rarely drawn`"] L1 --> L2 --> L3 --> L4
Think of it as a map you can zoom. The Context view is the whole country; Container is a city; Component is a neighbourhood; Code is the floor plan of one building. You rarely need every level — most systems are well served by Context + Container, with Component for the few parts complex enough to earn it.
| Level | What it answers | Draw it? |
|---|---|---|
| Context | Who and what uses this system? | Almost always |
| Container | What are the major runnable parts? | Almost always |
| Component | How is this one part structured? | When a container is complex enough |
| Code | How is it implemented? | Rarely — generate on demand if at all |
Elements: the typed boxes
Every box on a C4 canvas has a type that fixes how it's read and drawn. CRAYON-C4 uses five fixed element types:
- Person — a human role that uses the system ("Claims Handler", "Customer").
- Software System — the thing you're describing, or another whole system it talks to.
- External System — a system owned by someone else that yours depends on.
- Container — a separately runnable or deployable unit: a web app, an API, a database, a single-page app, a message broker.
- Component — a structural grouping inside a single container: a controller, service, repository, or adapter.
You can recolour these types to suit your house style, but you can't rename or remove them — the type is the meaning. (You can also define your own display types for purely visual variants when you need a distinct look without changing what an element means.)
Relationships: the labeled edges
Boxes alone say nothing. A C4 model is really a typed reference graph — the value is in the directed, labeled edges between elements.
A good relationship carries two things:
- Purpose — what the source does to the target, as a verb phrase: "Reads claim data from", "Sends payment instruction to".
- Technology — how, where it matters: "HTTPS / JSON", "JDBC", "AMQP".
Direction encodes who initiates, not which way data flows. A service that reads from a database still points its arrow at the database, because the service makes the call. Getting this consistent is what keeps a reader from misreading your dependencies. The Add a relationship guide goes deeper.
Zoom is the whole point
A node that represents a Software System can be opened to reveal its Containers; a Container can be opened to reveal its Components. Each level lives on its own canvas, and CRAYON-C4 keeps it that way deliberately.
The one rule: one level per canvas. Don't put components on your container diagram. Mixing granularities is the single most common C4 mistake, and the level separation exists precisely to prevent it. If a canvas starts to feel crowded with boxes of different sizes of meaning, you've drifted across a level boundary — split it.
The same two systems may carry one coarse relationship at Context ("Exchanges claim data with") that expands into several finer ones at Container ("Reads from", "Writes to", "Subscribes to events"). That's expected — each level labels relationships at its own granularity.
The diagram's subject: center and boundary
Each C4 diagram can have a subject — the single element the diagram is "about". The subject appears as a boundary group (a labeled box), not as a plain node. When you set a subject, all its direct children render inside that boundary, emphasizing that you're showing the insides of one thing. The boundary itself becomes drillable: readers click it to navigate back up to the parent diagram.
You set the subject in the editor's layer form (a "Subject" field). In the viewer, the side panel shows "About:
Why one shared model matters
Because every level, every relationship, and every F4 hand-off draws from the same underlying model, the views can't contradict each other. Change a container once and every view that references it stays in agreement. That single source of truth is what separates a living model from a folder of drawings that drifted apart the moment something changed.
Tips & tricks
Advice distilled from the C4 community (sources: c4model.com and practitioners — see the links at the end):
- Label every relationship with a verb phrase — "Sends customer data via HTTPS", never a bare arrow or "uses".
- Give every diagram a title and keep meaning consistent — a reader should always know which level they're looking at.
- State each container's technology in its description ("PostgreSQL", "React SPA") — it's what makes the container level useful for planning.
- Keep external systems opaque. Show their public face, never their insides — you don't own them, and they change without telling you.
- Crowded canvas? Split by business area rather than shrinking boxes. Two clear diagrams beat one dense one.
- Merge duplicate arrows. Several interactions between the same two elements with the same purpose collapse into one labeled relationship.
- Most systems need only Context + Container. Add Component where a container is complex enough to earn it; skip Code.
Common pitfalls
- Mixing levels on one canvas. The cardinal sin. One level per canvas.
- Unlabeled arrows. An arrow with no purpose or technology tells the reader nothing.
- Over-decomposing. Drawing every class as a Component, or every Component for every Container. Model what the reader at this level needs.
- Confusing structure with deployment. Regions and replica counts belong on a deployment diagram, not a Container one.
Where next
- Create a context diagram — apply this level by level.
- The deployment model — the same parts, placed onto infrastructure.
- The F4 flow model — the same parts, working in sequence.
Learn more outside these docs: c4model.com is the canonical reference by Simon Brown.