The C4 model: four steps to documenting software architecture
Is it possible to visualise and document software architecture in just four steps? According to the C4 model, a maximum of four diagrams is all you need to present the majority of systems in enough detail to implement them.
At FIS-SST we decided to verify this assumption by applying the C4 model to a greenfield app, currently being designed by our R&D team. In this article we present both the C4 guidelines for documenting software architecture and a detailed example of using this model in practice, shown as a step by step process.
What is C4 all about?
The creator of C4, Simon Brown, proposed a four-stage, recipient-focused model of documenting software architecture. The C4 approach is quite transparent, with just a few rules and semantic elements that should be applied to the process of designing system architecture. These features make this approach compatible with agile development methods.
An important feature of this model has already been mentioned: the model is recipient-focused. But what does this mean in practice? For example, a client or a manager might not be interested in how the system is divided into separate environments or what are the physical machines, on which particular components will be installed. What they might actually be interested in is the functionality of the system and its interactions with external systems. Other recipients, like development teams, might in turn need to focus on entirely different architectural elements. And here the C4 model proves to be useful, offering separate diagrams for four levels of system abstraction, namely:
These diagrams, each showing a different level of detail, depict not only the static structure of the system but also the way the system elements interact with each other and with their environment. These levels can be compared to using zoom in maps. As you zoom in, new or more detailed information appears for the select fragment of the map. The same applies to documenting software architecture: the lower the level, the more detailed it is.
The diagrams are optional and depending on the scale and complexity of the designed system, you might not need to use them all. There is a general C4 rule: if information provided at a given level is of no interest to any person working on the project, do not create a diagram for this level.
A major aspect that influences the acceptability of the C4 diagrams is their readability, resulting from the transparent variety of semantic elements used in the C4 methodology. The use of universal and fixed notation, makes it possible to present the complexity of the given system in an easy and intuitive manner. Each element of the diagram should include a name, a type (like “person”, “system”, “container” or “component”) and a short description of its function.
Level 1: System Context
The starting point for creating system architecture is the context in which a given system is embedded. The diagram of this level presents large-scale, highly-abstract information about the system (the big picture). It shows the designed system as the central part of the diagram, along with the way it interacts with external actors and systems. At this stage, the technologies and protocols used are irrelevant for the recipient, as the target recipient is usually the client or the management. Despite the target recipients being so clearly defined, this diagram should be known to and understandable for each person involved in the project.
Level 2: Container diagram
As you delve into the system, you reach a lower level of abstraction: the system structure based on containers. This structure represents the way the responsibility of particular system elements which handle business processes is spread over the system. The container is understood as a separately run or installed unit that executes code or writes data.
This level is quite often referred to as the “deployment architecture”. It shows the way the system is deployed, what its building blocks are and which infrastructural elements it will be installed on. Containers characteristic for this level are: mobile applications, web applications, databases or system queues. At this level, it is essential to provide information about the type of storage or the protocols used for communication between particular containers. This diagram also includes external systems, which had been depicted at the previous level, so as to illustrate the way these systems communicate externally. The target recipients of this diagram are the DevOps teams – the people responsible for the development, maintenance or quality assurance of the system, as well as architects and developers.
Level 3: Components
At this level, you present the inside of a single container, consisting of various components. But what actually is a component? This is a highly ambiguous concept in IT, understood differently by different people. In the C4 model, the component is the true abstraction at code level, i.e. grouped code pieces that share the same database, meaning or functionality. For anyone familiar with Domain-Driven Design, the notion of “Bounded Context” should be quite helpful in defining what a component in C4 is. This level shows the technological aspects connected with the implementation of a given component, i.e. the framework or the programming language used.
Level 4: Classes
Separate classes are depicted at the lowest level of the C4 model. The components defined at the previous level have an internal structure that can be separated into classes or other artefacts. In large and complex systems, a component might be an architectural unit so substantial that it results in a particular architectural style being exhibited at this level (like the layered architectural style for example).
Taking into account that software developers and architects are the target recipients of this level, the classes diagram can be visualised using the UML notation. The class diagram is optional and prone to frequent changes, therefore it should be generated only if there is a justified need and with the help of special tools (for instance included in IDEs).
C4 in practice: the four diagrams
It is our hope to go beyond the standard, often purely theoretical examples of documenting software architecture and to present real-case, C4-compliant diagrams. We have created these diagrams at FIS-SST while designing the architecture of our new greenfield application. The application uses microservices architecture and its working title is “Food Ordering”.
Step 1: System Context
As shown in the provided diagram, each of the elements has a short description of its functionality within the system. As a result, for example in the case of the Notifier, you immediately know what responsibility it has and which elements of the system it is directly connected with.
Step 2: Containers
The next step was to create a diagram showing containers – the units of deployment. Due to the use of microservices in our application, the Container diagram became the most extensive one. It depicts not only all the microservices but also all other relevant infrastructural elements like databases or the message bus. The diagram also shows the interconnectivity of its elements and the message transfer between them. At this level of detail, we presented which microservices communicate with external systems. As a result, the target recipient can easily identify the system boundaries.
Due to the diagram being so detailed, we decided to present it in two versions – a general view and a detailed view (which is a close-up of the Food Ordering application).
Step 3: Components
The Component diagram shows the elements that build up the previously defined containers. It enables you to depict low-level dependencies between various components, which might be especially useful in microservices-based architectures. We decided to break down the “User Microservice” component, as it was one of the more complex elements of our application. We did not characterize other components, having arrived at the conclusion that they would have a similar (and often much simpler) structure.
For the development of our application, we decided to use the Spring framework, with Spring Boot and Spring Cloud. Therefore, in this diagram, we identified elements connected with the selected technology: controllers, services and repositories, including the connections between them. We defined other elements of the system as well, like the Event Listener which listens for the Message Bus events or like the Time Scheduler which is responsible for executing given business logic at defined time intervals.
What about the fourth step?
The examples provided above refer to three out of four levels available in the C4 methodology. The last level, the Class diagram, is often optional. We decided that in this step would be redundant in our case, as our application is still in planning and designing stage. Another factor that influenced our choice was the fact that the class diagram is really prone to change, which is a result of the changing dynamics of the software industry.
And so a question may come to mind – how does the C4 model handle the dynamics of software development projects? Developing software is an ongoing process which involves implementing numerous changes, including major changes of the design. The Class diagram is the diagram that will change most often. Therefore, it might be advisable to use special tools (like IDE modelling tools) for generating the diagrams of different classes and the relations between them. The Component diagram is also sensitive to change, especially if microservices are used. The Container diagram and the System Context diagram, due to the higher abstraction level depicted, require less frequent updates.
One of the guidelines of the C4 methodology is to create a common set of abstract terms used for documenting software, which leads to increased consistency and transparency of communication. What is worth remembering about the C4 approach is that you are supposed to use simple, self-explanatory diagrams and a single, coherent notation. As a result, by implementing C4, you start using the same set of abstractions and the same notation on each and every level of abstraction. And you do so regardless of who your target recipient is – whether it is the management, the client, the DevOps team, the development team or the testing team.
Applying the C4 model does not exclude the use of other ways of documenting software architecture. On the contrary, this model is fully compatible with templates for architecture documentation such as Arc42 and it can be complemented with other notations, like the UML notation.