When the question of describing a system's architecture arises, there are several main solutions for where and how to do it. Popular notations for visualizing architecture diagrams include:

  • C4,

  • ArchiMate,

  • SysML,

  • 4+1,

  • AADL.

In this article, I want to focus on the C4 architecture modeling notation. My goal is to show practical examples of its application that you can use as a guide in your work, as well as tools for creating it.

At the end of the article, I will leave a list of sources where you can find additional theory and examples.

This article is useful for system analysts, architects, developers, project managers, and anyone involved in creating and making decisions about project architecture.

Theory of the C4 Notation

The C4 modeling notation is a method for visualizing software architecture developed by Simon Brown. It is used to create diagrams that describe system architecture.

C4 emerged in response to the complexity and incomprehensibility of traditional architectural diagrams. Simon Brown proposed this approach in the early 2010s to simplify the understanding of architecture for all development team members, including developers, testers, analysts, managers, and other stakeholders.

The name "C4" stands for:

  • Context,

  • Containers,

  • Components,

  • Code.

These four "Cs" represent the four levels of abstraction (views) used in this notation to visualize architecture.

Levels of Architectural Representation in C4 Notation with Examples

A brief and clear description for one project: C4 diagram in Miro with a project example.

For this article, I will create the visualization using code and the tool https://www.structurizr.com/dsl.

? Context

Shows how the system interacts with external entities (users, external systems). Integrations are immediately visible.

Typically used in the initial design stages to understand the overall context.

Elements:
- systems,
- users,
- relationships.

Project example:
The aggregator service
GetDelivery from my channel for system analysts, where I break down system design tasks in practice.

Context - code for https://www.structurizr.com/dsl

workspace {

model {
    user = person "Клиент" "Использует приложение GetDelivery."
    admin = person "Администратор" "Управляет приложением GetDelivery."

    GetDelivery = softwareSystem "GetDelivery" "Сервис доставки." {
        webApp = container "Web-приложение" "Интерфейс для клиентов." "Web Application"
        mobileAppiOS = container "Mobile App iOS" "iOS приложение для клиентов." "iOS"
        mobileAppAndroid = container "Mobile App Android" "Android приложение для клиентов." "Android"
        adminWebApp = container "Web App Admin" "Интерфейс для администраторов." "Web Application"
        backend = container "Backend" "Обрабатывает бизнес-логику." "Server-side Application"
        database = container "База данных" "Хранит информацию о заказах, пользователях и т.д." "Database"
        userDatabase = container "База данных пользователей" "Хранит данные пользователей." "Database"
        reportStorage = container "Файловое хранилище отчетов" "Хранит PDF отчеты." "File Storage"
        logicService = container "Сервис основной логики" "Обрабатывает основные функции системы." "Server-side Application"
        deliveryIntegrationService = container "Сервис интеграций с сервисами доставки" "Интеграция с СДЭК, Возовоз, Деловые Линии." "Server-side Application"
        authService = container "Сервис авторизации и регистрации пользователей" "Управляет авторизацией и регистрацией." "Server-side Application"
        reportService = container "Сервис генерации отчетов" "Генерирует PDF отчеты." "Server-side Application"
    }

    cdek = softwareSystem "СДЭК" "Система доставки."
    vozovoz = softwareSystem "Возовоз" "Система доставки."
    delovieLinii = softwareSystem "Деловые Линии" "Система доставки."

    user -> webApp "Использует"
    user -> mobileAppiOS "Использует"
    user -> mobileAppAndroid "Использует"
    admin -> adminWebApp "Использует"
    webApp -> backend "Взаимодействует"
    mobileAppiOS -> backend "Взаимодействует"
    mobileAppAndroid -> backend "Взаимодействует"
    adminWebApp -> backend "Взаимодействует"
    backend -> database "Использует"
    backend -> userDatabase "Использует"
    backend -> logicService "Использует"
    backend -> deliveryIntegrationService "Использует"
    backend -> authService "Использует"
    backend -> reportService "Использует"
    logicService -> reportStorage "Сохраняет отчеты"
    reportService -> reportStorage "Сохраняет отчеты"
    deliveryIntegrationService -> cdek "Интеграция"
    deliveryIntegrationService -> vozovoz "Интеграция"
    deliveryIntegrationService -> delovieLinii "Интеграция"
}

views {
    systemContext GetDelivery {
        include *
        autolayout lr
    }

    theme default
}
}

