Structurizr vs Mermaid vs PlantUML for C4 (and When to Generate Instead)

Raghav ChamadiyaUpdated 9 min read
Compared in this post: repowise and
  • Structurizr
  • Mermaid
  • PlantUML
On this page

Pick Structurizr when you want one C4 model that feeds many views and you can run its tooling. Mermaid suits a diagram that must render inside GitHub Markdown with no build step, if you accept that its C4 support is experimental. C4-PlantUML fits when you want strict C4 shapes as text and your docs pipeline can run a PlantUML renderer.

Structurizr DSLMermaid C4C4-PlantUML
C4 supportBuilt for C4 by the person who created C4Context, container, component, dynamic and deployment diagrams, marked experimentalContext, container, component, dynamic, deployment and C4-styled sequence diagrams
What you writeA model, then views of itOne diagramOne diagram
Renders natively inStructurizr's own tools (playground, local, server)GitHub and many Markdown toolsGitLab.com, plus anything that runs PlantUML
Layoutautolayout, or drag and save in the UIStatement order plus UpdateLayoutConfig, no direction hintsGraphviz, plus Lay_R, Lay_D and friends
Can export toMermaid, PlantUML, DOT, static HTMLSVG or PNG via the Mermaid CLISVG, PNG and the other PlantUML outputs
LicenseApache-2.0 (prebuilt server binaries need a license)MITMIT (library), PlantUML itself is open source
Lines for our sample diagram301316
A second view of the same systemAbout 4 more linesA new diagram restating the elementsA new diagram restating the elements

Scroll the table sideways to see every column.

C4 is a model for drawing software architecture at four zoom levels: system context, containers, components and code. The line counts are for the sample below, which we rendered on 6 October 2026. The rest of the table comes from each project's own docs (Structurizr, Mermaid C4, C4-PlantUML), read again on 12 October 2026.

One diagram, three ways

The same container diagram is written below in all three syntaxes. It is a small online shop: a customer, a web app, an API, a database and an external payment provider. Each version has the same elements, labels and four relationships. All three rendered without errors on Kroki, a service that renders diagrams from text, on 6 October 2026, so you can paste them as they are.

Structurizr DSL

text
workspace "Shop" {
    model {
        customer = person "Customer" "Buys things online"
        payments = softwareSystem "Payment provider" "Takes card payments" {
            tags "External"
        }
        shop = softwareSystem "Shop" {
            web = container "Web app" "Product pages and checkout" "React"
            api = container "API" "Orders and stock" "Python, FastAPI"
            db = container "Database" "Orders, products, users" "PostgreSQL" {
                tags "Database"
            }
        }
        customer -> web "Browses and buys" "HTTPS"
        web -> api "Calls" "JSON/HTTPS"
        api -> db "Reads and writes" "SQL"
        api -> payments "Charges cards" "HTTPS"
    }
    views {
        container shop "Containers" {
            include *
            autolayout lr
        }
        styles {
            element "Database" {
                shape cylinder
            }
        }
    }
}

Mermaid C4

text
C4Container
    title Containers for Shop
    Person(customer, "Customer", "Buys things online")
    System_Ext(payments, "Payment provider", "Takes card payments")
    System_Boundary(shop, "Shop") {
        Container(web, "Web app", "React", "Product pages and checkout")
        Container(api, "API", "Python, FastAPI", "Orders and stock")
        ContainerDb(db, "Database", "PostgreSQL", "Orders, products, users")
    }
    Rel(customer, web, "Browses and buys", "HTTPS")
    Rel(web, api, "Calls", "JSON/HTTPS")
    Rel(api, db, "Reads and writes", "SQL")
    Rel(api, payments, "Charges cards", "HTTPS")

C4-PlantUML

text
@startuml
!include <C4/C4_Container>
title Containers for Shop
Person(customer, "Customer", "Buys things online")
System_Ext(payments, "Payment provider", "Takes card payments")
System_Boundary(shop, "Shop") {
    Container(web, "Web app", "React", "Product pages and checkout")
    Container(api, "API", "Python, FastAPI", "Orders and stock")
    ContainerDb(db, "Database", "PostgreSQL", "Orders, products, users")
}
Rel(customer, web, "Browses and buys", "HTTPS")
Rel(web, api, "Calls", "JSON/HTTPS")
Rel(api, db, "Reads and writes", "SQL")
Rel(api, payments, "Charges cards", "HTTPS")
SHOW_LEGEND()
@enduml

