Thomas Pedot

dimanche 15 février 2026

Integrating Architecture Decision Records with C4 Model Diagrams

The Problem: Diagrams Without Context

C4 diagrams show what your architecture looks like. Architecture Decision Records (ADRs) document why it looks that way. Most teams maintain these separately — a draw.io file in one folder, ADR markdown files in another — and the two drift apart within months.

Six months after a design decision, no one remembers why the team chose microservices over a monolith, why PostgreSQL was picked over MongoDB, or why that third-party authentication provider was integrated instead of building in-house. The diagram is still accurate. The reasoning is gone.

This article shows a practical workflow for integrating ADRs directly into C4 model diagrams, using visual-c4.com as the primary tool.


What Is an Architecture Decision Record?

An ADR is a short document (typically one page) that captures a single architectural decision. The minimal format:

MARKDOWN
1# ADR-001: Use PostgreSQL as Primary Database
2
3**Status:** Accepted
4**Date:** 2026-01-15
5
6## Context
7We need a relational database for user accounts, projects, and diagram data.
8We evaluated PostgreSQL, MySQL, and SQLite.
9
10## Decision
11Use PostgreSQL for production. Use SQLite for development and self-hosted deployments.
12
13## Consequences
14- PostgreSQL requires a managed database service in production (adds ~$20/month)
15- SQLite allows zero-ops self-hosting for small teams
16- Prisma supports both — schema is identical, connection string changes

The key insight: an ADR captures the decision at the time it was made, including the options considered and the context that no longer exists. It's a letter to your future self.

For a full guide on ADR formats and templates, see the C4 + ADR documentation on visual-c4.com.


The Integration Model

The core idea is to attach ADRs to C4 diagram nodes — not to store them separately.

When you click a component on a C4 container diagram, you should be able to see:

  • What this component does (from the diagram label)
  • Why this component exists (from linked ADRs)
  • What decisions were made about its design (also from ADRs)

This is what visual-c4.com implements natively. Each diagram node can have one or more ADRs linked to it.


Practical Workflow

Step 1: Start with the C4 Context Diagram

Before writing any ADRs, draw the System Context diagram. This forces you to identify:

  • Your system's external boundaries
  • The users and external systems it interacts with

The context diagram becomes the "table of contents" for your ADRs. Each significant external dependency (a third-party payment API, an email service, an authentication provider) should have at least one ADR explaining why it was chosen.

Step 2: Drill Down to Container Diagrams

For each container in your C4 Container diagram, ask: "Why does this container exist as a separate container?"

If you added a separate Redis container alongside PostgreSQL, that's an architectural decision. Write an ADR:

MARKDOWN
1# ADR-007: Use Redis for Session Storage
2
3**Status:** Accepted
4
5## Context
6User sessions need to be shared across multiple API server instances.
7Storing sessions in PostgreSQL adds database load and complicates horizontal scaling.
8
9## Decision
10Use Redis for session storage. Sessions expire automatically via TTL.
11
12## Consequences
13- Adds Redis as an infrastructure dependency
14- Sessions survive API restarts (good)
15- Sessions are lost if Redis goes down without persistence (acceptable for this use case)

Then in visual-c4.com, link this ADR to the Redis container node.

Step 3: Component-Level ADRs

Component diagrams are where the most implementation decisions happen. Useful ADR triggers at this level:

  • Why CQRS? — If you split read and write paths
  • Why a domain event pattern? — If components communicate via events
  • Why a specific adapter pattern? — If you abstracted a third-party SDK

Keep component-level ADRs shorter than system-level ones. They're often one-paragraph decisions:

MARKDOWN
1# ADR-012: Use DataLoader for GraphQL N+1 Prevention
2
3**Status:** Accepted
4
5## Context
6Our GraphQL resolvers were triggering N+1 database queries for list fields.
7
8## Decision
9Wrap all repository calls in DataLoader. Batch database queries per request tick.
10
11## Consequences
12- All resolver data access goes through DataLoader
13- Significantly reduced database query count in list queries
14- Adds DataLoader as a dependency in each resolver file

Step 4: ADR Lifecycle Management

ADRs should change status as the system evolves:

StatusMeaning
ProposedDecision under discussion
AcceptedCurrent decision in use
DeprecatedStill in use but planned for replacement
SupersededReplaced by a newer ADR

When you migrate from PostgreSQL to a managed cloud database, you don't delete ADR-001 — you mark it as Superseded by ADR-023. This preserves the historical record.

In visual-c4.com, ADR status is visible directly on the diagram — deprecated decisions show visually on the linked component, prompting review.


File-Based ADR Workflow (Without a Tool)

If you're not using visual-c4.com, the simplest ADR workflow is a /docs/adr/ folder in your repo:

Plain Text
1project/
2├── docs/
3│   └── adr/
4│       ├── 0001-use-postgresql.md
5│       ├── 0002-separate-blog-and-app.md
6│       ├── 0003-use-cytoscape-for-graph.md
7│       └── README.md   ← index of all ADRs
8├── src/
9└── ...

Link ADRs to C4 diagrams by adding an ADRs: section to diagram element descriptions:

Plain Text
[PostgreSQL Database]
Description: Primary relational store for projects, diagrams, and ADRs.
ADRs: docs/adr/0001-use-postgresql.md, docs/adr/0007-use-redis-for-sessions.md

The limitation: this only works if your C4 diagrams live in a text-based format (Structurizr DSL, PlantUML). Visual tools that export images lose this metadata.


Why This Matters

The ROI of ADR + C4 integration becomes obvious during:

Onboarding. New team members can explore the C4 diagram and click any component to understand not just what it does but why it was built that way. Onboarding time drops significantly.

Architecture reviews. When evaluating a refactoring, you can see which decisions are still valid and which are outdated. The diagram shows what changed; the ADRs show whether the original reasoning still applies.

Incident post-mortems. After an incident involving a specific component, you can immediately see the ADR trail — what tradeoffs were accepted when that component was built.


Getting Started

  1. Start at visual-c4.com — create a free account
  2. Draw your System Context diagram first
  3. Write one ADR for each significant external dependency
  4. Drill down to Container level, link ADRs to containers
  5. Review and update ADR status as the system evolves

For more on the C4 model itself: What is the C4 Model? For ADR best practices: Architecture Decision Records Guide For C4 + ADR integration in practice: Linking ADRs to C4 Models