Project example: an aggregator service for calculating the most cost-effective delivery price, GetDelivery.

? Container

Describes the high-level architecture and technologies. Used to understand the technology stack and separate areas of responsibility.

Elements:
- containers (e.g., web applications, databases),
- relationships,
- technologies.

Project example: The aggregator service GetDelivery from my channel for system analysts, where I break down system design tasks in practice.

Container - code for https://www.structurizr.com/dsl
workspace {

    model {
        user = person "Клиент" "Использует приложение GetDelivery."
        admin = person "Администратор" "Управляет приложением GetDelivery."

        GetDelivery = softwareSystem "GetDelivery" "Сервис доставки." {
            webApp = container "Web-приложение" "Интерфейс для клиентов." "Web Application"
            mobileAppiOS = container "Mobile App iOS" "iOS приложение для клиентов." "iOS"
            mobileAppAndroid = container "Mobile App Android" "Android приложение для клиентов." "Android"
            adminWebApp = container "Web App Admin" "Интерфейс для администраторов." "Web Application"
            backend = container "Backend" "Обрабатывает бизнес-логику, содержит сервисы и базы данных." "Server-side Application"
        }

        cdek = softwareSystem "СДЭК" "Система доставки." 
        vozovoz = softwareSystem "Возовоз" "Система доставки."
        delovieLinii = softwareSystem "Деловые Линии" "Система доставки."

        user -> webApp "Использует"
        user -> mobileAppiOS "Использует"
        user -> mobileAppAndroid "Использует"
        admin -> adminWebApp "Использует"
        webApp -> backend "API"
        mobileAppiOS -> backend "API"
        mobileAppAndroid -> backend "API"
        adminWebApp -> backend "API"
        backend -> cdek "HTTPS/JSON"
        backend -> vozovoz "HTTPS/JSON"
        backend -> delovieLinii "HTTPS/JSON"
    }

    views {
        container GetDelivery {
            include *
            autolayout lr
        }

        theme default
    }
}

? Component

Details the structure inside a system container, i.e., it describes only one container from the previous level in more detail.

Used for designing and documenting the internal structure of system components.

Elements:
- components,
- relationships,
- technologies,
- dependencies.

Project example: The aggregator service GetDelivery from my channel for system analysts, where I break down system design tasks in practice.

Реализована в Draw.io
Implemented in Draw.io

About Structurizr's Capabilities

Additionally, for this diagram, I want to take an example from the official documentation so you can see how layered and beautifully everything can be done with code within a single diagram.

