By Arjun Mehta
Most software architecture diagrams fail in the same way. They try to show everything at once: boxes for services, arrows for calls, annotations for technologies, color coding for teams, dotted lines for async flows. The result is a diagram that looks comprehensive in a review and is unreadable in practice. Two senior engineers staring at it will disagree about what it means.
Simon Brown's C4 model solves this by acknowledging an obvious truth: different audiences need different levels of abstraction. A CTO doesn't need to see every microservice. A new engineer doesn't need to see the whole system before understanding their first service. The C4 model provides four levels of abstraction - Context, Container, Component, and Code - each designed for a specific audience and a specific question.
The Four Levels of the C4 Model
Level 1: System Context diagram. The highest abstraction level. Shows your software system as a single box surrounded by users and external systems. This is the "what is this thing and who uses it" diagram. Audience: business stakeholders, anyone new to the project. A context diagram for an e-commerce platform might show: the customer (person), the e-commerce system (your system), and the external payment processor, email service, and inventory system it connects to. Nothing about how any of these work internally. Just: what is it, who uses it, what does it depend on.
Level 2: Container diagram. Zooms into the system to show the major technical building blocks - applications, databases, microservices, message queues. Each container is a separately deployable unit. A container diagram answers "how is the system split up at a high level." Audience: technical leads, architects, anyone who needs to understand the system's overall shape. This is the level where you might show: the React frontend, the Node API, the PostgreSQL database, the Redis cache, the background job processor. Still no detail about what's inside any of these.
Level 3: Component diagram. Zooms into a single container to show its internal structure - the major logical components and how they interact. This is the level that shows how code within a service is organized. Audience: engineers working on that specific service. A component diagram for the API container might show: the authentication component, the order management component, the notification component, and the shared data access layer. This is where "how does the auth service actually work internally" gets answered.
Level 4: Code diagram. The lowest level - UML class diagrams, entity relationship diagrams, or similar code-level views. C4's original specification includes this level but Brown himself has noted that it's often not worth maintaining for most codebases. Code changes so frequently that code-level diagrams go stale almost immediately. For most teams, this level is better handled by reading the code directly.
Why C4 Works Where Other Approaches Fail
The fundamental insight of C4 is that architectural communication failures aren't about diagramming skill. They're about scope mismatch. When a developer creates an architecture diagram for a meeting with the CTO and puts in 40 microservices and 200 arrows, the diagram fails not because it's wrong but because it answers the wrong questions for the audience. When someone creates a high-level system map for a new engineer trying to understand a specific service, it fails because it's too abstract to be actionable.
C4 solves this by giving teams a shared vocabulary for choosing the right level of abstraction for a specific purpose. "Let's start with a container diagram" means something concrete. "We need a context diagram first" is a meaningful request. The model creates a common frame of reference that most ad-hoc diagramming approaches lack.
The other key advantage is that C4 diagrams are deliberately minimal. Each level shows only what's relevant at that abstraction. No color-coding for team ownership, no technology version numbers, no infrastructure details that belong in a deployment diagram rather than an architecture diagram. This constraint feels limiting at first and becomes essential when you're trying to create diagrams that remain useful over time.
How to Create a C4 Context Diagram
Start with the people and systems that interact with your software, not with your software itself. The temptation is to begin by drawing the system and then adding what it connects to. Starting with the external view produces better context diagrams.
Identify your users - the humans who interact with the system. Be specific about roles. "Users" is too vague. "Customers placing orders," "support agents resolving tickets," and "warehouse staff managing inventory" are three distinct actors who might use the same system differently.
Identify your external systems - anything your system sends data to or receives data from that your team doesn't own. Payment processors, authentication providers, external APIs, email services. Each becomes a box. The relationships between your system and these external systems become arrows, labeled with the communication protocol or the nature of the data flow.
Keep it to one page. If your context diagram has more than 8-10 external connections, you either have a legitimately complex system or you're including detail that belongs at the container level.
Container Diagrams: Where Architecture Actually Gets Communicated
The container level is where most of the practical value of C4 lives for engineering teams. Context diagrams are useful for onboarding and stakeholder communication. Code-level diagrams go stale too fast to maintain. Container diagrams occupy the sweet spot: stable enough to remain accurate for months, specific enough to actually inform engineering decisions.
A good container diagram answers: How is the system deployed? What are the major moving parts? How do they communicate? Which team owns which container?
For each container, show: the name, the technology choice (React, Node, PostgreSQL), and the responsibility in one short sentence. For the relationships, show the communication mechanism (REST, gRPC, event queue) and the direction. Bidirectional arrows are almost always a sign that the diagram needs more precision - most service-to-service communication is actually request-response in one primary direction.
Ownership mapping is valuable to add at the container level: which team is responsible for which container. In a multi-team organization, this is some of the most practically useful information in an architecture diagram. Before changing how a container behaves, knowing whose code you're modifying and who to loop in is the difference between a smooth change and an incident. See Understanding Code Dependencies for how ownership connects to dependency management.
The Tooling Question: Diagrams-as-Code vs. Drawing Tools
C4 diagrams can be created with any diagramming tool. The more important question is whether to treat them as drawings or as code.
Drawing tools (Miro, Lucidchart, draw.io): Fast to create, visually flexible, familiar to non-technical stakeholders. The problem is the same as all manual documentation: they go stale. A container diagram in Miro isn't connected to the code. When the architecture changes, the diagram only changes if someone remembers to update it.
Diagrams-as-code tools (Structurizr DSL, PlantUML with C4 library, Mermaid): The diagram is defined in code that lives in the repository alongside the source code. This doesn't automatically keep the diagram current - you still have to update the diagram code when the architecture changes - but it lowers the friction significantly and makes the diagram subject to code review and version control.
Codebase intelligence tools: A newer category that derives architecture diagrams from the actual codebase, rather than from manually authored diagram files. Tools like Glue analyze import graphs, service calls, and dependency relationships to produce container and component-level views that reflect the current state of the code. This approach trades diagramming flexibility for accuracy - the map always matches the territory because it's derived from the territory. For the structural layer of a C4 model (what exists and how it connects), derived diagrams beat manual ones on accuracy for any codebase that's actively evolving. See Software Architecture Documentation for a deeper exploration of this tradeoff.
Common C4 Mistakes
Mixing levels in one diagram. Putting a database (container level) next to a specific React component (component level) in the same diagram produces something that's technically a diagram but isn't a C4 diagram and is confusing to read. Stay at one level per diagram.
Too many boxes. A container diagram with 30 containers is probably trying to do the work of both a container diagram and component diagrams for multiple services. If the diagram has more than 15 boxes, ask whether some of the detail belongs at a different level.
Bidirectional arrows as a shortcut. When the direction of a relationship isn't clear, the instinct is to add arrows going both ways. In most cases, this is a sign that the relationship needs more thought. Specify the primary direction and the protocol. It forces more precise thinking about the architecture and produces diagrams that communicate more clearly.
Treating C4 as a one-time artifact. C4 diagrams are most useful when kept approximately current. A context diagram from two years ago is probably still mostly accurate. A container diagram from two years ago in an actively developed system is likely to be significantly wrong. Build in lightweight update practices: revisit container diagrams when new services are added, use code review as a trigger for diagram updates.
Using it for everything. C4 is an architecture communication model, not a general-purpose diagramming framework. It's not the right tool for sequence diagrams, deployment diagrams, data flow diagrams, or org charts. Use C4 for system structure and use other tools for other purposes.
FAQ
What is a C4 architecture diagram?
A C4 architecture diagram is a software architecture visualization created using the C4 model, which uses four abstraction levels: Context (the system and its external relationships), Container (major technical building blocks within the system), Component (logical components within a container), and Code (implementation-level details). Created by Simon Brown, C4 gives engineering teams a shared language for communicating architecture at the right level of detail for a given audience.
What is the difference between a C4 container and a component?
In C4, a container is a separately deployable unit - a web application, a microservice, a database, a mobile app. A component is a logical grouping within a container - a set of related classes or functions that together implement a specific responsibility. Components live inside containers; containers are the deployment boundary. A single container (like an API service) might have multiple components (authentication, order management, notification handling).
What tools can I use to create C4 diagrams?
Common options include Structurizr (purpose-built for C4, supports DSL for diagrams-as-code), PlantUML with the C4 library, Mermaid (supports C4 context and container diagrams), draw.io/Lucidchart (manual diagramming), and Miro (collaborative whiteboarding). For teams wanting diagrams derived from the actual codebase rather than manually authored, codebase intelligence tools like Glue can generate architectural views based on dependency analysis.
When should I use a C4 diagram vs. a sequence diagram?
C4 diagrams show static structure - what components exist and how they connect. Sequence diagrams show dynamic behavior - the specific sequence of interactions for a particular flow or use case. Use C4 when you want to communicate the overall architecture of a system or service. Use sequence diagrams when you want to trace how a specific request flows through the system. Most architecture documentation benefits from both: C4 for the "what exists" and sequence diagrams for the "how it works at runtime."
Related Reading
- What Is Technical Debt Tracking?
- What Is Technical Debt Prioritization?
- Technical Debt Patterns: The 7 Types Costing You the Most
- The CTO's Guide to Product Visibility
- What Is Code Intelligence?