Diagram type

Mermaid C4 Diagram Syntax & Examples

Reference for Mermaid C4 diagram syntax — C4Context / C4Container / C4Component, Person, System, Boundary, and Rel declarations. Copy-paste architecture examples.

Use this page to connect a high-intent search query to the right problem-solution narrative.

At a glance

A syntax reference for Mermaid's C4 diagram grammar — read this when you need the exact way to declare a person, system, container, or relationship at the four C4 levels (context / container / component / code).

What is the C4 modelThe four C4 diagram keywordsElement declarations — Person, System, Container, ComponentRelationships — Rel and labelled connectionsBoundaries — group containers and componentsCommon patterns & gotchas
Rendered proof
C4 system context diagram.
Theme · Blueprint
Open this diagram in editor
This example could not be rendered in the proof block. The source is still available below.
View Mermaid sourcePlain-text diagram syntax — copy or edit directly.
diagram.mmd
1C4Context
2 title System context diagram for a billing service
3 Person(customer, "Customer", "A paying customer")
4 System(billing, "Billing service", "Handles subscriptions, invoices, and payments")
5 System_Ext(stripe, "Stripe", "Payment processor")
6 System_Ext(email, "Email service", "Sends invoices and receipts")
7 Rel(customer, billing, "Manages subscription")
8 Rel(billing, stripe, "Charges cards", "HTTPS / API")
9 Rel(billing, email, "Sends invoices", "HTTPS / API")

What is the C4 model

C4 is an architecture documentation model developed by Simon Brown that describes a software system at four levels of zoom: Context (the system and its external users / systems), Container (the deployable / runnable pieces — services, databases, queues), Component (the major code modules inside a container), and Code (the class-level detail, rarely diagrammed). Mermaid supports the first three cleanly with the `C4Context`, `C4Container`, and `C4Component` diagram keywords. The fourth level (Code) is typically expressed with class diagrams instead. Each C4 level is its own diagram; mixing levels in one chart breaks the cognitive model.

The four C4 diagram keywords

Each diagram starts with one of the C4 type keywords. `C4Context` is the outermost zoom — the system shown as a single box with external users and external systems around it. `C4Container` zooms in: the system is decomposed into its containers (services, databases, single-page apps). `C4Component` zooms in further: a single container's internal components are shown. `C4Dynamic` is a Mermaid-specific variant for showing dynamic behaviour at any C4 level. Pick the level by audience: Context for non-technical readers, Container for engineering planning, Component for deep dives.

  • `C4Context` — system + external actors (for outside audiences)
  • `C4Container` — decompose the system into deployable pieces
  • `C4Component` — decompose a single container
  • `C4Dynamic` — show runtime behaviour at any level

Element declarations — Person, System, Container, Component

Each level uses different element declarations. `Person(id, "Label", "Description")` declares a human actor. `System(id, "Label", "Description")` declares an internal system (your system). `System_Ext(id, "Label", "Description")` declares an external system you depend on (Stripe, an email service, a third-party API). `Container(id, "Label", "Tech", "Description")` declares a deployable piece — note the extra `Tech` parameter (e.g. "Node.js", "PostgreSQL"). `Component(id, "Label", "Tech", "Description")` works the same way inside a container. Suffix `_Ext` variants exist for every type to mark external elements with a distinct visual style.

  • `Person(id, "Label", "Description")` — human / actor (Person_Ext for external)
  • `System(id, "Label", "Description")` — internal system (System_Ext for external)
  • `Container(id, "Label", "Tech", "Description")` — deployable piece (Container_Ext for external)
  • `Component(id, "Label", "Tech", "Description")` — module inside a container

Relationships — Rel and labelled connections

Relationships use `Rel(from_id, to_id, "Label")` for the default arrow. `Rel(from, to, "Label", "Tech")` adds a technology / protocol annotation on the connection (e.g. "HTTPS / API", "AMQP", "JDBC"). Directional variants control the visual direction: `Rel_U` (up), `Rel_D` (down), `Rel_L` (left), `Rel_R` (right) — useful when the auto-layout doesn't match the intended reading direction. `BiRel` declares a bidirectional relationship without two separate arrows. Labelling relationships well is the highest-leverage part of a C4 diagram — readers learn the integration model from the labels, not from the box layout.