Example code for a Component diagram and other levels
/*
 * This is a combined version of the following workspaces, with automatic layout enabled:
 *
 * - "Big Bank plc - System Landscape" (https://structurizr.com/share/28201/)
 * - "Big Bank plc - Internet Banking System" (https://structurizr.com/share/36141/)
*/
workspace "Big Bank plc" "This is an example workspace to illustrate the key features of Structurizr, via the DSL, based around a fictional online banking system." {

    model {
        customer = person "Personal Banking Customer" "A customer of the bank, with personal bank accounts." "Customer"

        group "Big Bank plc" {
            supportStaff = person "Customer Service Staff" "Customer service staff within the bank." "Bank Staff"
            backoffice = person "Back Office Staff" "Administration and support staff within the bank." "Bank Staff"

            mainframe = softwaresystem "Mainframe Banking System" "Stores all of the core banking information about customers, accounts, transactions, etc." "Existing System"
            email = softwaresystem "E-mail System" "The internal Microsoft Exchange e-mail system." "Existing System"
            atm = softwaresystem "ATM" "Allows customers to withdraw cash." "Existing System"

            internetBankingSystem = softwaresystem "Internet Banking System" "Allows customers to view information about their bank accounts, and make payments." {
                singlePageApplication = container "Single-Page Application" "Provides all of the Internet banking functionality to customers via their web browser." "JavaScript and Angular" "Web Browser"
                mobileApp = container "Mobile App" "Provides a limited subset of the Internet banking functionality to customers via their mobile device." "Xamarin" "Mobile App"
                webApplication = container "Web Application" "Delivers the static content and the Internet banking single page application." "Java and Spring MVC"
                apiApplication = container "API Application" "Provides Internet banking functionality via a JSON/HTTPS API." "Java and Spring MVC" {
                    signinController = component "Sign In Controller" "Allows users to sign in to the Internet Banking System." "Spring MVC Rest Controller"
                    accountsSummaryController = component "Accounts Summary Controller" "Provides customers with a summary of their bank accounts." "Spring MVC Rest Controller"
                    resetPasswordController = component "Reset Password Controller" "Allows users to reset their passwords with a single use URL." "Spring MVC Rest Controller"
                    securityComponent = component "Security Component" "Provides functionality related to signing in, changing passwords, etc." "Spring Bean"
                    mainframeBankingSystemFacade = component "Mainframe Banking System Facade" "A facade onto the mainframe banking system." "Spring Bean"
                    emailComponent = component "E-mail Component" "Sends e-mails to users." "Spring Bean"
                }
                database = container "Database" "Stores user registration information, hashed authentication credentials, access logs, etc." "Oracle Database Schema" "Database"
            }
        }

        # relationships between people and software systems
        customer -> internetBankingSystem "Views account balances, and makes payments using"
        internetBankingSystem -> mainframe "Gets account information from, and makes payments using"
        internetBankingSystem -> email "Sends e-mail using"
        email -> customer "Sends e-mails to"
        customer -> supportStaff "Asks questions to" "Telephone"
        supportStaff -> mainframe "Uses"
        customer -> atm "Withdraws cash using"
        atm -> mainframe "Uses"
        backoffice -> mainframe "Uses"

        # relationships to/from containers
        customer -> webApplication "Visits bigbank.com/ib using" "HTTPS"
        customer -> singlePageApplication "Views account balances, and makes payments using"
        customer -> mobileApp "Views account balances, and makes payments using"
        webApplication -> singlePageApplication "Delivers to the customer's web browser"

        # relationships to/from components
        singlePageApplication -> signinController "Makes API calls to" "JSON/HTTPS"
        singlePageApplication -> accountsSummaryController "Makes API calls to" "JSON/HTTPS"
        singlePageApplication -> resetPasswordController "Makes API calls to" "JSON/HTTPS"
        mobileApp -> signinController "Makes API calls to" "JSON/HTTPS"
        mobileApp -> accountsSummaryController "Makes API calls to" "JSON/HTTPS"
        mobileApp -> resetPasswordController "Makes API calls to" "JSON/HTTPS"
        signinController -> securityComponent "Uses"
        accountsSummaryController -> mainframeBankingSystemFacade "Uses"
        resetPasswordController -> securityComponent "Uses"
        resetPasswordController -> emailComponent "Uses"
        securityComponent -> database "Reads from and writes to" "SQL/TCP"
        mainframeBankingSystemFacade -> mainframe "Makes API calls to" "XML/HTTPS"
        emailComponent -> email "Sends e-mail using"

        deploymentEnvironment "Development" {
            deploymentNode "Developer Laptop" "" "Microsoft Windows 10 or Apple macOS" {
                deploymentNode "Web Browser" "" "Chrome, Firefox, Safari, or Edge" {
                    developerSinglePageApplicationInstance = containerInstance singlePageApplication
                }
                deploymentNode "Docker Container - Web Server" "" "Docker" {
                    deploymentNode "Apache Tomcat" "" "Apache Tomcat 8.x" {
                        developerWebApplicationInstance = containerInstance webApplication
                        developerApiApplicationInstance = containerInstance apiApplication
                    }
                }
                deploymentNode "Docker Container - Database Server" "" "Docker" {
                    deploymentNode "Database Server" "" "Oracle 12c" {
                        developerDatabaseInstance = containerInstance database
                    }
                }
            }
            deploymentNode "Big Bank plc" "" "Big Bank plc data center" "" {
                deploymentNode "bigbank-dev001" "" "" "" {
                    softwareSystemInstance mainframe
                }
            }

        }

        deploymentEnvironment "Live" {
            deploymentNode "Customer's mobile device" "" "Apple iOS or Android" {
                liveMobileAppInstance = containerInstance mobileApp
            }
            deploymentNode "Customer's computer" "" "Microsoft Windows or Apple macOS" {
                deploymentNode "Web Browser" "" "Chrome, Firefox, Safari, or Edge" {
                    liveSinglePageApplicationInstance = containerInstance singlePageApplication
                }
            }

            deploymentNode "Big Bank plc" "" "Big Bank plc data center" {
                deploymentNode "bigbank-web***" "" "Ubuntu 16.04 LTS" "" 4 {
                    deploymentNode "Apache Tomcat" "" "Apache Tomcat 8.x" {
                        liveWebApplicationInstance = containerInstance webApplication
                    }
                }
                deploymentNode "bigbank-api***" "" "Ubuntu 16.04 LTS" "" 8 {
                    deploymentNode "Apache Tomcat" "" "Apache Tomcat 8.x" {
                        liveApiApplicationInstance = containerInstance apiApplication
                    }
                }

                deploymentNode "bigbank-db01" "" "Ubuntu 16.04 LTS" {
                    primaryDatabaseServer = deploymentNode "Oracle - Primary" "" "Oracle 12c" {
                        livePrimaryDatabaseInstance = containerInstance database
                    }
                }
                deploymentNode "bigbank-db02" "" "Ubuntu 16.04 LTS" "Failover" {
                    secondaryDatabaseServer = deploymentNode "Oracle - Secondary" "" "Oracle 12c" "Failover" {
                        liveSecondaryDatabaseInstance = containerInstance database "Failover"
                    }
                }
                deploymentNode "bigbank-prod001" "" "" "" {
                    softwareSystemInstance mainframe
                }
            }

            primaryDatabaseServer -> secondaryDatabaseServer "Replicates data to"
        }
    }

    views {
        systemlandscape "SystemLandscape" {
            include *
            autoLayout
        }

        systemcontext internetBankingSystem "SystemContext" {
            include *
            animation {
                internetBankingSystem
                customer
                mainframe
                email
            }
            autoLayout
            description "The system context diagram for the Internet Banking System."
            properties {
                structurizr.groups false
            }
        }

        container internetBankingSystem "Containers" {
            include *
            animation {
                customer mainframe email
                webApplication
                singlePageApplication
                mobileApp
                apiApplication
                database
            }
            autoLayout
            description "The container diagram for the Internet Banking System."
        }

        component apiApplication "Components" {
            include *
            animation {
                singlePageApplication mobileApp database email mainframe
                signinController securityComponent
                accountsSummaryController mainframeBankingSystemFacade
                resetPasswordController emailComponent
            }
            autoLayout
            description "The component diagram for the API Application."
        }

        image mainframeBankingSystemFacade "MainframeBankingSystemFacade" {
            image https://raw.githubusercontent.com/structurizr/examples/main/dsl/big-bank-plc/internet-banking-system/mainframe-banking-system-facade.png
            title "[Code] Mainframe Banking System Facade"
        }

        dynamic apiApplication "SignIn" "Summarises how the sign in feature works in the single-page application." {
            singlePageApplication -> signinController "Submits credentials to"
            signinController -> securityComponent "Validates credentials using"
            securityComponent -> database "select * from users where username = ?"
            database -> securityComponent "Returns user data to"
            securityComponent -> signinController "Returns true if the hashed password matches"
            signinController -> singlePageApplication "Sends back an authentication token to"
            autoLayout
            description "Summarises how the sign in feature works in the single-page application."
        }

        deployment internetBankingSystem "Development" "DevelopmentDeployment" {
            include *
            animation {
                developerSinglePageApplicationInstance
                developerWebApplicationInstance developerApiApplicationInstance
                developerDatabaseInstance
            }
            autoLayout
            description "An example development deployment scenario for the Internet Banking System."
        }

        deployment internetBankingSystem "Live" "LiveDeployment" {
            include *
            animation {
                liveSinglePageApplicationInstance
                liveMobileAppInstance
                liveWebApplicationInstance liveApiApplicationInstance
                livePrimaryDatabaseInstance
                liveSecondaryDatabaseInstance
            }
            autoLayout
            description "An example live deployment scenario for the Internet Banking System."
        }

        styles {
            element "Person" {
                color #ffffff
                fontSize 22
                shape Person
            }
            element "Customer" {
                background #08427b
            }
            element "Bank Staff" {
                background #999999
            }
            element "Software System" {
                background #1168bd
                color #ffffff
            }
            element "Existing System" {
                background #999999
                color #ffffff
            }
            element "Container" {
                background #438dd5
                color #ffffff
            }
            element "Web Browser" {
                shape WebBrowser
            }
            element "Mobile App" {
                shape MobileDeviceLandscape
            }
            element "Database" {
                shape Cylinder
            }
            element "Component" {
                background #85bbf0
                color #000000
            }
            element "Failover" {
                opacity 25
            }
        }
    }
}

