October 6, 2025
Practical guide to C4 architecture documentation: decision criteria for Context/Container/Component levels, domain-driven design integration, team size considerations, and working Mermaid examples. Includes common mistakes and implementation checklist.
architecture software design documentation c4 model domain driven design technical communicationWord Count: 7211
Introduction
The C4 model, created by Simon Brown between 2006 and 2011, provides a hierarchical approach for software architecture visualization through four levels: Context, Containers, Components, and Code. As Brown describes it, C4 is like “Google Maps for your code” - you can zoom in and out based on what your audience needs to see.
Unlike prescriptive methodologies, C4 is both notation independent and tooling independent. You can use UML, simple boxes and lines, or any consistent notation. You can draw diagrams on whiteboards, in general-purpose tools like Visio or Miro, with diagram-as-code tools like Mermaid or PlantUML, or with specialized C4 tools like Structurizr.
The C4 model consists of:
- A set of hierarchical abstractions: software systems, containers, components, and code
- A set of hierarchical diagrams: system context, container, component, and code
- Additional supplementary diagrams: system landscape, dynamic, and deployment
This article covers:
- Understanding the 4 C4 levels and their purposes (based on official C4 documentation)
- A decision approach for selecting diagram levels (our interpretation with explicit reasoning)
- Strategic architecture decisions using C4 (for architects and technical leads)
- Domain-driven design integration (making business boundaries visible)
- Implementation process with working Mermaid examples (our approach)
- Common mistakes and how to avoid them (based on community experience)
Note: Team size guidelines, implementation timelines, and decision criteria presented here are practical interpretations based on organizational dynamics and software architecture principles, not official C4 specifications.
The Problem
In his 2018 InfoQ article introducing C4, Simon Brown identifies several problems with software architecture diagrams:
Ambiguity: Diagrams are often a “confused mess of boxes and lines” with unclear notation and semantics. Without legends, descriptions, or consistent notation, viewers project their own interpretations.
Scaled-Back Documentation: An unintended side effect of agile methodologies is that many teams have stopped or scaled back diagramming efforts, including the use of UML. Teams now rely on ad hoc whiteboard diagrams that are difficult to find or maintain.
Communication Breakdown: When diagrams are created, they often fail to serve their intended audiences effectively. Technical diagrams confuse stakeholders; high-level diagrams don’t provide developers with implementation guidance.
These problems manifest in several ways:
Onboarding Challenges: New developers spend time building mental models through trial and error. Senior developers repeat explanations in 1:1 sessions. Incorrect mental models lead to poor implementation decisions.
Decision Friction: Architecture discussions lack shared visual context. Teams debate without a common reference point, and the same questions resurface repeatedly.
Knowledge Concentration: System knowledge lives exclusively in specific people’s heads, creating bus factor risks and coordination overhead.
Documentation Rot: Diagrams created during initial design phases diverge from actual implementation as systems evolve. Outdated diagrams can cause more harm than having no diagrams.
Understanding the C4 Model
The following descriptions are based on the official C4 model documentation at c4model.com.
The Core Principle: Hierarchical Abstraction
The C4 model defines four levels of hierarchical abstraction:
- Software System: Made up of one or more containers
- Container: Each contains one or more components
- Component: Each implemented by one or more code elements
- Code: Classes, interfaces, objects, functions, etc.
Each level provides a different zoom level, similar to how map applications work. The hierarchy provides different levels of abstraction, each relevant to a different audience.
Level 1: System Context Diagram
Official Definition: Shows the software system you are building and how it fits into the world in terms of the people who use it and the other software systems it interacts with.
Purpose: Provides the big picture view - what is the system and who/what does it interact with?
Scope (from official documentation):
- A single software system
- People and software systems directly connected to the software system
Elements:
- Your software system (one box representing everything you’re building)
- People who use it (actors, roles, personas)
- External systems it depends on or interacts with
- Relationships between these elements
Audience: Everyone - technical and non-technical stakeholders, executives, product managers, developers, operations teams.
Time to Value: A rough Context diagram can be created in 30-60 minutes. Refine iteratively as understanding deepens.
Example: An e-commerce platform’s Context diagram would show the platform as a single box, with external connections to customers, administrators, payment gateway (Stripe), email service (SendGrid), and shipping provider API.
Technology Details: Context diagrams deliberately hide technology choices and internal implementation. The entire system appears as one box regardless of whether it’s a monolith or fifty microservices.
Color Coding: Brown’s examples use color to distinguish existing systems (grey) from systems being built (blue).
Level 2: Container Diagram
Official Definition: Zooms into the software system and shows the containers (applications, data stores, microservices, etc.) that make up that software system. Technology decisions are a key part of this diagram.
Purpose: Shows the high-level shape of the software architecture and how responsibilities are distributed. Shows major technology choices and how containers communicate.
What is a Container? According to the official C4 documentation:
“In the C4 model, a container represents an application or a data store. A container is something that needs to be running in order for the overall software system to work.”
Containers include:
- Server-side web applications (Java EE on Tomcat, ASP.NET on IIS, Node.js app)
- Client-side web applications (Angular, React SPA running in browser)
- Client-side desktop applications (WPF, Objective-C, JavaFX)
- Mobile apps (iOS, Android, Windows Phone)
- Server-side console applications (batch processes, standalone services)
- Serverless functions (AWS Lambda, Azure Functions)
- Databases (relational database schema, NoSQL database)
- Blob or content stores (S3 bucket, file system)
- File systems
- Shell scripts
Important: C4 containers are NOT Docker containers, though a Docker container would be a C4 container. The C4 terminology predates Docker. As the official documentation notes: “From one perspective, it’s unfortunate that containerisation has become popular, because many software developers now associate the term ‘container’ with Docker.”
Container vs. Deployment Artifact: Containers are runtime constructs, not deployment artifacts. Java JAR files, C# assemblies, and DLLs are used to organize code within applications, but aren’t containers themselves.
Scope (from official documentation):
- A single software system
- Containers within that system
- People and software systems directly connected to the containers
Audience: Software developers and support/operations staff. This is a simple, high-level technology-focused diagram.
Time to Value: A rough Container diagram can be created in 2-3 hours. Refine iteratively as deployment architecture stabilizes.
Technology Choices: At this level, you specify technologies: React, Node.js, PostgreSQL, Redis, RabbitMQ. These choices are relevant to developers and operations but would be noise in a Context diagram.
Level 3: Component Diagram
Official Definition: Zooms into an individual container to show the components inside it.
What is a Component? According to the official C4 documentation:
“In the C4 model, a component is a grouping of related functionality encapsulated behind a well-defined interface.”
The documentation further clarifies:
- For Java or C#: A component is a collection of implementation classes behind an interface
- Components are NOT separately deployable units (the container is the deployable unit)
- All components inside a container execute in the same process space
- Components should map to real abstractions in your codebase
Purpose: Shows how a container is decomposed into components, what each component is responsible for, and implementation details.
Scope (from official documentation):
- A single container
- Components within that container
- Supporting elements (other containers, systems)
Audience: Software architects and developers working on the specific container.
Time to Value: Component diagrams provide value when container complexity causes recurring questions. Create only when needed, not preemptively.
Mapping to Code: The official C4 documentation provides detailed guidance on mapping components to code structures. The strategy varies by codebase but typically involves grouping related classes/interfaces into logical components based on architectural patterns (layered architecture, hexagonal architecture, etc.).
Level 4: Code Diagram
Official Definition: Shows how an individual component is implemented as code.
Purpose: Provides implementation-level detail showing classes, interfaces, and their relationships.
Notation: C4 relies on existing notations at this level - UML class diagrams, entity-relationship diagrams, or diagrams generated by IDEs.
Simon Brown’s Guidance: In his InfoQ article, Brown states: “I wouldn’t necessarily recommend creating diagrams at this level of detail, especially when you can obtain them on demand from most IDEs.”
Scope (from official documentation):
- A single component
- Code elements within that component (classes, interfaces, objects, functions)
Audience: Software architects and developers who need to understand implementation details.
Reality Check: Code diagrams require continuous maintenance and become outdated quickly. The code itself is the source of truth at this level.
C4 Model Principles
Based on Simon Brown’s official guidance and InfoQ article:
Include Sufficient Text:
“Every element includes a name, the element type (i.e., ‘Person’, ‘Software System’, ‘Container’, or ‘Component’), a technology choice (if appropriate), and some descriptive text. It might seem unusual to include so much text in a diagram, but this additional text removes much of ambiguity typically seen on software architecture diagrams.”
This means each element should have:
- Name (clear, descriptive)
- Type (Person, Software System, Container, Component)
- Technology (where relevant)
- Description (explaining purpose/responsibility)
Always Include a Legend:
“Make sure that you have a key/legend to describe any notation that you’re using, even if it’s obvious to you. This should cover colours, shapes, acronyms, line styles, borders, sizing, etc.”
Consistent Notation:
“Your notation should ideally remain consistent across each level of detail.”
Diagram Titles:
“Don’t forget about the diagram title, which should appear on every diagram to unambiguously describe each diagram’s type and scope (e.g., ‘System context diagram for Internet banking system’).”
Notation Independence: The C4 model doesn’t prescribe specific notation. Use simple boxes and lines, UML, or any consistent approach. The notation works on whiteboards, paper, sticky notes, index cards, and various diagramming tools.
Decision Criteria: Which Levels Do You Need?
Note: The following criteria represent practical guidance based on software architecture principles and organizational dynamics, not official C4 specifications. C4 itself is notation and tooling independent and doesn’t prescribe when to use each level.
Understanding the Trade-offs
Every diagram level has:
- Creation cost: Time to create it
- Maintenance burden: Effort to keep it accurate
- Value delivered: Problems it solves
- Coordination overhead: Communication required to keep it current
Higher levels (Context, Container) have broader applicability, lower maintenance burden, and clearer ownership. Lower levels (Component, Code) have narrower applicability, higher maintenance burden, and distributed ownership.
Core Decision Criteria
Ask these questions for each level:
-
Does this diagram answer questions we get repeatedly?
- If no, skip it
- If yes, create it
-
Can we keep this accurate with available effort?
- If no, simplify or skip it
- If yes, establish ownership
-
Does this provide faster time-to-value than alternatives?
- Alternatives: pair programming, code reading, documentation
- If no, use the alternative
- If yes, create the diagram
Decision Tree
Question 1: Does your system interact with external systems or users?
├─ YES → Context Diagram provides value for stakeholder communication
│ Quick win: 30-60 minutes for rough version
└─ NO → Revisit when system has external interactions
Question 2: Does your system consist of multiple deployable parts?
├─ YES → Container Diagram provides value for technical teams
│ Quick win: 2-3 hours for rough version
└─ NO → Evaluate whether Container diagram adds value
Question 3: Do containers have internal structure causing repeated questions?
├─ YES → Component Diagram may provide value for those specific containers
│ Signals: "Where does this go?", inconsistent patterns, confusion
└─ NO → Component diagrams likely unnecessary
Question 4: Do you have algorithms/models requiring code-level visualization?
├─ YES → Consider whether IDE tools suffice before creating Code diagrams
└─ NO → Code diagrams likely unnecessary
Team Size and Communication Overhead
Why team size matters: Communication paths grow exponentially with team size. With 3 people, you have 3 communication paths. With 10 people, you have 45 paths. Documentation becomes more valuable as direct communication becomes more expensive.
Small Teams (2-5 people):
- Communication paths: 1-10
- Consider: Context + Container diagrams
- Rationale: Direct communication is cheap. Shared understanding emerges from daily collaboration. Documentation overhead may exceed value.
- Signals you might need more:
- New team member takes >2 weeks to become productive
- Repeated architecture questions
- Inconsistent implementation patterns
Medium Teams (6-15 people):
- Communication paths: 15-105
- Consider: Context + Container + selective Component diagrams
- Rationale: Direct communication becomes expensive. Not everyone knows every part. Documentation starts providing positive ROI.
- Signals you need Component diagrams:
- Developers ask “where does this logic belong?” weekly
- Code reviews reveal inconsistent patterns
- Features land in wrong containers
- Refactoring discussions lack shared understanding
Large/Distributed Teams (15+ people):
- Communication paths: 105+
- Consider: Full Context + Container diagrams, selective Component diagrams
- Rationale: Direct communication is very expensive. Clear boundaries essential for parallel work. Documentation is critical coordination mechanism.
- Distributed ownership: Platform teams maintain Context/Container. Service teams maintain Component diagrams for their containers.
System Complexity Indicators
“Complex” is vague. Here are concrete indicators:
Container needs Component diagram when:
- Developers regularly ask “where does this code belong?”
- Code reviews reveal 3+ different organizational patterns
- New features are implemented in inconsistent locations
- Defect rate in container is >2x other containers
- Refactoring discussions take >30 minutes without consensus
- Container has >5000 lines of code with unclear structure
Container does NOT need Component diagram when:
- Code organization is self-evident
- Team has consistent patterns
- New developers navigate it easily
- Low defect rate
- Clear separation of concerns
Cost-Benefit Analysis by Level
Context Diagram:
- Creation: 30-60 minutes (rough), 2-4 hours (polished)
- Maintenance: Quarterly or when external dependencies change
- Value: Explains system to all stakeholders, aligns understanding
- ROI: Very high - benefits everyone, rarely changes
Container Diagram:
- Creation: 2-3 hours (rough), 4-8 hours (polished)
- Maintenance: Monthly or when services added/removed
- Value: Deployment architecture, technology decisions, service boundaries
- ROI: High for systems with multiple deployables
Component Diagram:
- Creation: 2-4 hours per container
- Maintenance: When internal structure changes
- Value: Navigate complex containers, consistent patterns
- ROI: Varies - high for complex containers, negative for simple ones
Code Diagram:
- Creation: Depends on tooling
- Maintenance: Continuous (impractical)
- Value: Implementation details
- ROI: Usually negative - IDE tools better alternative
“Good Enough” Stopping Criteria
Stop creating more diagrams when:
- Architecture discussions no longer generate confusion
- Onboarding time is acceptable (developers productive in <2 weeks)
- Cross-team coordination doesn’t require constant meetings
- Diagrams aren’t referenced (they’re not solving problems)
- Maintenance burden outweighs benefits
Signs you need more detail:
- Same questions asked repeatedly
- Incorrect implementation decisions
- Long onboarding times
- Integration surprises between teams
Strategic Architecture Decisions
Note: This section provides strategic guidance for architects and technical leads on using C4 diagrams to make architecture decisions visible and discussable. This represents architectural practice, not official C4 specifications.
Identifying Architectural Problems with C4
Container diagrams reveal coupling and cohesion issues:
High coupling indicators:
- Many arrows between containers
- Containers that communicate with >5 other containers
- Circular dependencies between containers
- Containers that must be deployed together despite being separate
Low cohesion indicators:
- Container with responsibilities spanning multiple business capabilities
- Container name is vague (“Service Manager”, “Data Handler”)
- Container requires >3 Component diagrams to explain structure
- Multiple teams need to modify same container
When you see these patterns, ask:
- Should these containers be merged (too fine-grained)?
- Should this container be split (too coarse-grained)?
- Do service boundaries match team boundaries?
- Do service boundaries match business capabilities?
Using C4 for Lightweight Architecture Governance
Governance without bureaucracy:
Context Diagram governance:
- New external dependencies require architecture review
- External dependencies should align with buy vs. build strategy
- Track: Are we adding dependencies faster than removing them?
Container Diagram governance:
- New containers require justification (what problem does this solve?)
- Container technology choices should align with team skills
- Track: Container growth rate vs. team growth rate
- Red flag: More containers than team members who can deploy them
Component Diagram governance (when used):
- Components should follow consistent architectural patterns
- Component boundaries should match domain concepts
- Track: Component coupling trends over time
Decision records: Link Architecture Decision Records (ADRs) to relevant diagrams. Every significant architectural decision should have:
- Which diagram it affects
- Before and after states
- Rationale for change
- Consequences and trade-offs
Evolving Architecture Over Time
C4 diagrams enable iterative refinement:
Phase 1: Initial Design (Rough)
- Context diagram: 30 minutes, identify major external dependencies
- Container diagram: 2 hours, rough service boundaries
- Component diagrams: None yet
- Purpose: Establish shared vocabulary, identify major risks
Phase 2: Implementation (Refine)
- Context diagram: Updated when external dependencies added
- Container diagram: Updated as deployment architecture emerges
- Component diagrams: Created for containers with emerging complexity
- Purpose: Track reality vs. plan, adjust as learning occurs
Phase 3: Evolution (Maintain)
- Context diagram: Quarterly reviews
- Container diagram: Updated with each service added/removed
- Component diagrams: Updated when internal structure changes
- Purpose: Keep diagrams accurate, use as architecture governance tool
Refactoring indicators from diagrams:
- Container with 10+ connections: Consider API gateway or event bus
- Component diagram with 15+ components: Container might need splitting
- Circular dependencies: Need architectural refactoring
- “Core” containers that change weekly: Boundaries might be wrong
Where to Invest Architectural Complexity
Not all parts of your system deserve equal architectural attention. C4 diagrams help visualize where to invest effort:
High investment areas (visible in Container diagrams):
- Containers handling core business logic
- Containers with high change frequency
- Containers on critical path for business value
- Containers shared by multiple teams
Low investment areas:
- Generic containers (authentication, notification)
- Containers that rarely change
- Containers easily replaced with third-party services
- Supporting containers not on critical path
Use C4 to make this explicit:
- Color code containers by investment level
- Track: Are we spending architectural effort on high-value areas?
- Identify: Which containers could be replaced with SaaS?
- Plan: Where should architectural improvement effort go?
Architectural Health Metrics
Track these over time using C4 diagrams:
Coupling metrics (from Container diagrams):
- Average connections per container
- Maximum connections for any container
- Containers with circular dependencies
- Trend: Increasing or decreasing?
Complexity metrics:
- Number of containers per system
- Containers requiring Component diagrams
- Average components per container (when used)
- Trend: Increasing or decreasing relative to team size?
Knowledge distribution:
- How many people can explain Context diagram?
- How many people can explain Container diagram?
- Containers where only 1 person understands internals (bus factor)
Healthy trends:
- Coupling: Stable or decreasing
- Complexity: Grows slower than team size
- Knowledge: Spreading rather than concentrating
Domain-Driven Design: Making Business Boundaries Visible
Note: This section represents architectural interpretation of how C4 and DDD concepts work together, not official guidance from either approach.
Why DDD and C4 Together?
Domain-Driven Design focuses on making business domain explicit in code and architecture. C4 provides visualization that makes domain boundaries visible and discussable with business stakeholders, not just developers.
The core problem C4 solves for DDD: Business stakeholders can’t read code. They can read diagrams. C4 diagrams become shared language between business and technology.
Strategic Domain Design in C4
DDD identifies three types of subdomains:
- Core Domain: Your competitive advantage, highest business value
- Supporting Subdomain: Necessary but not differentiating
- Generic Subdomain: Common solutions, consider buy vs. build
Make this visible in Container diagrams:
Use color coding or annotations:
- Core domain containers: Blue (highest investment, custom solutions)
- Supporting containers: Yellow (moderate investment, customized)
- Generic containers: Grey (low investment, consider SaaS/COTS)
Example: E-commerce platform
Core Domain Containers (Blue):
- Recommendation Engine (competitive advantage)
- Pricing Service (dynamic pricing strategy)
Supporting Containers (Yellow):
- Order Service (necessary but not differentiating)
- Inventory Service (necessary but not differentiating)
Generic Containers (Grey):
- Authentication Service (use Auth0 or similar)
- Email Service (use SendGrid or similar)
- Payment Gateway (use Stripe or similar)
Why this matters:
- Architecture investment should match business value
- Core domain deserves Component diagrams, custom solutions, experimentation
- Generic domain should use off-the-shelf solutions when possible
- Container diagrams make investment strategy visible to business
When Technical and Domain Boundaries Should Align
Domain-to-Container mapping works well when:
- Each container encapsulates complete domain model
- One team owns one domain mapped to one container
- Domain boundaries are stable
- Clear ubiquitous language exists
Example alignment:
- Order Management (domain) → Order Service (container)
- Inventory Management (domain) → Inventory Service (container)
- Customer Account (domain) → Customer Service (container)
Benefits:
- Team autonomy (domain experts own their container)
- Clear ownership
- Easier to reason about business capabilities
- Changes to domain don’t ripple across containers
When Technical and Domain Boundaries Should Diverge
Not all containers are domains. Technical containers cross domain boundaries:
Cross-Domain Technical Containers:
- API Gateway: Routes to all domains, isn’t a domain itself
- Event Bus: Connects domains, isn’t a domain
- Search Service: Aggregates data from multiple domains
- Analytics Service: Observes all domains
Why this is OK: These are infrastructure concerns. They enable domains to communicate without knowing about each other. Don’t force them to be domains.
Single Domain Spanning Multiple Containers:
Sometimes organizational or technical reasons require splitting a domain:
- User domain split: Authentication Service + Profile Service
- Reporting domain: Data Collector + Report Generator
- Product domain: Catalog Service + Search Service
When to split:
- Different teams own different aspects
- Different technology requirements (e.g., search needs Elasticsearch)
- Different scale requirements (authentication scales differently than profiles)
- Different release cadences
Key principle: Make the split explicit in Container diagram. Document: “These three containers together implement the User domain.”
Making Domain Language Visible
Use ubiquitous language in diagram labels:
❌ Technical Language:
- “User Manager Service”
- “Data Processor”
- “Handler Component”
✅ Ubiquitous Language:
- “Order Fulfillment Service”
- “Inventory Allocation Service”
- “Payment Authorization Component”
If your business stakeholders say “Order Fulfillment,” your Container diagram should say “Order Fulfillment Service,” not “OrderProcessingManager.”
Domain Boundaries and Conway’s Law
Conway’s Law: Organizations design systems that mirror their communication structure.
C4 diagrams reveal Conway’s Law in action:
- Container boundaries often match team boundaries
- Components often match team structure within teams
- Communication paths between containers mirror team communication
Use this deliberately:
If you want domain-driven architecture:
- Organize teams around business capabilities (Order team, Inventory team)
- Container diagram will naturally follow domain boundaries
- Each team’s container becomes their bounded context
If teams are organized differently:
- Container boundaries won’t match domain boundaries
- Make this explicit in diagrams
- Document coordination mechanisms (how teams collaborate on shared domains)
C4 makes organizational constraints visible: A Container diagram that shows “Order Service owned by Team A” and “Inventory Service owned by Team B” but with 20 connections between them reveals organizational friction.
Either:
- Merge services (if teams can merge or coordinate closely)
- Reduce coupling (if teams need autonomy)
- Accept coordination cost (if organization can’t change)
Bridging Business-Technical Communication
Context diagrams for business conversations:
- Show how system provides business value
- External dependencies are business decisions (build vs. buy)
- User personas represent market segments or user types
- System name should match business vocabulary
Container diagrams for business-technical translation:
- Core/Supporting/Generic color coding shows investment strategy
- Container names use ubiquitous language
- Technology choices explain why certain capabilities exist
- Service boundaries show what can change independently
Example business conversation using diagrams:
Business: “Can we add a new payment method?” Technical (using Container diagram): “Payment Gateway is external (Stripe). Check their docs. If they support it, we can add it without code changes.”
Business: “How hard is it to change our recommendation algorithm?” Technical (using Container diagram): “Recommendation Engine is core domain (blue), isolated container. We can experiment without affecting other services. Medium effort but low risk.”
Business: “Why is search slow?” Technical (using Container diagram): “Search Service aggregates data from Order, Inventory, and Product services. Improving search requires coordinating three teams.”
Practical Application
Start simple:
- Create Container diagram with technical names
- Review with domain experts
- Rename containers to match ubiquitous language
- Add color coding for Core/Supporting/Generic
- Validate: Can business stakeholders understand which containers provide which capabilities?
Iterate: 6. When domain understanding deepens, refine container boundaries 7. When team structure changes, revisit whether containers should change 8. When business strategy shifts, update Core/Supporting/Generic classification
Outcome: Container diagram becomes shared artifact between business and technology, making architectural decisions visible and discussable with non-technical stakeholders.
Implementation Process
Note: The following process represents one practical approach, not official C4 guidance. Emphasizes quick wins and iterative refinement.
Phase 1: Initial Setup
Step 1: Inventory Your System
Document:
- Deployable units (applications, services, databases, queues, caches)
- External dependencies (third-party APIs, SaaS tools)
- User types (different personas)
- Key interactions
This inventory provides raw material for diagrams. Don’t perfect this—it will evolve.
Step 2: Choose Your Tool
C4 is tooling independent. Options include:
Diagram-as-Code:
- Mermaid: Version controlled, renders in GitHub/GitLab, free and open source
- Structurizr DSL: Official C4 tooling with precise control
- PlantUML: Mature, extensive features
Visual Tools:
- Miro/Whiteboard: Real-time collaboration
- Lucidchart/Visio: Polished presentations
- draw.io: Free, versatile
Trade-offs:
- Code-based: Better version control, harder for workshops
- Visual: Better for collaboration, harder to version control
Recommendation: Start with whatever is fastest for your team. Perfect is the enemy of good.
Step 3: Establish Conventions
Document your notation standards:
- Colors (internal vs. external systems)
- Shapes (rectangles for systems, cylinders for databases)
- Relationship labels (use verbs)
- File organization
Create a style guide that explains your conventions.
Phase 2: Create Initial Diagrams (Iterate, Don’t Perfect)
Context Diagram - Quick Win (30-60 minutes)
Goal: Rough sketch, not perfect. Iterate later.
- Place your system as single box in center
- Add user personas around it
- Add external systems around edges
- Draw relationships with descriptive labels
- Add name, type, and brief description to each element
- Include title and legend
Stop when: Everyone understands what the system does and what it depends on. Don’t polish yet.
Common mistakes:
- Spending hours on layout
- Including internal structure
- Perfectionism blocking progress
Container Diagram - Quick Win (2-3 hours)
Goal: Understand deployment architecture, not perfect documentation.
- Start with system boundary from Context diagram
- List all things that need to run (containers)
- Draw them as boxes with technology
- Connect with relationships
- Add descriptions
Stop when: Developers understand what needs to be deployed and how it communicates. Refine later.
Common mistakes:
- Mixing abstraction levels
- Too much detail
- Perfectionism
Component Diagrams - Only When Needed
Don’t create these yet. Wait until:
- Developers ask “where does this go?” multiple times
- Code organization is inconsistent
- New features land in wrong places
When that happens, create Component diagram for that specific container. Not all containers need Component diagrams.
Phase 3: Team Calibration Workshop
Objectives:
- Validate diagrams reflect reality
- Identify gaps
- Establish shared understanding
- Agree on update process
Agenda:
- Review Context Diagram (30 minutes): Validate boundaries and dependencies
- Review Container Diagram (45 minutes): Confirm deployment architecture
- Review Component Diagrams if applicable (45 minutes): Validate internal structure
- Establish Ownership (30 minutes): Who updates what and when
Outputs:
- Corrected diagrams
- Ownership model
- Update triggers
- Review cadence
Phase 4: Integration into Workflows
Sprint Planning:
- Review diagrams when planning cross-service features
- Update diagrams when architectural changes are planned
Architecture Reviews:
- Use diagrams to discuss system evolution
- Document decisions with diagram updates
Onboarding:
- New developers start with Context diagram (day 1)
- Progress to Container diagram (week 1)
- Reference Component diagrams for specific work areas
Documentation Updates:
Define clear triggers:
| Trigger Event | Diagram | Owner |
|---|---|---|
| New external dependency | Context | Architecture team |
| New service deployed | Container | Platform team |
| Service decomposed/merged | Container | Platform team |
| Major refactoring | Component (affected) | Service team |
Review Cadence:
- Monthly (first 3 months)
- Quarterly (after stabilization)
- On-demand (when inaccuracies reported)
Phase 5: Measuring Effectiveness
Track indicators such as:
- Onboarding time for new developers
- Whether diagrams are referenced in discussions
- Time between architectural change and diagram update
- Feedback from team on diagram usefulness
Red flags:
- Diagrams aren’t referenced (not providing value)
- Updates lag significantly (maintenance burden too high)
- “That’s wrong” comments without corrections (ownership unclear)
- Onboarding takes longer than before diagrams existed
Response: Simplify, clarify ownership, or stop creating diagrams until you understand what value they should provide.
Practical Examples with Mermaid
The following examples use Mermaid, one of several tooling options for C4 diagrams. Remember: C4 is tooling independent.
Example System: TaskFlow (Task Management SaaS)
We’ll use a fictional task management platform to demonstrate three diagram levels.
Level 1: Context Diagram
Following C4 principles: showing the system and its relationships to users and external systems.
C4 Principles Applied:
- TaskFlow Platform shown as single system
- Each element includes name, type, and description
- Technology noted where relevant (OAuth, Webhooks, API)
- Relationships are descriptive (“sends notifications via” not just “uses”)
- Would include legend in actual documentation
What This Shows:
- System boundaries and external dependencies
- User types and their relationships
- No internal implementation details (appropriate for this level)
Appropriate For: All stakeholders - executives, product managers, developers, operations.
Time to Create: 30-60 minutes rough, 2-4 hours polished
Level 2: Container Diagram
Following C4 principles: showing containers (applications, data stores) within the system with technology choices.
C4 Principles Applied:
- Each container is a separate deployable/runnable unit
- Technology choices specified (React, Node.js, Python, PostgreSQL)
- Different container types shown (applications, databases, queues, caches)
- Protocols specified in relationships (HTTPS, WebSocket, SQL, AMQP)
- Each element has name, type, technology, and description
What This Shows:
- Deployment architecture (what needs to run in production)
- Technology stack decisions
- How containers communicate
- Service boundaries
Appropriate For: Technical teams, DevOps, architects.
Time to Create: 2-3 hours rough, 4-8 hours polished
Level 3: Component Diagram
Following C4 principles: showing components within a container that map to real code abstractions.
C4 Principles Applied:
- Components represent groupings of related functionality
- Each component maps to real code abstractions (controllers, services, repositories)
- Shows responsibilities and relationships
- Integration points with external containers visible
What This Shows:
- Internal structure of Task Service
- Architectural patterns (layered architecture: Controller → Logic → Data Access)
- Where to add new functionality
- Component responsibilities
Appropriate For: Developers working on Task Service.
Note on Notification Service: We chose not to create a Component diagram for Notification Service. It’s simpler (consume event, route to channel, call API, handle retries) and may not benefit from a Component diagram. This demonstrates selective use of Component level.
When to Create: Only when developers ask structural questions repeatedly. Not preemptively.
Why Mermaid?
Mermaid is one option for C4 diagrams. Benefits and limitations:
Benefits:
- Version controlled with code in Git
- Renders automatically in GitHub, GitLab
- Text-based enables diffs and code review
- Programmatic generation possible
- Free and open source
Limitations:
- Learning curve for diagram-as-code syntax
- Less layout control than visual tools
- Mermaid C4 support still maturing
- Less aesthetic polish than design tools
Alternative Tools:
- Structurizr (official C4 tooling)
- PlantUML (mature diagram-as-code)
- Visual tools (Miro, Lucidchart, draw.io)
Remember: C4 is tooling independent. Choose based on your team’s needs.
Living Documentation: Keeping Diagrams Current
Diagrams become outdated when teams create them during design and forget them during implementation. Outdated documentation is worse than no documentation - it creates false confidence and leads to incorrect decisions.
Update Triggers
Define clear triggers indicating updates are needed:
| Trigger Event | Diagram | Owner | Urgency |
|---|---|---|---|
| New external dependency | Context | Architecture team | Within 1 week |
| New service deployed | Container | Platform team | Within 1 sprint |
| Service decomposed/merged | Container | Platform team | Immediately |
| Major refactoring | Component | Service team | Within 1 sprint |
| New user persona | Context | Product team | Within 1 month |
Scheduled Reviews:
- Monthly (first 3 months)
- Quarterly (after stabilization)
- Annually (comprehensive review)
Event-Based:
- Onboarding feedback from new team members
- Architecture reviews exposing outdated assumptions
- Incident postmortems revealing incorrect documentation
Ownership Models
Centralized (Small Teams):
- One person maintains all diagrams
- Team suggests changes via pull requests
- Lower coordination overhead
Distributed (Large Teams):
- Each team owns diagrams for their containers
- Platform team owns Context and Container diagrams
- Regular sync ensures consistency
Hybrid:
- Context + Container: Architecture/platform team
- Component: Individual service teams
- Review process ensures consistency
Validation Techniques
Code Review Integration:
Add to PR template:
# Checklist
- [ ] Tests pass
- [ ] Documentation updated
- [ ] Architecture diagrams updated (if applicable)
Architecture Decision Records (ADRs):
Link ADRs to relevant diagrams. When ADR is accepted, include diagram updates in implementation. Creates traceable history of architectural decisions.
Onboarding Feedback:
New team members validate diagrams during first month. Fresh eyes catch outdated or confusing elements. Creates incentive to keep diagrams accurate.
Measuring Freshness:
Track:
- Last updated date on each diagram
- “Diagram incorrect” reports
- Time between architectural change and diagram update
- Whether diagrams are referenced in discussions
If diagrams aren’t being used, they’re not providing value.
Common Mistakes and Solutions
❌ Creating All 4 Levels for Everything
Problem: Team creates Context, Container, Component, AND Code diagrams for every service. Massive maintenance burden. Diagrams become outdated.
Why It Happens: Belief that more documentation is always better. Following examples without considering actual needs.
Solution:
- Start with Context + Container
- Add Component diagrams only for containers generating repeated questions
- Skip Code level - use IDE tools instead
- Ask: “Will this diagram answer questions we get repeatedly?”
❌ Ambiguous Notation
Problem: Unlabeled boxes and lines, no legend, no descriptions. Viewers interpret differently.
Why It Happens: Assuming “everyone knows what we mean.” Creating diagrams quickly without following C4 principles.
Solution:
Follow Simon Brown’s guidance:
- Include name, type, technology, and description on every element
- Add legend to every diagram
- Use descriptive relationship labels (verbs, not just “uses”)
- Create templates enforcing C4 principles
Example:
❌ Violates C4 Principles: Box labeled “Service A” with arrow to “DB”
✅ Follows C4 Principles: Box labeled “Order Service (Python, FastAPI) - Manages order lifecycle from creation to fulfillment” with arrow labeled “Reads/Writes (SQL)” to “PostgreSQL Database - Stores order data, user information, product catalog”
❌ Wrong Audience Targeting
Problem: Super-detailed Context diagram with technology choices, or super-abstract Container diagram without technical details.
Why It Happens: Not understanding that different levels serve different audiences per C4 model.
Solution:
Remember C4’s hierarchical abstraction:
- Context: Non-technical stakeholders should understand without help
- Container: Technical teams, includes technology choices
- Component: Developers working on specific containers
- Each level serves different audience - embrace the separation
❌ Documentation Theater
Problem: Beautiful, polished diagrams that don’t match actual system. More time making diagrams pretty than keeping them accurate.
Why It Happens: Focus on form over function. No validation process.
Solution:
- Accuracy over aesthetics
- Implement validation (onboarding feedback, reviews, PR checks)
- Living documentation with clear triggers and ownership
- Measure and track freshness
❌ Container Confusion
Problem: Container diagram includes UI components, deployment details (Kubernetes pods), or class-level details. Mixing abstraction levels.
Why It Happens: Misunderstanding what “container” means in C4. Confusing C4 containers with Docker containers.
Solution:
Remember C4 definition: Container = application or data store that needs to be running for the system to work. NOT:
- UI elements
- Classes or modules
- Infrastructure components
- Deployment artifacts
Create separate deployment diagrams if infrastructure details are important.
❌ Component Explosion
Problem: Component diagram with 30+ boxes showing every class.
Why It Happens: Treating Component level like Code level. Not understanding component definition.
Solution:
Remember C4 definition: Components are groupings of related functionality, not individual classes. Consider:
- Limit to major groupings (controllers, services, repositories)
- Typically 5-12 components per container
- If you need more, consider splitting the container
❌ Update Neglect
Problem: Diagrams created during design, never updated as system evolves.
Why It Happens: No ownership, no triggers, no perceived value in updates.
Solution:
- Clear ownership model
- Update triggers in workflow (PR templates, ADRs)
- Code-based diagrams in repository (easy to update)
- Make updates visible work
❌ Premature Component Diagrams
Problem: Creating Component diagrams for all containers before code is written or before complexity emerges.
Why It Happens: Trying to “do architecture right” upfront. Following process rather than solving problems.
Solution:
- Wait for pain: Create Component diagrams only when developers repeatedly ask “where does this go?”
- Let complexity emerge: Don’t predict which containers will be complex
- Validate with usage: If Component diagram isn’t referenced after creation, delete it
Quick Reference
Decision Tree
1. System with external interactions?
YES → Context Diagram provides communication value (30-60 min)
NO → Revisit when system has external interactions
2. Multiple deployable parts?
YES → Container Diagram provides technical value (2-3 hours)
NO → Evaluate whether Container diagram adds value
3. Containers with recurring structural questions?
YES → Component Diagram may help (create selectively)
NO → Component diagrams likely unnecessary
4. Complex algorithms/models needing visualization?
EVALUATE → Consider whether IDE tools suffice
C4 Principles Checklist
Every element should include:
- Name (clear, descriptive)
- Type (Person, Software System, Container, Component)
- Technology (where relevant)
- Description (purpose/responsibility)
Every diagram should include:
- Title (type and scope)
- Legend/key (notation explanation)
- Last updated date
- Owner/maintainer
Suggested Maintenance Schedule
| Diagram Level | Update Trigger | Review Frequency |
|---|---|---|
| Context | New external dependency | Quarterly or as needed |
| Container | New service/database | Monthly or per release |
| Component | Internal restructuring | As needed |
| Code | Consider using IDE tools | N/A |
Complexity Indicators for Component Diagrams
Create Component diagram when:
- Developers ask “where does this go?” weekly
- Code reviews reveal 3+ organizational patterns
- Features land in wrong locations
- Defect rate >2x other containers
- Refactoring discussions >30 min without consensus
- Container >5000 LOC with unclear structure
Common Mermaid Syntax
// Context Diagram
C4Context
Person(id, "Name", "Description")
System(id, "Name", "Description")
System_Ext(id, "Name", "Description")
Rel(from, to, "Label", "Technology")
// Container Diagram
C4Container
Container(id, "Name", "Technology", "Description")
ContainerDb(id, "Name", "Technology", "Description")
ContainerQueue(id, "Name", "Technology", "Description")
System_Boundary(id, "Boundary Name") { ... }
// Component Diagram
C4Component
Component(id, "Name", "Technology", "Description")
Container_Boundary(id, "Container Name") { ... } Red Flags
- Diagrams aren’t referenced in discussions
- Updates lag significantly
- “That’s wrong” comments without corrections
- Onboarding takes longer than before diagrams
- Creating diagrams feels like compliance exercise
- Diagrams show idealized vs. actual architecture
Response: Simplify, clarify ownership, or stop creating diagrams until you understand what value they should provide.
Implementation Checklist
Week 1: Setup
- Inventory system components (rough list, don’t perfect)
- Choose tooling (fastest option for your team)
- Establish notation conventions (simple first)
- Create directory structure
- Set up diagram templates
Week 2: Initial Diagrams (Iterate, Don’t Perfect)
- Create rough Context Diagram (30-60 min)
- Create rough Container Diagram (2-3 hours)
- Identify containers that might need Component diagrams (don’t create yet)
- Stop when “good enough” - iterate later
Week 3: Validation
- Schedule team calibration workshop
- Walk through diagrams with team
- Collect feedback and make corrections
- Assign ownership
- Document update triggers
Ongoing: Integration
- Add diagram references to PR template
- Link diagrams in README and onboarding docs
- Include in architecture review agenda
- Monthly freshness check (first 3 months)
- Collect onboarding feedback
Success Indicators
- Onboarding time tracked
- Architecture discussions reference diagrams
- Diagrams updated within reasonable timeframe
- New team members can explain architecture
Conclusion
The C4 model, created by Simon Brown, provides a simple, hierarchical approach to software architecture diagramming. Its key strengths are notation independence, tooling independence, and hierarchical abstraction serving different audiences.
Official C4 Guidance:
- Use all four levels appropriately for your audience
- Follow principles: include sufficient text, always have a legend, use consistent notation
- Remember: notation and tooling are your choice
Practical Recommendations (Our Interpretation):
- Start with Context and Container diagrams (quick wins)
- Add Component diagrams selectively when complexity causes repeated questions
- Consider skipping Code level in favor of IDE tools
- Measure effectiveness through onboarding time and diagram usage
- If diagrams aren’t helping, simplify or stop creating them
For Architects:
- Use Container diagrams to visualize coupling and identify refactoring needs
- Map Core/Supporting/Generic domains to investment strategy
- Track architectural health metrics over time
- Make Conway’s Law visible and deliberate
For Domain-Driven Design:
- Make domain boundaries visible to business stakeholders
- Use ubiquitous language in diagram labels
- Color code containers by strategic importance
- Accept when technical and domain boundaries should diverge
Next Steps
- Review official C4 documentation at c4model.com
- Create rough Context diagram (30-60 minutes)
- Create rough Container diagram (2-3 hours) if multiple deployables
- Schedule team calibration workshop
- Establish update process with clear triggers
- Measure and iterate based on actual usage
Remember: Start simple. Iterate as understanding deepens. Good documentation serves a clear purpose. The C4 model provides the structure; you determine what level of detail your team needs.
Sources and Further Reading
Primary Sources:
- Official C4 Model - Simon Brown’s complete specification
- The C4 Model for Software Architecture - Simon Brown’s 2018 InfoQ article introducing C4
- C4 Model - Wikipedia - Overview and history
Supplementary Resources:
- Mermaid C4 Diagrams - Documentation for C4 support in Mermaid
- Structurizr - Official C4 tooling by Simon Brown
- C4-PlantUML - PlantUML library for C4 diagrams
- Architecture Decision Records - Complementary documentation approach
About the C4 Model:
Created by Simon Brown between 2006 and 2011, based on UML and the 4+1 architectural view model. The model gained popularity following the launch of the official website under Creative Commons license and Brown’s 2018 InfoQ article. Brown is an independent consultant specializing in software architecture and author of “Software Architecture for Developers.”
Note: This article was refined using AI editorial assistance.