Boundaries — group containers and components

Boundaries group related elements visually. `System_Boundary(id, "Label")` and `Container_Boundary(id, "Label")` create a labelled enclosure that other elements are declared inside. Use `Enterprise_Boundary(id, "Label")` to wrap multiple systems that belong to the same organisation. Boundaries are particularly useful at the Container level to show service boundaries: which containers are deployed together, which cross an organisational boundary, which belong to the same product area. Like with subgraphs in flowcharts, prefer one or two levels of boundary nesting — deeper nesting becomes hard to read.

Common patterns & gotchas

Two patterns dominate real C4 diagrams. Context diagrams almost always have the shape: one System box in the centre, two-to-four Person boxes around it, and a few System_Ext boxes for third-party dependencies. Container diagrams typically show 3-8 Container boxes inside the system, with external Persons and Systems still on the periphery. The most common gotcha: mixing levels in one chart — putting both System and Container declarations in the same diagram breaks C4's discipline and produces an unclear hybrid. Second gotcha: forgetting the `"Tech"` parameter on Container / Component (the third positional argument) — the diagram still renders but the technology annotations that make C4 diagrams useful are missing.

  • Keep one C4 level per diagram — don't mix System with Container in the same chart
  • Always supply the `Tech` parameter on Container / Component for the integration annotations
  • Use `_Ext` variants for external (third-party) elements — visual distinction matters
FAQ

Mermaid C4 Diagram Syntax & Examples — frequently asked questions

What's the difference between C4Context, C4Container, and C4Component in Mermaid?

Each is a different zoom level on the same system. `C4Context` is the outermost view — your system shown as a single box with external users and external systems around it. `C4Container` zooms inside: the system is broken into its deployable pieces (services, databases, single-page apps). `C4Component` zooms further into one container, showing its internal modules. Pick the level by audience: Context for non-technical stakeholders, Container for engineering planning, Component for deep architectural reviews. Mermaid also supports `C4Dynamic` for showing runtime behaviour at any level.

When should I use System_Ext vs System?

Use `System(id, "Label", "Description")` for systems you own and operate — the systems that are inside your team's scope. Use `System_Ext(id, "Label", "Description")` for third-party systems you depend on but don't control: Stripe, Auth0, an email provider, an external API. The `_Ext` suffix exists for `Person_Ext` (external user / customer outside your organisation) and `Container_Ext` (external container) too. The visual distinction is important — it tells readers what is in-scope for changes vs what is a fixed external dependency.

How do I label the technology on a C4 container?

The Container and Component declarations take a third positional argument for technology: `Container(api, "API Service", "Node.js / Hono", "Public REST API")`. This appears as a small annotation under the main label in the rendered diagram. The same pattern applies on relationships: `Rel(api, db, "Stores users", "PostgreSQL / JDBC")` adds the protocol or technology annotation to the connection. These technology labels are what make C4 diagrams useful for engineering planning — without them the diagram is just boxes.

Can I group containers visually inside a C4 diagram?

Yes — use boundaries. `System_Boundary(id, "Label")` wraps containers that belong to the same system. `Container_Boundary(id, "Label")` is for components inside a container. `Enterprise_Boundary(id, "Label")` is the outermost — wraps multiple systems that belong to the same organisation. Boundaries are declared as parent elements that contain child declarations inside them, like a subgraph in a flowchart. Don't nest boundaries deeper than two levels — the visual hierarchy becomes hard to follow.

Should I mix multiple C4 levels in one diagram?

No. The whole point of C4 is that each level has a different audience and a different level of abstraction — mixing them in one diagram produces an unclear hybrid that doesn't serve either audience well. Make a separate diagram per level: the Context diagram for the executive summary, the Container diagram for the planning doc, the Component diagram for the deep-dive design review. Link the levels in the surrounding documentation rather than stacking them together visually.