Learn

Architecture & pattern guides

Read the idea, build it on a Grid, prove it in a challenge. Short, practical guides — illustrated with RodGrid's own nodes — on system design, design patterns, flow modeling, and how to get the most out of the app.

All articles

The C4 model: context, containers, components, code

Four levels of zoom for drawing a software system, what belongs at each one, and the labels that keep a diagram at its level.

Thirty-four boxes, many kinds of thing

A city library network keeps one architecture diagram for its lending system, on the wiki. It has 34 boxes: HoldQueue and LoanPolicy beside PostgreSQL 15, an nginx config, two Kubernetes namespaces, and near the bottom a box called ILL. Before a budget meeting the director needs to know whether the network still depends on the regional catalogue the libraries share for interlibrary loans. It does, through ILL, but she cannot tell that from the page. A developer who joined that morning wants to know where the "your hold is ready" emails come from, and cannot tell either.

Each box is accurate. The diagram fails because the boxes are different kinds of thing, classes, a database server, a config file, deployment namespaces, an outside system, drawn side by side at one size, so no reader can tell which of them belong to their question.

The C4 model, created by Simon Brown, keeps those kinds apart. It defines four levels of abstraction for a software system, each a closer zoom on the one before: System Context, Container, Component and Code. A diagram stays at one level and one scope. The director needs the first zoom; the new developer needs the second.

Who uses it, and what it leans on

A System Context diagram draws the software system in scope as one box with nothing visible inside, and around it the people who use it and the other software systems it talks to. For the library that is members and librarians, the email provider that delivers notices, and the regional catalogue.

The lending system at Context level

One box stands for the whole lending system. Nothing inside it is shown yet.

The director's answer is one hop from the middle box. This diagram is for everyone, technical or not, so it leaves out technologies and protocols: a PostgreSQL box here would be a second level mixed in, the wiki diagram's mistake again.

Applications and data stores

Open the middle box and you have the Container diagram. In C4, a container is an application or a data store inside the system in scope: a unit that runs code or holds data, and that the overall system needs in order to work. The member website, the desk app librarians use at the counter, the lending service behind both, its database, the queue of pending notices and the worker that sends them are six containers.

The word is not Docker's. C4 chose it to say nothing about how a unit runs: the lending service is one container whether it runs in Docker, on a virtual machine or straight on a server, and whether one copy runs or three. Docker's meaning is Containers & orchestration.

The same system at Container level

The Context box is opened: the people and outside systems stay, and the six containers it held appear.

The people and outside systems did not move; one box became six, and the lines now say how as well as what, with JSON/HTTPS, SQL or AMQP. The developer's question is a single path: the lending service publishes a hold-ready event, the worker takes it from the queue and calls the email provider. How many copies of each container run, and on which machines, is still absent: that is a deployment diagram, drawn once per environment.

Two deeper zooms, where they help

The Component level opens one container. A component is a group of related functionality behind a well-defined interface, and it cannot be deployed on its own: Holds, Circulation and the Interlibrary adapter, the only part allowed to call the regional catalogue, all run inside the lending service's process. In code a component is often a package or a module, and the rule about which may depend on which is Packages, notes and dependency direction.

The Code level opens one component, with the notations that already exist for it: a class diagram of Hold and HoldQueue as in The class box: name, attributes, operations, or the tables of Entity-relationship modelling. C4's own documentation recommends both deeper levels only where they add value, and would rather an IDE generate the Code level than anyone draw it by hand, since it changes whenever the code does.

A box that says only Notices

C4 is notation independent: it prescribes no shapes, colours or icons, so it works on a whiteboard or on a Grid. What keeps a diagram at its level is the labels. Each element states its type and, from the Container level down, its technology; each line runs one way and says in specific words what flows that way, with the protocol between containers. "Uses" only says that a line exists; "hold ready (AMQP)" says what travels on it.

Picture the Container diagram with a box that says only Notices. Taken for a container, it sends the on-call engineer looking for a process and a deployment that do not exist. Taken for a component, it hides a worker that can stop on its own while the lending service keeps answering, and holds pile up in the queue with no emails sent. The label Notice worker: container, Node.js settles it before anyone guesses. The small examples above give the type only through each card's icon; a full Container diagram writes the technology too.

Two things stay off the four level diagrams. The order of calls in one scenario, a member placing a hold until the email arrives, is a Dynamic diagram, one of C4's supplementary diagrams, drawn with the systems, containers or components of the levels, and UML draws it as Sequence diagrams: who calls whom, in what order. And the decision itself: whether Holds and Circulation should be two containers or two components of one is weighed in Microservices vs monolith. C4 only makes the choice visible: here, two separately deployed services talking across a process boundary, usually over the network, or two components inside one application.

On a Grid, the Views panel generates Context, Container, Component and Deployment views from the catalog components already drawn, with no Code view; From a picture to a model: governance and views shows how.

Two lines of Context before Calendar & Scheduling

Calendar & Scheduling grades the design against its brief, and nothing in it grades C4 levels, but its brief has people and outside systems at both ends: organisers, attendees outside the company, reached only by email, an email provider for invitations and reminders. Write its Context in two lines first, who uses the calendar and what it depends on; the people stay in those lines, since the palette has no card for a person. The Grid you then build is the Container diagram, and the level check is yours: every card an application, a data store or an outside system it talks to, every connection labelled with what it carries and how. A card for a reminder module that cannot run on its own is a component, one zoom too far in. What goes on the Grid in the first place is Approaching a system design problem.

Practice this