Source: https://github.com/structurizr/examples/tree/main/dsl (big-bank-pic)

If you copy the code and paste it into https://www.structurizr.com/dsl, you will see the following:

An additional example of the Component level from Miro for the Pet Store project:

? Code

Shows the implementation details of individual components.

Used for documenting code structure. In practice, it is not used because developers don't need it. It's like a UML class diagram: it seems useful to understand, but in reality, it's not needed.

Elements:
- classes,
- interfaces,
- relationships between them.

An example can be found on the notation author's website - Simon Brown's banking project.

Where to Create C4 Diagrams - Tools

To create diagrams in C4 notation, you can use:

  • graphical tools,

  • code-based visualization tools (+ ChatGPT).

Using tools that allow describing C4 through code can speed up the process by leveraging artificial intelligence - ChatGPT or a similar tool.

1. Draw.io — A Graphical Tool

Draw.io (diagrams.net) is a free online tool suitable for creating various types of diagrams, including C4. It provides a wide range of design elements, making it convenient for quickly creating diagrams.

There are downsides to editing when a diagram has many elements: sometimes you move something you didn't intend to, or not in the way you wanted.

Pros:
+ Free;
+ Supports all types of diagrams;
+ Integrates with Confluence, Google Drive, and other commonly used programs.

Cons:
- Large diagrams are a pain to edit. This is a problem with all graphical editors.