The Mermaid and PlantUML versions are nearly the same text, because Mermaid's C4 syntax follows C4-PlantUML's macro names. Moving between them mostly means changing the wrapper lines.

The Structurizr version is twice as long because it keeps the model apart from the views, which is the point of the tool: the model block says what exists, and the views block says what to draw. Adding a system context view costs four lines, because the elements and relationships are already defined. In Mermaid or PlantUML, a second diagram means writing the elements again in a second file, and from then on there are two copies to keep in step.

Structurizr vs Mermaid: model vs picture

Mermaid is diagrams as code, where each diagram is a standalone picture described in text. Its big strength is where it renders: GitHub draws Mermaid code blocks natively in Markdown, so a diagram in a README or a pull request shows up as a picture with no build step.

The catch is on Mermaid's own C4 page, which says the C4 diagram is experimental and that syntax and properties can change in future releases. Layout is controlled by the order you write statements in, plus UpdateLayoutConfig for how many shapes sit in a row. The page says there are no plans to support direction statements such as Lay_U or Lay_D. For a context or container diagram with a handful of boxes, that is fine. For anything bigger, you will spend time reordering lines to stop arrows crossing.

Structurizr is models as code. You describe the software system once and draw several views from it: context, containers, components, deployment. Rename a container in the model and every view picks up the change. Structurizr can also export its views to Mermaid and PlantUML, so the two can work together: you can keep the model in Structurizr and publish Mermaid where GitHub needs to render it.

Structurizr vs PlantUML

C4-PlantUML is a macro library for PlantUML, MIT licensed, and it ships inside PlantUML's standard library, so !include <C4/C4_Container> works without fetching anything from the internet. It covers more of C4 than Mermaid does, it has a legend macro, and it lays out with Graphviz plus explicit hints like Lay_R() when Graphviz picks something odd.

The cost is rendering: GitHub does not draw PlantUML blocks, so you need a renderer in CI, a PlantUML server, or a docs site plugin. GitLab.com does render PlantUML in Markdown for everyone with no setup, and self-managed GitLab can once an administrator connects a PlantUML server.

Against Structurizr, the trade is the same as with Mermaid: PlantUML gives you a picture per file, and Structurizr gives you a model with views. With one or two diagrams the model is overhead, but with ten views of the same system the model is what stops them disagreeing.

Structurizr product changes in 2026

If you last looked at Structurizr a couple of years ago, the product names have moved. Structurizr's documentation now lists the cloud service, Structurizr Lite, the old on-premises installation and the old Structurizr CLI under "End of life". Lite is replaced by the local command, the on-premises install by server, and the CLI by separate commands such as pull, push and export. The cloud service has no replacement.

According to structurizr.com, the current tools are a browser playground, local for viewing and laying out diagrams on your machine, server in an open-core build and a licensed prebuilt build, export to PlantUML, Mermaid or a static HTML site, and a free, open source MCP server (a tool server AI agents can call) for parsing and validating workspaces. The main repository is Apache-2.0. Check the date on any tutorial that still says structurizr/lite.

How each one keeps up with the code

This section describes the mechanism rather than a measured rate.

All three are hand-written, and a hand-written diagram is correct on the day someone edits it and wrong from the first day the code changes and nobody updates the diagram. The tool can't change that, but it does change how many places go wrong at once.

  • Mermaid and C4-PlantUML drift per diagram, so five diagrams of one system are five copies of the same facts, and each one goes stale on its own schedule.
  • Structurizr drifts per model. Fixing the model fixes every view, which is a real improvement, but a person still types the model, so it is only as current as the last time someone remembered.
  • Diagrams kept in the same pull request as the code stay fresher than diagrams in a wiki, whichever syntax you pick, because reviewers see them change, or see that they did not.

From freshest to stalest, the ranking is a Structurizr model kept next to the code, then Mermaid or PlantUML kept next to the code, then anything in a wiki. None of them can tell you on their own when they have fallen behind.

