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.
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).
View Mermaid sourcePlain-text diagram syntax — copy or edit directly.
1C4Context2 title System context diagram for a billing service3 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