Conclusion:
If I need to draw an architecture diagram in C4 notation using a graphical tool, I will do it in Draw.io. At GetAnalyst, we use this tool as our primary one.

How to enable C4 in Draw.io
Добавление элементов С4 в Draw.io
Adding C4 elements in Draw.io
Пример C4 в Draw.io
C4 example in Draw.io

2. Miro — A Graphical Tool

Miro is an online platform for visually creating and discussing projects on digital whiteboards, which can also be used to create C4 diagrams.

To use Miro as a tool for visualizing architecture diagrams, I recommend you take my Miro template with C4 elements and copy the elements from it.

Pros:
+ Integrates with Confluence, Google Drive, and other commonly used programs.
+ Pleasant and user-friendly interface, looks more modern than Draw.io.

Cons:
- Limited number of free boards, so it's conditionally paid.
- Large diagrams are a pain to edit.
- C4 elements are not standard in Miro, which can lead to editing problems.

Conclusion:
When comparing the experience of working with Miro and Draw.io, I remain a proponent of the simpler and more convenient Draw.io, as for Miro, the ability to draw C4 is more of an unexpected option than a convenient feature.

Шаблон Miro с элементами C4
Miro template with C4 elements

3. Microsoft Visio — A Graphical Tool

Microsoft Visio from Microsoft is a professional solution for creating complex diagrams. It is similar in functionality to Draw.io, and you will likely have to create C4 element templates first, as in Miro.

Pros:
+ Widely used in IT companies.

Cons:
- Paid.
- Works offline, although for some this might be a plus.
- Not designed for C4.

Conclusion:
I would choose draw.io, as I haven't opened Visio in several years and haven't used Windows for over a year.

4. Structurizr — A Code-Based Visualization Tool

Structurizr is one of the most specialized tools for creating C4 diagrams. Structurizr allows you to define them through code, which provides high flexibility and accuracy in describing the architecture.

To use Structurizr to describe architecture in C4 notation:

  1. Use the online interface with the DSL editor: https://www.structurizr.com/dsl.

  2. Write or paste the code below into the Structurizr editor.

  3. Click "Render" at the top right, above the code panel, to see your diagram.

Pros:
+ Free.
+ Easy to use.
+ Understandable markup language for "drawing".
+ Supports code generation via artificial intelligence (ChatGPT).
+ Visually simple and clear.
+ Clean interface - no junk ads.
+ You can even write Java code for visualization.
+ Amazing knowledge base with examples in English.

Cons:
- There may be difficulties with visualizing large diagrams.

Conclusion:
Take it and use it.

Code Examples for Structurizr - Context

Code for the Context level diagram:

workspace {

    model {
        user = person "Пользователь" "Описание пользователя."
        bankingSystem = softwareSystem "Банковская Система" "Описание банковской системы."

        user -> bankingSystem "Использует" "HTTPS"
    }

    views {
        systemContext bankingSystem {
            include *
            autoLayout lr
        }

        theme default
    }
}

