<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ C4 Model - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ C4 Model - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Thu, 25 Jun 2026 04:44:35 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/c4-model/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Create Software Architecture Diagrams Using the C4 Model ]]>
                </title>
                <description>
                    <![CDATA[ As a developer, you'll likely work on a complex project at some point where deciphering the codebase feels like reading a whole novel. Engineers are code wizards, but even the best get lost in sprawling code. The challenge is that architecture diagra... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-software-architecture-diagrams-using-the-c4-model/</link>
                <guid isPermaLink="false">66c636dc83227f02672177db</guid>
                
                    <category>
                        <![CDATA[ Software Engineering ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ design patterns ]]>
                    </category>
                
                    <category>
                        <![CDATA[ C4 Model ]]>
                    </category>
                
                    <category>
                        <![CDATA[ diagrams ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Alex Pliutau ]]>
                </dc:creator>
                <pubDate>Wed, 21 Aug 2024 18:50:04 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1724187048778/7d2821c6-c0c9-4d03-999f-37022388210c.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>As a developer, you'll likely work on a complex project at some point where deciphering the codebase feels like reading a whole novel. Engineers are code wizards, but even the best get lost in sprawling code.</p>
<p>The challenge is that architecture diagrams – if they even exist – are often outdated relics from a bygone era.</p>
<p>This is why creating and maintaining effective and clear diagrams should be effortless. Up-to-date visuals ensure everyone stays on the same page, eliminating confusion and wasted time.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a target="_blank" href="heading-what-is-the-c4-model">What is the C4 Model?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-level-1-context">Level 1: Context</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-level-2-containers">Level 2: Containers</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-level-3-components">Level 3: Components</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-level-4-code">Level 4: Code</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-supplementary-diagrams">Supplementary Diagrams</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-diagrams-as-code">Diagrams as Code</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-automate-rendering-in-your-ci">Automate Rendering in Your CI</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-resources">Resources</a></p>
</li>
</ul>
<h2 id="heading-what-is-the-c4-model">What is the C4 Model?</h2>
<p>The <a target="_blank" href="https://c4model.com/">C4 model</a> was created as a way to help software development teams describe and communicate software architecture.</p>
<p>C4 stands for “Context, Containers, Components, and Code”. Those are the four levels that should be enough to describe a complex system.</p>
<p>The best way to explain the concept is to think about how we use Google Maps. When we are exploring an area in Google Maps, we will often start zoomed out to help us get context. Once we find the rough area we are interested in we can zoom in to get a little more detail.</p>
<h3 id="heading-level-1-context">Level 1: Context</h3>
<p>This level is the most zoomed out. It's a bird’s eye view of the system in the greater context of the world. The diagram concentrates on actors and systems.</p>
<p>For the examples below, we will use a simple Task Management Software System to demonstrate all these 4 levels.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d096cb9-3058-4bbd-9c69-6a41361e4d3b_1600x2000.png" alt="Diagram showing the context Level" width="1456" height="1820" loading="lazy"></p>
<p>This diagram portrays the Task Management Software System's interactions with external systems and the different user groups that utilize it. We can see that the Task Management software relies on two external systems: Email and Calendar, and two types of actors (users) use it: Customer and Admin User.</p>
<h3 id="heading-level-2-containers">Level 2: Containers</h3>
<p>The containers level is a more detailed view of your system (don’t confuse C4 containers with Docker containers).</p>
<p>It reveals how various functional units like applications and databases work together and distribute responsibilities.</p>
<p>This diagram also highlights the key technologies employed and showcases the communication flow between these containers. It presents a simplified, technology-centric view of the system's core components and their interactions.</p>
<p>If you have Microservice architecture, then each Microservice would be a container.</p>
<p>Examples of containers are:</p>
<ul>
<li><p>Single page application</p>
</li>
<li><p>Web server</p>
</li>
<li><p>Serverless function</p>
</li>
<li><p>Database</p>
</li>
<li><p>API</p>
</li>
<li><p>Message buses</p>
</li>
</ul>
<p>And so on.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb614c4e5-4fbd-4e10-8682-c3e67ec72f2d_3028x2691.png" alt="Diagram showing the Containers Level" width="1456" height="1294" loading="lazy"></p>
<p>This level delves into the internal composition of the Task Management Software System. It showcases that our Task Management software system consists of containers such as User Web UI, Admin Web UI, API and a Database. API is also the container that is connected to external systems, for example to send emails or create events in calendar.</p>
<h3 id="heading-level-3-components">Level 3: Components</h3>
<p>The next level of zoom is components. This shows the major structural building blocks of your application, and is often a conceptual view of the application. The term component is loose here. It could represent a controller or a service containing business logic.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55564aaa-d404-4322-a6f3-9674326410d5_1995x1900.png" alt="Diagram showing the Components Level" width="1456" height="1387" loading="lazy"></p>
<p>This diagram focuses on the internal structure of the API container within the Task Management Software System. It reveals that the API container houses crucial functionalities like CRUD operations (Create, Read, Update, Delete) for data manipulation and user authentication mechanisms. The CRUD components is the one that talks to the database.</p>
<h3 id="heading-level-4-code">Level 4: Code</h3>
<p>The deepest level of zoom is the code diagram. Although this diagram exists, it is often not used as the code paints a very similar picture. However, in highly regulated environments and complex legacy projects this level can help to paint a better picture of inner intricacies of the software.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde6e40f0-d713-46b9-906e-618fb61eb622_602x339.png" alt="https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde6e40f0-d713-46b9-906e-618fb61eb622_602x339" width="602" height="339" loading="lazy"></p>
<h3 id="heading-supplementary-diagrams">Supplementary Diagrams</h3>
<p>Besides the 4 diagrams above, there are a couple more worth mentioning:</p>
<ul>
<li><p>Deployment diagram</p>
</li>
<li><p>Dynamic diagram: to describe the process or a flow</p>
</li>
</ul>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa13b10a-2093-4ab8-8302-dc75b09be96f_1570x1461.png" alt="Login Flow" width="1456" height="1355" loading="lazy"></p>
<p>On this diagram we show a Login Flow, which is not a container or component, but rather a software process that happens in our software system. It shows that Web/Admin UIs use JWT-based authentication for communication with the API and the JWT token is stored in local storage on a client side.</p>
<h2 id="heading-diagrams-as-code">Diagrams as Code</h2>
<p>The power of C4 comes with a diagram-as-code approach. This means treating your diagrams just like your codebase:</p>
<ul>
<li><p><strong>Version control:</strong> Store them in a source control system (like Git) for easy tracking and collaboration.</p>
</li>
<li><p><strong>Collaboration:</strong> Work together on diagrams using pull requests, similar to code reviews.</p>
</li>
<li><p><strong>Automation:</strong> Integrate them into your build pipelines for automatic rendering with your preferred tools.</p>
</li>
</ul>
<h3 id="heading-helpful-tool-structurizr">Helpful Tool: Structurizr</h3>
<p>There are few tools to help with modeling and diagramming, but the most popular nowadays is <a target="_blank" href="https://www.structurizr.com/">Structurizr</a> with their custom DSL (Domain Specific Language).</p>
<p>All you need is to get familiar with the DSL syntax, which is pretty simple. As long as you get used to it you will be able to create or update diagrams in no time.</p>
<p>Below you can see the DSL for our Task Management Software System.</p>
<pre><code class="lang-bash">workspace {
    model {
        <span class="hljs-comment"># Actors</span>
        customer = person <span class="hljs-string">"Customer"</span> <span class="hljs-string">""</span> <span class="hljs-string">"person"</span>
        admin = person <span class="hljs-string">"Admin User"</span> <span class="hljs-string">""</span> <span class="hljs-string">"person"</span>

        <span class="hljs-comment"># External systems</span>
        emailSystem = softwareSystem <span class="hljs-string">"Email System"</span> <span class="hljs-string">"Mailgun"</span> <span class="hljs-string">"external"</span>
        calendarSystem = softwareSystem <span class="hljs-string">"Calendar System"</span> <span class="hljs-string">"Calendly"</span> <span class="hljs-string">"external"</span>

        <span class="hljs-comment"># Task Management System</span>
        taskManagementSystem  = softwareSystem <span class="hljs-string">"Task Management System"</span>{
            webContainer = container <span class="hljs-string">"User Web UI"</span> <span class="hljs-string">""</span> <span class="hljs-string">""</span> <span class="hljs-string">"frontend"</span>
            adminContainer = container <span class="hljs-string">"Admin Web UI"</span> <span class="hljs-string">""</span> <span class="hljs-string">""</span> <span class="hljs-string">"frontend"</span>
            dbContainer = container <span class="hljs-string">"Database"</span> <span class="hljs-string">"PostgreSQL"</span> <span class="hljs-string">""</span> <span class="hljs-string">"database"</span>
            apiContainer = container <span class="hljs-string">"API"</span> <span class="hljs-string">"Go"</span> {
                authComp = component <span class="hljs-string">"Authentication"</span>
                crudComp = component <span class="hljs-string">"CRUD"</span>
            }
        }

        <span class="hljs-comment"># Relationships (Actors &amp; Systems)</span>
        customer -&gt; webContainer <span class="hljs-string">"Manages tasks"</span>
        admin -&gt; adminContainer <span class="hljs-string">"Manages users"</span>
        apiContainer -&gt; emailSystem <span class="hljs-string">"Sends emails"</span>
        apiContainer -&gt; calendarSystem <span class="hljs-string">"Creates tasks in Calendar"</span>

        <span class="hljs-comment"># Relationships (Containers)</span>
        webContainer -&gt; apiContainer <span class="hljs-string">"Uses"</span>
        adminContainer -&gt; apiContainer <span class="hljs-string">"Uses"</span>
        apiContainer -&gt; dbContainer <span class="hljs-string">"Persists data"</span>

        <span class="hljs-comment"># Relationships (Components &amp; Containers)</span>
        crudComp -&gt; dbContainer <span class="hljs-string">"Reads from and writes to"</span>
        webContainer -&gt; authComp <span class="hljs-string">"Authenticates using"</span>
        adminContainer -&gt; authComp <span class="hljs-string">"Authenticates using"</span>
    }
}
</code></pre>
<p>Let's dive into the most important parts:</p>
<pre><code class="lang-yaml"><span class="hljs-string">workspace</span> [<span class="hljs-string">name</span>] [<span class="hljs-string">description</span>] {
    <span class="hljs-string">model</span> {
    }
}
</code></pre>
<p>Here we define our workspace which should have at least one model. A workspace can optionally be given a name and description.</p>
<pre><code class="lang-yaml"><span class="hljs-string">customer</span> <span class="hljs-string">=</span> <span class="hljs-string">person</span> <span class="hljs-string">"Customer"</span> <span class="hljs-string">""</span> <span class="hljs-string">"person"</span>
<span class="hljs-string">admin</span> <span class="hljs-string">=</span> <span class="hljs-string">person</span> <span class="hljs-string">"Admin User"</span> <span class="hljs-string">""</span> <span class="hljs-string">"person"</span>
</code></pre>
<p>In this section we define our persons (for example, a user, actor, role, or persona) in the following format: <code>person &lt;name&gt; [description] [tags]</code>.</p>
<p>You can use a similar format (name, description, tags) to identify the external systems:</p>
<pre><code class="lang-yaml">        <span class="hljs-string">emailSystem</span> <span class="hljs-string">=</span> <span class="hljs-string">softwareSystem</span> <span class="hljs-string">"Email System"</span> <span class="hljs-string">"Mailgun"</span> <span class="hljs-string">"external"</span>
        <span class="hljs-string">calendarSystem</span> <span class="hljs-string">=</span> <span class="hljs-string">softwareSystem</span> <span class="hljs-string">"Calendar System"</span> <span class="hljs-string">"Calendly"</span> <span class="hljs-string">"external"</span>
</code></pre>
<p>To describe the internal software system we need to write a block that also shows its containers and components:</p>
<pre><code class="lang-yaml"><span class="hljs-string">taskManagementSystem</span>  <span class="hljs-string">=</span> <span class="hljs-string">softwareSystem</span> <span class="hljs-string">"Task Management System"</span>{
    <span class="hljs-string">webContainer</span> <span class="hljs-string">=</span> <span class="hljs-string">container</span> <span class="hljs-string">"User Web UI"</span> <span class="hljs-string">""</span> <span class="hljs-string">""</span> <span class="hljs-string">"frontend"</span>
    <span class="hljs-string">adminContainer</span> <span class="hljs-string">=</span> <span class="hljs-string">container</span> <span class="hljs-string">"Admin Web UI"</span> <span class="hljs-string">""</span> <span class="hljs-string">""</span> <span class="hljs-string">"frontend"</span>
    <span class="hljs-string">dbContainer</span> <span class="hljs-string">=</span> <span class="hljs-string">container</span> <span class="hljs-string">"Database"</span> <span class="hljs-string">"PostgreSQL"</span> <span class="hljs-string">""</span> <span class="hljs-string">"database"</span>
    <span class="hljs-string">apiContainer</span> <span class="hljs-string">=</span> <span class="hljs-string">container</span> <span class="hljs-string">"API"</span> <span class="hljs-string">"Go"</span> {
        <span class="hljs-string">authComp</span> <span class="hljs-string">=</span> <span class="hljs-string">component</span> <span class="hljs-string">"Authentication"</span>
        <span class="hljs-string">crudComp</span> <span class="hljs-string">=</span> <span class="hljs-string">component</span> <span class="hljs-string">"CRUD"</span>
    }
}
</code></pre>
<ul>
<li><p>Container format: <code>container &lt;name&gt; [description] [technology] [tags]</code></p>
</li>
<li><p>Component format: <code>component &lt;name&gt; [description] [technology] [tags]</code></p>
</li>
</ul>
<p>The rest of the model is the most interesting part where we define the relationships between all parts (systems, containers, components):</p>
<pre><code class="lang-yaml"><span class="hljs-string">apiContainer</span> <span class="hljs-string">-&gt;</span> <span class="hljs-string">emailSystem</span> <span class="hljs-string">"Sends emails"</span>
</code></pre>
<p>The following format is used: <code>&lt;identifier&gt; -&gt; &lt;identifier&gt; [description] [technology] [tags]</code>.</p>
<p>There are other features available in Structurizr DSL, such as styling, themes, visibility, etc. You can find find them <a target="_blank" href="https://docs.structurizr.com/dsl/language">here</a>.</p>
<h2 id="heading-automate-rendering-in-your-ci">Automate Rendering in Your CI</h2>
<p>Since you can host your models on GitHub, it is very easy to automate the pipeline for rendering the diagrams in the tools of your choice.</p>
<p>In our case, Structurizr has a GitHub Action that allows you to run <strong>structurizr-cli</strong>, a command line utility for Structurizr that lets you create software architecture models based upon the C4 model using a textual domain specific language (DSL).</p>
<p>This sample repository contains a <a target="_blank" href="https://github.com/plutov/c4-diagram-example/blob/main/.github/workflows/pages.yaml">workflow</a> that simply generates a static page and publishes it to GitHub Pages.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">name:</span> <span class="hljs-string">Deploy</span> <span class="hljs-string">static</span> <span class="hljs-string">content</span> <span class="hljs-string">to</span> <span class="hljs-string">Github</span> <span class="hljs-string">Pages</span>

<span class="hljs-attr">on:</span>
  <span class="hljs-attr">push:</span>
    <span class="hljs-attr">branches:</span> [<span class="hljs-string">"main"</span>]

<span class="hljs-attr">permissions:</span>
  <span class="hljs-attr">contents:</span> <span class="hljs-string">read</span>
  <span class="hljs-attr">pages:</span> <span class="hljs-string">write</span>
  <span class="hljs-attr">id-token:</span> <span class="hljs-string">write</span>

<span class="hljs-attr">concurrency:</span>
  <span class="hljs-attr">group:</span> <span class="hljs-string">"pages"</span>
  <span class="hljs-attr">cancel-in-progress:</span> <span class="hljs-literal">false</span>

<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">build:</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>
    <span class="hljs-attr">container:</span>
      <span class="hljs-attr">image:</span> <span class="hljs-string">ghcr.io/avisi-cloud/structurizr-site-generatr</span>
      <span class="hljs-attr">options:</span> <span class="hljs-string">--user</span> <span class="hljs-string">root</span>
    <span class="hljs-attr">steps:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Checkout</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v3</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Create</span> <span class="hljs-string">site</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">|
          /opt/structurizr-site-generatr/bin/structurizr-site-generatr generate-site -w diagram.dsl
</span>      <span class="hljs-bullet">-</span> <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/upload-artifact@v3</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">name:</span> <span class="hljs-string">website</span>
          <span class="hljs-attr">path:</span> <span class="hljs-string">build/site</span>
  <span class="hljs-attr">deploy:</span>
    <span class="hljs-attr">needs:</span> <span class="hljs-string">build</span>
    <span class="hljs-attr">environment:</span>
      <span class="hljs-attr">name:</span> <span class="hljs-string">github-pages</span>
      <span class="hljs-attr">url:</span> <span class="hljs-string">${{</span> <span class="hljs-string">steps.deployment.outputs.page_url</span> <span class="hljs-string">}}</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>
    <span class="hljs-attr">steps:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/download-artifact@v3</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">name:</span> <span class="hljs-string">website</span>
          <span class="hljs-attr">path:</span> <span class="hljs-string">build/site</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Setup</span> <span class="hljs-string">Pages</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/configure-pages@v3</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Upload</span> <span class="hljs-string">artifact</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/upload-pages-artifact@v1</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">path:</span> <span class="hljs-string">"build/site"</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Deploy</span> <span class="hljs-string">to</span> <span class="hljs-string">GitHub</span> <span class="hljs-string">Pages</span>
        <span class="hljs-attr">id:</span> <span class="hljs-string">deployment</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/deploy-pages@v2</span>
</code></pre>
<p>This Github Action uses Structurizr CLI action to compile our DSL file as HTML and publish it to Github Pages.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>I believe that creating and maintaining effective and clear diagrams should be effortless. Up-to-date visuals ensure everyone stays on the same page, eliminating confusion and wasted time.</p>
<p>The C4 model and a bit of automation with Structurizr DSL can help make this process faster and keep diagrams close to the codebase. The whole process can now be automated as well into your SDLC.</p>
<h3 id="heading-resources">Resources</h3>
<ul>
<li><p><a target="_blank" href="https://github.com/plutov/c4-diagram-example">Github Repository</a></p>
</li>
<li><p><a target="_blank" href="https://c4model.com/">C4 Model</a></p>
</li>
<li><p><a target="_blank" href="https://docs.structurizr.com/dsl/language">DSL Language Reference</a></p>
</li>
<li><p><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=systemticks.c4-dsl-extension">C4 DSL Visual Studio Code Extension</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/marketplace/actions/structurizr-cli-action">structurizr-cli-action</a></p>
</li>
<li><p><a target="_blank" href="https://packagemain.tech">Discover more articles from packagemain.tech</a></p>
</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