When to generate the C4 model from code instead

Hand-written C4 is the right call for the parts of architecture that are not in the code: intent, the target state, which team owns what, a system you have not built yet. A drawing of what you plan is supposed to differ from what exists.

The container and component levels work differently, because they describe what exists, and what exists is already written down in the import graph and the package manifests. Typing it out by hand is copying data from one place to another, and copies drift.

This is where repowise fits. It derives the system context, container and component levels from the dependency graph and package manifests, with no LLM (large language model) in the layout, and writes the result as Structurizr DSL. It needs no API key and works after repowise init --index-only.

bash
# a complete workspace you can open right away
repowise export --format structurizr --standalone --output arch/

# or a model fragment to !include from your own workspace.dsl
repowise export --format structurizr

The fragment holds the model block only, never your views or styles, so you !include it inside your own workspace block and re-export whenever you like without touching what you wrote. Containers carry Hotspot and Dead tags and repowise.owner and repowise.minBusFactor properties, so a view can show which boxes are churning or unowned, which C4 has no vocabulary for. Add --components for one component per directory. Details are in the Structurizr export docs.

On langchain-ai/langchain, the export on 6 October 2026 held 21 containers (one per package under libs/), 25 third-party systems such as Pydantic, httpx and LangSmith, and 115 relationships. You can download it from langchain's knowledge graph page and open it in Structurizr yourself.

repowise architecture graph of the repowise repository, showing modules such as server, cli, ingestion and ui as clusters joined by weighted import edges
repowise architecture graph of the repowise repository, showing modules such as server, cli, ingestion and ui as clusters joined by weighted import edges

A generated container is a package or a top-level directory, and its description is facts such as file counts and versions. The export writes one way and never reads hand edits back. The split that works: generate the model of what exists, and hand-write the views, intent and future state on top of it.

For more tools in this space, see the best architecture documentation tools, IcePanel alternatives, including open source, and how to generate C4 diagrams from code automatically.

How we measured

On 6 October 2026 we wrote the shop container diagram in all three syntaxes and rendered each one through Kroki (structurizr, mermaid and c4plantuml endpoints). All three returned a rendered SVG with every element present. Line counts are wc -l on those files. Feature and status claims come from each project's own documentation, read the same day. The langchain numbers come from repowise's public Structurizr export for its latest snapshot of langchain-ai/langchain, completed 6 October 2026. The test does not tell you how any team's diagrams drift over months, which we did not measure.

FAQ

Is Mermaid good enough for C4 diagrams?
For small context and container diagrams, usually yes, and native rendering on GitHub is a real advantage. Mermaid's own documentation marks the C4 diagram as experimental, says the syntax can change, and has no direction hints for layout, so larger diagrams take manual reordering. If you need many views of one system, a model-based tool will save you more time than it costs.
What is the difference between Structurizr and PlantUML?
PlantUML, with the C4-PlantUML library, draws one diagram per file from text. Structurizr keeps a model of your software system and draws many views from it, so one edit updates every view. Structurizr can export its views to PlantUML, so many teams use both: Structurizr for the model, PlantUML for the published picture.
Is Structurizr Lite still available?
Structurizr's documentation lists Lite as end of life, replaced by the local command. The cloud service, the old on-premises installation and the old CLI are listed as end of life too. The playground, local, server and export are the current tools.
Is there a free Structurizr alternative?
All three tools in this post are free to use. Mermaid and C4-PlantUML are MIT licensed. Structurizr's own repository is Apache-2.0 and its commands are free, except prebuilt server binaries, which need a license. LikeC4 is another open source, model-based option with its own DSL, covered in IcePanel alternatives.
Can I convert Structurizr DSL to Mermaid or PlantUML?
Yes, Structurizr's export command writes the views in a workspace out as PlantUML, Mermaid or a static HTML site. Going the other way, from a Mermaid or PlantUML diagram into a Structurizr model, has no official converter.
Can I generate C4 diagrams from code?
Yes, for the parts that exist in code: containers from packages, components from directories, relationships from imports. Several tools do this, and repowise exports the result as Structurizr DSL. The intent, the future state and anything outside the repository still need a person.