This code creates a context diagram with two elements:

  1. "User" (displayed as Person in PlantUML), who interacts with the system.

  2. "Banking System" (displayed as System), which represents an external system with which the user interacts.

A relationship is established between these elements with the description "Uses" and the protocol "HTTPS".

Code Examples for Structurizr - Container

Code for the Container level:

workspace {

    model {
        user = person "Пользователь" "Описание пользователя."

        bankingSystem = softwareSystem "Банковская Система" {
            webApp = container "Веб-приложение" "Предоставляет банковские услуги онлайн." "Java"
            db = container "База Данных" "Хранит данные о счетах и транзакциях." "MySQL"
            api = container "API" "Предоставляет API для доступа к данным." "RESTful"
        }

        user -> webApp "Использует" "HTTPS"
        webApp -> db "Читает/записывает" "JDBC"
        api -> db "Запрашивает" "JDBC"
    }

    views {
        container bankingSystem {
            include *
            autoLayout lr
        }

        theme default
    }
}

This code creates a container diagram within the "Banking System". Here we see:

  1. User, who interacts with the web application.

  2. In the Banking System, three containers are now defined:

    • Web Application: Represents a user interface written in Java.

    • Database: A MySQL database that stores information.

    • API: A RESTful API for accessing database data.

Code Examples for Structurizr - Component

Details the "Web Application" container from the previous example.

In this example, we focus on the components inside the "Web Application":

It also shows the relationships between these components, as well as their interaction with external containers such as the "API" and the physical "Database".

Code for the Component level:

workspace {

    model {
        user = person "Пользователь" "Описание пользователя."
        
        
        bankingSystem = softwareSystem "Банковская Система" {
        webApp = container "Веб-приложение" {
            ui = component "Пользовательский Интерфейс" "Angular, Предоставляет веб-интерфейс для пользователей."
            server = component "Серверная Логика" "Spring Boot, Обрабатывает запросы от пользовательского интерфейса."
            databaseComponent = component "Компонент Базы Данных" "JPA/Hibernate, Обеспечивает доступ к данным."
        }

        api = container "API" "RESTful, Предоставляет API для доступа к данным."
        db = container "База Данных" "MySQL, Хранит данные о счетах и транзакциях."

        user -> ui "Использует" "HTTPS"
        ui -> server "Вызывает" "JSON/HTTP"
        server -> databaseComponent "Использует" "JDBC"
        server -> api "Делает запросы" "JSON/HTTP"
        databaseComponent -> db "Читает/Записывает" "JDBC"
        }
    }

    views {
        component webApp {
            include *
            autoLayout lr
        }

        theme default
    }
}

5. PlantUML — A Code-Based Visualization Tool

PlantUML is a tool that allows you to create UML diagrams from a text description. It supports syntax for creating C4 diagrams but works intermittently - it periodically fails to load the visualizer from a link and throws an error. Therefore, I recommend using it only if you have a great love for PlantUML.

Pros:
+ You can neatly visualize diagrams through code.

Cons:
- Works unstably.

Conclusion:
Structurizr is better suited for creating C4 diagrams through code.

To use PlantUML to describe architecture in C4 notation:

  1. Use an online PlantUML interface, such as PlantText or the online PlantUML editor on the plantuml.com website.

  2. Write or paste the code below into the PlantUML editor.

  3. The diagram will be automatically generated based on this text description. Alternatively, click "Submit".

*In case of display problems due to the unavailability of the URL https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Context.puml within PlantUML, change your browser or switch between day and night modes several times (the switch is to the right of the "Submit" button).

Code Examples for PlantUML

Context

Example PlantUML code for a Context level diagram:

@startuml C4_Example
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Context.puml

LAYOUT_WITH_LEGEND()

Person(user, "Пользователь", "Описание пользователя.")
System(bankingSystem, "Банковская Система", "Описание банковской системы.")

Rel(user, bankingSystem, "Использует", "HTTPS")
@enduml

*If you don't see the diagram immediately, switch to the dark/light theme or change your browser. There can be problems establishing a connection.

Куча рекламы вокруг печалит.
The amount of surrounding ads is saddening.

Container

Code for the Container level:

@startuml C4_Containers
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml

