C4 Model — Communicating Architecture at the Right Level
Use the C4 model to communicate software architecture: System Context, Container, Component, and Code diagrams — when to use each level, how to draw them, and which tools work best for .NET teams.
Why the C4 Model
The problem with most architecture diagrams:
→ Too abstract for developers ("boxes and arrows, what does this mean?")
→ Too detailed for stakeholders ("I see 47 boxes and 83 arrows, I'm lost")
→ Inconsistent notation — every diagram uses different symbols
→ Nobody can tell if an arrow means HTTP, events, SQL, or "it talks to it somehow"
C4 solves this with four zoom levels, each for a different audience:
Level 1 — System Context: for business stakeholders ("what does this system do and who uses it?")
Level 2 — Container: for architects and tech leads ("what are the deployable units?")
Level 3 — Component: for developers ("what modules/services are inside a container?")
Level 4 — Code: for individual developers ("what classes/types implement this?")
You rarely need Level 4 — the code already shows Level 4.
Most teams need Levels 1-3.Level 1 — System Context
Audience: business stakeholders, product owners, non-technical managers
Question it answers: "What is this system and who uses it?"
What to show:
→ The system (one box)
→ External users (personas)
→ External systems it integrates with
→ The relationship/protocol between them
What NOT to show:
→ Internal structure of the system
→ Technologies
→ Database tables
Example: Clinical Prescription Platform
[Ward Nurse] ──uses──> [Clinical Platform] ──reads patient data──> [NHS Patient Registry (FHIR R4)]
──sends alerts──> [Email/SMS Gateway]
──reports──> [MHRA Audit System]
[Clinical Pharmacist] ──uses──> [Clinical Platform]
[Hospital Admin] ──uses──> [Clinical Platform]
This tells a non-technical director: "the platform serves nurses and pharmacists,
pulls patient data from NHS, and reports to MHRA." That's all they need.Level 2 — Container Diagram
Audience: technical architects, tech leads, DevOps
Question: "What deployable things exist and how do they communicate?"
A "container" in C4 = any independently deployable/runnable unit:
→ Web application, API, mobile app, database, message queue, cache
Example: Clinical Platform containers
[SPA React App] ──HTTPS──> [ASP.NET Core API (modular monolith)]
| | |
[SQL Server] [Redis] [Azure Service Bus]
|
[Azure Blob Storage (documents)]
The API container communicates with:
→ SQL Server: EF Core / Dapper over TCP
→ Redis: IDistributedCache over TCP
→ Azure Service Bus: integration events
→ Azure Blob Storage: patient document uploads
Label every arrow with: protocol, direction, and what flows.
"Sends prescription events (AMQP)" is better than just an arrow.Level 3 — Component Diagram
Audience: developers working inside a specific container
Question: "What are the major structural parts inside this container?"
For the Clinical Platform API (modular monolith):
[ASP.NET Core API]
├── Patients Module
│ ├── PatientsController
│ ├── PatientsDbContext
│ └── IPatientQueryService (impl: PatientQueryService)
├── Prescriptions Module
│ ├── PrescriptionsController
│ ├── PrescriptionsDbContext
│ └── IPrescriptionRepository (impl: PrescriptionRepository)
├── LabResults Module
│ └── ...
└── SharedKernel
├── Result
├── IModuleEventBus
└── Entity
Each module shows its public surface (controller, public service interface)
and its major internal components. You don't list every class — just the
components another developer needs to understand to navigate the system. Drawing C4 Diagrams in Code
// Option 1: Structurizr DSL (text-based, version-controlled)
// https://structurizr.com/dsl
workspace "Clinical Platform" {
model {
nurse = person "Ward Nurse"
pharmacist = person "Clinical Pharmacist"
platform = softwareSystem "Clinical Platform" {
spa = container "React SPA" "Web UI" "React + TypeScript"
api = container "ASP.NET Core API" "Modular monolith" "C# .NET 8" {
patientsModule = component "Patients Module"
prescriptionsModule = component "Prescriptions Module"
labModule = component "LabResults Module"
}
db = container "SQL Server" "" "SQL Server 2022"
cache = container "Redis" "" "Redis 7"
}
fhir = softwareSystem "NHS FHIR Registry" "External"
mhra = softwareSystem "MHRA Audit System" "External"
nurse -> spa "Uses" "HTTPS"
pharmacist -> spa "Uses" "HTTPS"
spa -> api "Calls" "HTTPS/JSON"
api -> db "Reads/writes" "SQL over TCP"
api -> cache "Caches" "Redis protocol"
api -> fhir "Fetches patient data" "FHIR R4 REST"
api -> mhra "Submits audit events" "HTTPS"
}
views {
systemContext platform "SystemContext" { include * }
container platform "Containers" { include * }
component api "Components" { include * }
}
}// Option 2: Mermaid (inline in Markdown/GitHub)
graph TD
Nurse["Ward Nurse"]
Pharmacist["Clinical Pharmacist"]
SPA["React SPA"]
API["ASP.NET Core API"]
DB["SQL Server"]
FHIR["NHS FHIR Registry"]
Nurse --> SPA
Pharmacist --> SPA
SPA -->|HTTPS/JSON| API
API -->|SQL| DB
API -->|FHIR R4 REST| FHIRCommon C4 Mistakes
Mistake 1: Drawing C4 once and never updating it
Fix: Treat diagrams as living documentation. Update on major structural changes.
A stale diagram is worse than no diagram — it misleads.
Mistake 2: Too much detail at Level 1
Fix: Level 1 shows relationships, not technology. No SQL Server boxes at Level 1.
Mistake 3: Arrows with no labels
Fix: Every arrow must say what flows and which protocol.
"Uses" is not a protocol. "HTTPS/JSON REST" is.
Mistake 4: Drawing the ideal architecture, not the actual one
Fix: C4 is descriptive, not aspirational. Draw what exists.
Use a separate "target architecture" diagram if you need to show the future state.
Mistake 5: Making Level 3 a class diagram
Fix: Components are groups of related classes — not individual classes.
If you're showing 50 boxes, you're drawing Level 4 code, not Level 3 components.Production issue I've seen: A team handed me a "system architecture diagram" before a review. It was a Level 2 container diagram with 63 boxes, 118 arrows, and 4 different arrow styles with no legend. Nobody in the review could read it. When I asked the architect what the different arrow colors meant, the answer was: "I think blue is HTTPS and red is database, but I drew this in 2019 and I'm not sure anymore." We replaced it with three C4 diagrams (Levels 1, 2, 3) maintained in Structurizr DSL, version-controlled in the repo. New engineers could read Level 1 in 2 minutes and orient themselves in Level 3 within 20 minutes.
Key Takeaway
C4 provides four zoom levels: Context (business stakeholders), Container (deployable units), Component (internal structure), Code (classes). Use Level 1 for boardroom conversations, Levels 2-3 for engineering. Label every arrow with protocol and direction — unlabeled arrows are useless. Maintain diagrams as code (Structurizr DSL or Mermaid) in the repository alongside the system they describe. A stale diagram is worse than no diagram — keep them accurate or remove them.
Developer Documentation Knowledge Check
5 questions · Test what you just learned · Instant explanations
Found this helpful?
Leave a comment
Have a question, correction, or just found this helpful? Leave a note below.