PlantUML C4 Diagrams: Context, Container, and Component
PlantUML C4 diagrams combine PlantUML rendering with the C4 model's architectural vocabulary. With the C4-PlantUML library, you can describe people, software systems, containers, and components using macros such as Person, System, Container, Component, and Rel.
This tutorial follows one online shop from system context to container and component views. For other diagram families, start with the PlantUML examples guide.
Key Takeaways
- C4 uses multiple zoom levels; context, container, and component views answer different questions.
- C4-PlantUML is a PlantUML library of macros and helpers, not a separate renderer.
- Use
!include <C4/C4_Context>and related standard-library includes for a concise setup.- Remote includes from a moving branch are convenient but can make builds non-reproducible.
- A rendered C4 diagram communicates architecture; it does not verify runtime topology, security, or code alignment.
What Are the C4 Levels?
C4 stands for Context, Container, Component, and Code. The first three levels are the focus of the official C4-PlantUML repository, retrieved July 24, 2026.
- System context shows people, the system under consideration, and external systems.
- Container shows deployable or runnable applications and data stores inside a system.
- Component shows significant responsibilities inside one container.
- Code zooms into implementation details and is often covered by ordinary UML class diagrams or generated documentation.
Do not place every level on one canvas. Each view should have an explicit audience and question.
Prerequisites and Include Options
You need PlantUML plus C4-PlantUML definitions. PlantUML's published standard library supports includes such as:
!include <C4/C4_Context>
For container or component views, use:
!include <C4/C4_Container>
!include <C4/C4_Component>
The component definitions build on the container macros. The project's PlantUML standard library documentation explains the standard-library mechanism.
Remote URLs are another PlantUML include mechanism, but they depend on network access from OnUML's configured rendering service and can fail or change independently of your diagram. For the OnUML workflow, start with the standard-library <C4/...> include and verify the preview before saving or exporting.
Step 1: Draw the System Context
The context view defines the system boundary and its relationships without exposing internal applications.
@startuml
!include <C4/C4_Context>
title Online Shop - System Context
Person(customer, "Customer", "Browses products and places orders")
System(shop, "Online Shop", "Sells products through the web")
System_Ext(payment, "Payment Provider", "Authorizes card payments")
System_Ext(email, "Email Service", "Sends order confirmations")
Rel(customer, shop, "Browses and buys", "HTTPS")
Rel(shop, payment, "Requests authorization", "HTTPS/JSON")
Rel(shop, email, "Sends messages", "HTTPS/JSON")
SHOW_LEGEND()
@enduml
Use System_Ext for a system outside the ownership boundary of the system under consideration. “External” describes the architectural boundary in this view, not necessarily a different company or network.
Step 2: Zoom into Containers
In C4 terminology, a container is an application or data store—not necessarily a Docker container. Use System_Boundary to group the online shop's internal containers.
@startuml
!include <C4/C4_Container>
title Online Shop - Container View
Person(customer, "Customer", "Places orders")
System_Ext(payment, "Payment Provider", "Authorizes payments")
System_Ext(email, "Email Service", "Sends confirmations")
System_Boundary(shop, "Online Shop") {
Container(web, "Web Application", "Next.js", "Serves the customer experience")
Container(api, "Commerce API", "Java", "Handles catalog and ordering")
Container(worker, "Order Worker", "Java", "Processes background order tasks")
ContainerDb(db, "Commerce Database", "PostgreSQL", "Stores customers, products, and orders")
ContainerQueue(queue, "Order Events", "Message broker", "Carries order events")
}
Rel(customer, web, "Uses", "HTTPS")
Rel(web, api, "Calls", "HTTPS/JSON")
Rel(api, db, "Reads and writes", "SQL")
Rel(api, payment, "Authorizes payments", "HTTPS/JSON")
Rel(api, queue, "Publishes events")
Rel(worker, queue, "Consumes events")
Rel(worker, email, "Sends confirmations", "HTTPS/JSON")
SHOW_LEGEND()
@enduml
Technology labels should help a decision. If they make the view stale without helping the audience, omit them or make them more general.
Step 3: Zoom into Components
Choose one container and show its major internal responsibilities. The following view expands the Commerce API.
@startuml
!include <C4/C4_Component>
title Commerce API - Component View
Container_Boundary(api, "Commerce API") {
Component(orderController, "Order Controller", "HTTP adapter", "Accepts order requests")
Component(orderService, "Order Service", "Application service", "Coordinates order placement")
Component(pricing, "Pricing Component", "Domain component", "Calculates totals")
Component(orderRepository, "Order Repository", "Persistence adapter", "Stores and loads orders")
Component(eventPublisher, "Event Publisher", "Messaging adapter", "Publishes order events")
}
ContainerDb_Ext(db, "Commerce Database", "PostgreSQL", "Stores commerce data")
ContainerQueue_Ext(queue, "Order Events", "Message broker", "Carries order events")
System_Ext(payment, "Payment Provider", "Authorizes payments")
Rel(orderController, orderService, "Calls")
Rel(orderService, pricing, "Calculates price with")
Rel(orderService, payment, "Requests authorization", "HTTPS/JSON")
Rel(orderService, orderRepository, "Persists through")
Rel(orderRepository, db, "Reads and writes", "SQL")
Rel(orderService, eventPublisher, "Publishes through")
Rel(eventPublisher, queue, "Sends events to")
SHOW_LEGEND()
@enduml
Component names should describe responsibility rather than mirror every source directory. If reviewers need member-level detail inside Order Service, switch to a PlantUML class diagram.
Step 4: Keep Relationships and Layout Consistent
Rel(from, to, label, technology) provides a consistent relationship pattern. Use a short action label—“Calls,” “Publishes,” or “Reads and writes”—and reserve the optional technology argument for information that matters.
C4-PlantUML also supplies layout helpers and directional relationship macros. The repository's layout options reference documents current options. Treat layout as a readability aid, not architecture: moving a box does not change ownership or dependency.
When a layout becomes difficult:
- Remove elements that do not answer the view's question.
- Shorten descriptions and relationship labels.
- Split unrelated audiences into separate diagrams.
- Add directional helpers only after simplifying the content.
- Test output with the exact PlantUML and C4-PlantUML versions used in publishing.
How C4 Connects to Sequence, Class, and ER Diagrams
C4 diagrams establish boundaries and responsibilities. Other diagrams can provide targeted detail:
- Use the PlantUML sequence diagram guide to show a request crossing the Web Application, Commerce API, and Payment Provider.
- Use the PlantUML class diagram guide to show types inside the Order Service.
- Use the PlantUML ER diagram guide to show the structure stored in the Commerce Database.
Linking these views is more maintainable than forcing runtime behavior, domain types, storage fields, and deployment boundaries into one diagram.
Reproducible Include Strategies
| Strategy | Advantage | Tradeoff |
|---|---|---|
!include <C4/...> | Uses the PlantUML standard library available to OnUML | The bundled library may differ from the latest repository |
| Inline definitions | Keeps every required definition in the diagram source | Makes the source longer and harder to update |
| Remote commit URL | Identifies a specific library revision | Depends on remote access from the web renderer |
| Moving branch URL | Quickly accesses current repository content | Output can change without an edit to your diagram |
For OnUML, start with the standard-library <C4/...> include and verify the rendered preview. Export a reference SVG when visual stability matters.
Common C4-PlantUML Mistakes
| Problem | Result | Better approach |
|---|---|---|
| “Container” is read as “Docker container” | Important applications are omitted | Use the C4 definition: an application or data store |
| All C4 levels appear together | The diagram has no clear audience | Create one view per zoom level |
| A moving remote include is used | Rendering may change or fail unexpectedly | Prefer the standard library or a fixed source |
| Technology dominates every label | Architecture becomes an inventory | Include technology only when decision-relevant |
| Directional layout is over-constrained | Source becomes brittle | Simplify elements before adding layout hints |
| Diagram is assumed to match production | Documentation drifts silently | Review or generate architecture evidence regularly |
Frequently Asked Questions
Is C4-PlantUML part of PlantUML?
C4-PlantUML is maintained under the plantuml-stdlib organization and can be consumed through PlantUML's standard library. It provides macros and helpers that PlantUML renders.
Which include should I use?
Use C4_Context for context views, C4_Container for container views, and C4_Component for component views. Select the narrowest file that supports the view.
Should I use a remote include?
Remote includes depend on access from the web renderer and can fail independently of your diagram. In OnUML, prefer the standard-library <C4/...> include when it covers the macros you need, and verify the preview before saving or exporting.
Where can I compare Mermaid and C4-PlantUML?
Use the existing Mermaid vs PlantUML C4 diagram comparison when selecting a tool rather than learning C4-PlantUML.
Next Steps
Create a context view first and review its system boundary with both technical and nontechnical stakeholders. Then add a container view only for the system you own, and create component views for containers where an internal design decision needs discussion.
Return to the PlantUML examples hub, connect behavior with the sequence diagram tutorial, and keep the C4-PlantUML repository and sample directory nearby as the authoritative macro references.