LAYOUT_WITH_LEGEND()

Person(user, "Пользователь", "Описание пользователя.")

System_Boundary(bankingSys, "Банковская Система") {
    Container(webApp, "Веб-приложение", "Java", "Предоставляет банковские услуги онлайн.")
    Container(db, "База Данных", "MySQL", "Хранит данные о счетах и транзакциях.")
    Container(api, "API", "RESTful", "Предоставляет API для доступа к данным.")
}

Rel(user, webApp, "Использует", "HTTPS")
Rel(webApp, db, "Читает/записывает", "JDBC")
Rel(api, db, "Запрашивает", "JDBC")
@enduml

Component

Let's detail the "Web Application" from the previous example. Code for the Component level:

@startuml
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml

LAYOUT_WITH_LEGEND()

Container_Boundary(webApp, "Веб-приложение") {
    Component(ui, "Пользовательский Интерфейс", "Angular", "Предоставляет веб-интерфейс для пользователей.")
    Component(server, "Серверная Логика", "Spring Boot", "Обрабатывает запросы от пользовательского интерфейса.")
    Component(database, "База Данных", "JPA/Hibernate", "Обеспечивает доступ к данным.")
}

Container(api, "API", "RESTful", "Предоставляет API для доступа к данным.")
Container(db, "База Данных", "MySQL", "Хранит данные о счетах и транзакциях.")

Person(user, "Пользователь", "Описание пользователя.")
Rel(user, ui, "Использует", "HTTPS")

Rel(ui, server, "Вызывает", "JSON/HTTP")
Rel(server, database, "Использует", "JDBC")
Rel(server, api, "Делает запросы", "JSON/HTTP")
Rel(database, db, "Читает/Записывает", "JDBC")
@enduml

Conclusions

The choice of tool depends on personal preferences, project requirements, and comfort level with specific tools. Some prefer tools with a graphical interface for a more intuitive process, while others may choose code-based tools for greater automation and precision.

I recommend Draw.io and Structurizr for creating C4 diagrams.

Conclusion

I consider C4 to be the most understandable and accessible architecture modeling notation that helps the development team. The diagrams are easily read by all participants because they contain a limited set of symbols.

In my own practice as a system analyst, I also often use simplified models based on C4 when I need to show something large. On large diagrams, C4 rectangles take up a lot of space, making it difficult to view the diagram on a small monitor, and even on a large one.

The most useful levels:

  • Context — a general overview, useful for understanding external interactions with the system - integrations.

  • Container — the internal structure of the system, suitable for understanding what web, mobile, server, and other types of applications exist.

  • Component — ideal for documenting Backend architecture, the main level of architecture description that requires attention on a project.

The code level, Code, I consider a waste of time. As a system analyst, I don't deal with designing code structure, and having developers document code in C4 or a UML class diagram would more likely give me a sense of bureaucratic shock than admiration. It's better to just leave good comments.

Additional examples of architecture diagrams can be found on my channel in this post, and in the posts above and below it.

If you want to introduce an architecture documentation standard in your company, the C4 notation is ideal to start with (and then adapt it to your own needs, if necessary).

The C4 notation is a powerful tool that provides clarity and structure to the process of designing system architecture. This notation not only helps architects and developers create a holistic view of the system but also improves communication between developers, architects, project managers, analysts, and other stakeholders.

Additional Information

Theory and Examples

  1. The C4 model for visualising software architecture
    The C4 model and this website were created by Simon Brown
    The primary source with theory on the notation, where you can find answers to "how to do it correctly..." questions.

  2. Architecture examples for integration projects:

    1. Online Pet Store.

    2. Logistics service: from monolith to microservices.

  3. Another good article on Habr with a neat example and theory.
    How to describe a large system in C4 notation.

Tools

  1. Example of a project architecture diagram in Miro - online pet store
    Ekaterina Ananyeva
    An example of an architecture diagram in C4 notation, which can be used to study the notation and from which you can transfer element templates to your own Miro board.

  2. C4 Model with PlantUML (Eng)
    Huseyin Kutluca
    An article about the possibility of using PlantUML to create diagrams in C4 notation. It provides additional examples for study and a better understanding of the code-writing approach.

  3. https://github.com/structurizr/examples/tree/main/dsl
    A database of examples for the structurizr tool, which can be used to describe C4 diagrams through code.