Creating C4 Diagrams
This skill is C4-specific: model architecture using C4 abstractions and notation (not generic box-and-arrow diagrams).
Workflow: Creating a C4 diagram
Identify the audience and scope. Determine which diagram level is needed:
- Level 1 — System Context: How the system fits into the world. Always create this first.
- Level 2 — Container: Major technical building blocks and communication. Always create this second.
- Level 3 — Component: Internal structure of a single container. Create only when it adds value.
- Dynamic: Runtime behavior for a specific use case. Create for complex or non-obvious flows.
- Deployment: How containers map to infrastructure. Create for production systems.
- Skip Level 4 (Code) — auto-generate from IDE instead.
Choose the tool.
- Default: Structurizr DSL — model-first, single model with multiple views, supports all diagram types. Use for any long-lived architecture documentation.
- Alternative: Mermaid — use only for quick diagrams in Markdown files (READMEs, PRs, wikis). Limited to Context and Container levels; no dynamic or deployment diagrams.
Identify the elements. Map the system to C4 abstractions:
- Person: A human user role.
- Software System: A top-level system owned and deployed by one team.
- Container: A separately deployable/runnable unit (app, database, queue, function). NOT a Docker container.
- Component: A module/package within a container. Not separately deployable.
- Apply the test: "Does this need to be running for the system to work?" → Yes = Container. No = Component.
Define relationships. Every arrow must have:
- A specific action verb label: "Submits purchase orders to", "Reads customer records from", "Publishes OrderCreated events to"
- A technology annotation for inter-process communication:
HTTPS/JSON, gRPC, SQL/TCP, AMQP
- Unidirectional direction only — never use bidirectional arrows. Draw two separate arrows instead.
- Use the pattern:
[Action verb] + [what] + [preposition]
- Avoid weak verbs: Uses, Calls, Connects, Talks, Accesses.
Write the diagram code. Follow these rules:
- Every element gets: name, type label, technology (containers/components), one-sentence responsibility.
- Every diagram gets: title describing type and scope, key/legend, max ~20 elements.
- Tag external systems with
"External". Use tags for styling, not per-element styles.
- In Structurizr DSL: always use
!identifiers hierarchical.
- In Mermaid: use
C4Context or C4Container as diagram type.
Validate against the review checklist. Check all items in references/08-checklists.md.
Workflow: Reviewing an existing C4 diagram
Check abstraction correctness:
- Are containers actually separately deployable? (shared libraries are components, not containers)
- Are system boundaries aligned with team ownership?
- Is the message broker modeled as individual topics/queues, not a single hub?
- Are external systems shown as opaque boxes without internal details?
Check notation quality:
- Does every element have a name, type label, technology, and description?
- Are all arrows unidirectional with specific action-verb labels?
- Are communication protocols specified on inter-process arrows?
- Is there a title, legend, and ≤20 elements?
Check for common anti-patterns: vague "Uses"/"Calls" labels, bidirectional arrows, missing type metadata, color as only differentiator, 30+ elements in one diagram, invented abstraction levels. See references/03-anti-patterns.md for the full catalog.
Propose specific fixes with corrected code.
Workflow: Using C4 diagrams as context
When C4 diagrams are available in the project (.dsl files or Mermaid blocks), use them as architectural context for:
- Design decisions: Reference the container diagram to understand system boundaries and communication patterns before proposing changes.
- Code generation: Use component diagrams to understand module responsibilities and interfaces when generating implementation code.
- Risk analysis: Walk the container diagram to identify security boundaries, data flows, and single points of failure. See references/05-adr-and-risk-modeling.md.
- Onboarding explanations: Start with Level 1 (context), then zoom into Level 2 (containers) to explain system architecture.
- ADR context: Link architectural decisions to specific C4 elements. Reference ADRs in element descriptions.
Structurizr DSL quick reference
workspace "Name" "Description" {
!identifiers hierarchical
model {
user = person "User" "Description."
system = softwareSystem "System" "Description." {
webapp = container "Web App" "Description." "React"
api = container "API" "Description." "Go"
db = container "Database" "Description." "PostgreSQL" { tags "Database" }
}
ext = softwareSystem "External" "Description." { tags "External" }
user -> system.webapp "Browses via" "HTTPS"
system.webapp -> system.api "Makes API calls to" "HTTPS/JSON"
system.api -> system.db "Reads from and writes to" "SQL/TCP"
system.api -> ext "Sends requests to" "HTTPS/JSON"
}
views {
systemContext system "Context" { include *; autoLayout }
container system "Containers" { include *; autoLayout }
styles {
element "Person" { shape person }
element "Database" { shape cylinder }
element "External" { background #999999; color #ffffff }
}
}
}
Mermaid quick reference
C4Context
title System Context Diagram for My System
Person(user, "User", "Description.")
System(system, "My System", "Description.")
System_Ext(ext, "External System", "Description.")
Rel(user, system, "Browses via", "HTTPS")
Rel(system, ext, "Sends requests to", "HTTPS/JSON")
C4Container
title Container Diagram for My System
Person(user, "User", "Description.")
Container_Boundary(system, "My System") {
Container(webapp, "Web App", "React", "Serves the UI.")
Container(api, "API", "Go", "Handles business logic.")
ContainerDb(db, "Database", "PostgreSQL", "Stores data.")
}
Rel(user, webapp, "Browses via", "HTTPS")
Rel(webapp, api, "Makes API calls to", "HTTPS/JSON")
Rel(api, db, "Reads from and writes to", "SQL/TCP")
Key decisions
- Microservices owned by one team → model as containers within one software system.
- Microservices owned by separate teams → promote each to its own software system.
- Event-driven → model individual topics/queues as containers, not the broker.
- Serverless functions → model as containers (they are separately deployable).
- Component diagrams → create only for complex containers; skip for simple microservices.
Reference material
- Fundamentals and abstractions: references/01-fundamentals-and-abstractions.md
- Notation and styling: references/02-notation-and-styling.md — relationship label pattern library
- Anti-patterns: references/03-anti-patterns.md — common mistakes and fixes
- Tooling and diagram-as-code: references/04-tooling-and-diagram-as-code.md — Structurizr DSL, Mermaid, workspace modularization
- ADR and risk modeling: references/05-adr-and-risk-modeling.md — ADR integration, risk-storming, STRIDE
- Modern patterns and adoption: references/06-modern-patterns-and-adoption.md — microservices, event-driven, serverless, DDD, team playbook
- Worked example: references/07-worked-example.md — complete PageTurn bookstore from L1 through deployment
- Checklists: references/08-checklists.md — diagram review, abstraction guide, tool selection
1---2name: creating-c4-diagrams3description: Creates, reviews, and interprets C4 software architecture diagrams (System Context, Container, Component, Dynamic, Deployment). Produces Structurizr DSL or Mermaid C4 diagram code following C4 model best practices. Use when the requested output is explicitly C4, when reviewing existing C4 diagrams for correctness and anti-patterns, when generating Structurizr DSL workspaces, when producing Mermaid C4 diagrams for READMEs, or when using C4 diagrams as context for design decisions, code generation, risk analysis, or onboarding.4---56# Creating C4 Diagrams78This skill is C4-specific: model architecture using C4 abstractions and notation (not generic box-and-arrow diagrams).910## Workflow: Creating a C4 diagram11121. **Identify the audience and scope.** Determine which diagram level is needed:13 - **Level 1 — System Context**: How the system fits into the world. Always create this first.14 - **Level 2 — Container**: Major technical building blocks and communication. Always create this second.15 - **Level 3 — Component**: Internal structure of a single container. Create only when it adds value.16 - **Dynamic**: Runtime behavior for a specific use case. Create for complex or non-obvious flows.17 - **Deployment**: How containers map to infrastructure. Create for production systems.18 - Skip Level 4 (Code) — auto-generate from IDE instead.19202. **Choose the tool.**21 - **Default: Structurizr DSL** — model-first, single model with multiple views, supports all diagram types. Use for any long-lived architecture documentation.22 - **Alternative: Mermaid** — use only for quick diagrams in Markdown files (READMEs, PRs, wikis). Limited to Context and Container levels; no dynamic or deployment diagrams.23243. **Identify the elements.** Map the system to C4 abstractions:25 - **Person**: A human user role.26 - **Software System**: A top-level system owned and deployed by one team.27 - **Container**: A separately deployable/runnable unit (app, database, queue, function). NOT a Docker container.28 - **Component**: A module/package within a container. Not separately deployable.29 - Apply the test: *"Does this need to be running for the system to work?"* → Yes = Container. No = Component.30314. **Define relationships.** Every arrow must have:32 - A **specific action verb** label: *"Submits purchase orders to"*, *"Reads customer records from"*, *"Publishes OrderCreated events to"*33 - A **technology annotation** for inter-process communication: `HTTPS/JSON`, `gRPC`, `SQL/TCP`, `AMQP`34 - **Unidirectional direction only** — never use bidirectional arrows. Draw two separate arrows instead.35 - Use the pattern: `[Action verb] + [what] + [preposition]`36 - Avoid weak verbs: Uses, Calls, Connects, Talks, Accesses.37385. **Write the diagram code.** Follow these rules:39 - Every element gets: name, type label, technology (containers/components), one-sentence responsibility.40 - Every diagram gets: title describing type and scope, key/legend, max ~20 elements.41 - Tag external systems with `"External"`. Use `tags` for styling, not per-element styles.42 - In Structurizr DSL: always use `!identifiers hierarchical`.43 - In Mermaid: use `C4Context` or `C4Container` as diagram type.44456. **Validate against the review checklist.** Check all items in [references/08-checklists.md](references/08-checklists.md).4647## Workflow: Reviewing an existing C4 diagram48491. **Check abstraction correctness:**50 - Are containers actually separately deployable? (shared libraries are components, not containers)51 - Are system boundaries aligned with team ownership?52 - Is the message broker modeled as individual topics/queues, not a single hub?53 - Are external systems shown as opaque boxes without internal details?54552. **Check notation quality:**56 - Does every element have a name, type label, technology, and description?57 - Are all arrows unidirectional with specific action-verb labels?58 - Are communication protocols specified on inter-process arrows?59 - Is there a title, legend, and ≤20 elements?60613. **Check for common anti-patterns:** vague "Uses"/"Calls" labels, bidirectional arrows, missing type metadata, color as only differentiator, 30+ elements in one diagram, invented abstraction levels. See [references/03-anti-patterns.md](references/03-anti-patterns.md) for the full catalog.62634. **Propose specific fixes** with corrected code.6465## Workflow: Using C4 diagrams as context6667When C4 diagrams are available in the project (`.dsl` files or Mermaid blocks), use them as architectural context for:6869- **Design decisions**: Reference the container diagram to understand system boundaries and communication patterns before proposing changes.70- **Code generation**: Use component diagrams to understand module responsibilities and interfaces when generating implementation code.71- **Risk analysis**: Walk the container diagram to identify security boundaries, data flows, and single points of failure. See [references/05-adr-and-risk-modeling.md](references/05-adr-and-risk-modeling.md).72- **Onboarding explanations**: Start with Level 1 (context), then zoom into Level 2 (containers) to explain system architecture.73- **ADR context**: Link architectural decisions to specific C4 elements. Reference ADRs in element descriptions.7475## Structurizr DSL quick reference7677```78workspace "Name" "Description" {79 !identifiers hierarchical8081 model {82 user = person "User" "Description."83 system = softwareSystem "System" "Description." {84 webapp = container "Web App" "Description." "React"85 api = container "API" "Description." "Go"86 db = container "Database" "Description." "PostgreSQL" { tags "Database" }87 }88 ext = softwareSystem "External" "Description." { tags "External" }8990 user -> system.webapp "Browses via" "HTTPS"91 system.webapp -> system.api "Makes API calls to" "HTTPS/JSON"92 system.api -> system.db "Reads from and writes to" "SQL/TCP"93 system.api -> ext "Sends requests to" "HTTPS/JSON"94 }9596 views {97 systemContext system "Context" { include *; autoLayout }98 container system "Containers" { include *; autoLayout }99 styles {100 element "Person" { shape person }101 element "Database" { shape cylinder }102 element "External" { background #999999; color #ffffff }103 }104 }105}106```107108## Mermaid quick reference109110```mermaid111C4Context112 title System Context Diagram for My System113 Person(user, "User", "Description.")114 System(system, "My System", "Description.")115 System_Ext(ext, "External System", "Description.")116 Rel(user, system, "Browses via", "HTTPS")117 Rel(system, ext, "Sends requests to", "HTTPS/JSON")118```119120```mermaid121C4Container122 title Container Diagram for My System123 Person(user, "User", "Description.")124 Container_Boundary(system, "My System") {125 Container(webapp, "Web App", "React", "Serves the UI.")126 Container(api, "API", "Go", "Handles business logic.")127 ContainerDb(db, "Database", "PostgreSQL", "Stores data.")128 }129 Rel(user, webapp, "Browses via", "HTTPS")130 Rel(webapp, api, "Makes API calls to", "HTTPS/JSON")131 Rel(api, db, "Reads from and writes to", "SQL/TCP")132```133134## Key decisions135136- **Microservices owned by one team** → model as containers within one software system.137- **Microservices owned by separate teams** → promote each to its own software system.138- **Event-driven** → model individual topics/queues as containers, not the broker.139- **Serverless functions** → model as containers (they are separately deployable).140- **Component diagrams** → create only for complex containers; skip for simple microservices.141142## Reference material143144- **Fundamentals and abstractions**: [references/01-fundamentals-and-abstractions.md](references/01-fundamentals-and-abstractions.md)145- **Notation and styling**: [references/02-notation-and-styling.md](references/02-notation-and-styling.md) — relationship label pattern library146- **Anti-patterns**: [references/03-anti-patterns.md](references/03-anti-patterns.md) — common mistakes and fixes147- **Tooling and diagram-as-code**: [references/04-tooling-and-diagram-as-code.md](references/04-tooling-and-diagram-as-code.md) — Structurizr DSL, Mermaid, workspace modularization148- **ADR and risk modeling**: [references/05-adr-and-risk-modeling.md](references/05-adr-and-risk-modeling.md) — ADR integration, risk-storming, STRIDE149- **Modern patterns and adoption**: [references/06-modern-patterns-and-adoption.md](references/06-modern-patterns-and-adoption.md) — microservices, event-driven, serverless, DDD, team playbook150- **Worked example**: [references/07-worked-example.md](references/07-worked-example.md) — complete PageTurn bookstore from L1 through deployment151- **Checklists**: [references/08-checklists.md](references/08-checklists.md) — diagram review, abstraction guide, tool selection