The C4 Model is a diagramming framework. Over the years, we've had
many practitioners request C4 features in D2. There's even a community-maintained
exporter from the C4 creator's
tool, Structurizr, to D2.
The C4 Model is a loose framework. Unlike UML, which says these symbols always and must
mean certain things, the C4 model is a set of diagramming concepts. It's language and
tool agnostic, and these powerful concepts have proven to provide software projects with
clean, mature architecture diagrams.
With the latest 0.7 release of D2, we filled the gaps in the language to have first-class
support of these concepts:
A new suspend keyword which, along with existing D2 features, lets you define one
model and reuse them across different views.
Markdown labels on shapes allow you to give richer textual descriptions with font
hierarchy.
A new c4-person shape that is more conducive to holding longform labels.
A C4 theme for diagrams to be conveniently on-brand recognizable.
A new d2-legend variable to easily make beautiful legends.
Whether you choose to use these new features specifically for C4 model diagrams is up to
you. Much of this feature set was requested for other purposes. What's important are the
good practices it enables, which can be applied broadly across all sorts of diagrams.
In this article, I'll demonstrate how you can make C4 diagrams in D2. If you'd like more
detail on using a specific feature, you'll find dedicated sections in the
docs.
Let's say we want to create a view for the API team that only includes what's relevant for
them. We'll use the same code as the above, but add 2 sections:
Use globs to target everything declared so far and suspend them. These will be removed
unless "unsuspended" later on. Suspended objects and connections are effectively the
models.
Let's make a high level overview with the same concepts. The only change here is how we
unsuspend things.
And since there are connections between inner shapes of Internet Banking System to other
components, we'll make some connections that capture the general dependency.
Personal Banking Customer
[person]
A customer of the bank, with personal bank accounts.
Internet Banking System
[Software System]
E-mail System
[Software System]
The internal Microsoft Exchange e-mail system.
Mainframe Banking System
[Software System]
Stores all of the core banking information about customers, accounts, transactions, etc.
Let's say your repository of models is large; maybe everyone in your cross-functional team
is pushing their own models to this file.
To give an example of a small repository:
ATM Banking System
[Software System]
Allows customers to perform financial transactions via physical terminals.
Fraud Detection System
[Software System]
Monitors transactions for suspicious activity using ML algorithms.
Customer Service Portal
[Software System]
Tools for customer service representatives to assist clients.
Notification System
[Container: Java]
Sends alerts and notifications to customers via multiple channels.
Payment Gateway
[Container: Python & Django]
Processes payments and interfaces with external payment networks.
Backup System
[Container: Azure Cloud Storage]
Automated backup of critical banking data.
Administrative Portal
[Container: React]
Administrative interface for system maintenance and user management.
Security System
[Software System]
Manages authentication, authorization, and security policies.
Reporting Engine
[Container: Python & Pandas]
Generates reports and analytics for internal stakeholders.
Logging Service
[Container: ELK Stack]
Centralized logging for auditing and debugging purposes.
Compliance System
[Software System]
Ensures banking activities comply with regulations.
Customer Chatbot
[Container: Node.js & NLP]
AI-powered chat interface for customer support.
KYC Verification
[Software System]
Know Your Customer identity verification process.
Loan Processing System
[Container: Java EE]
Handles loan applications and approval workflows.
Investment Platform
[Software System]
Provides trading and investment capabilities to customers.
Account Management
[Container: Java & Spring Boot]
Core functions for creating and managing customer accounts.
Bill Payment Service
[Container: Node.js]
Allows customers to schedule and pay bills electronically.
Transaction Processor
[Container: Scala]
High-performance engine for processing financial transactions.
Data Warehouse
[Container: Snowflake]
Enterprise data repository for analytics and business intelligence.
Mobile Banking API
[Container: GraphQL & Node.js]
API gateway specifically optimized for mobile client applications.
To reuse these models for a specific domain, we can filter by their classes (tag in C4
vernacular). Assuming the models are in their own file, we can create something like a
CustomerInterface.d2 file, which imports these models, suspends all, and unsuspends the
ones that have the customer-facing class.
ATM Banking System
[Software System]
Allows customers to perform financial transactions via physical terminals.
Notification System
[Container: Java]
Sends alerts and notifications to customers via multiple channels.
Customer Chatbot
[Container: Node.js & NLP]
AI-powered chat interface for customer support.
KYC Verification
[Software System]
Know Your Customer identity verification process.
Investment Platform
[Software System]
Provides trading and investment capabilities to customers.
Bill Payment Service
[Container: Node.js]
Allows customers to schedule and pay bills electronically.
Mobile Banking API
[Container: GraphQL & Node.js]
API gateway specifically optimized for mobile client applications.
Now we can add some connections to create a diagram out of these pre-existing models.
ATM Banking System
[Software System]
Allows customers to perform financial transactions via physical terminals.
Notification System
[Container: Java]
Sends alerts and notifications to customers via multiple channels.
Customer Chatbot
[Container: Node.js & NLP]
AI-powered chat interface for customer support.
KYC Verification
[Software System]
Know Your Customer identity verification process.
Investment Platform
[Software System]
Provides trading and investment capabilities to customers.
Bill Payment Service
[Container: Node.js]
Allows customers to schedule and pay bills electronically.
Mobile Banking API
[Container: GraphQL & Node.js]
API gateway specifically optimized for mobile client applications.
To create a legend for this diagram, we declare it as a variable under
d2-legend.
Think of d2-legend as a mini diagram of its own, but with a special layout where every
shape and connection is deconstructed into a table. If something has opacity 0, it is
excluded in the table (this way we can have legends that only show connections, for
example).
Notice the legend in the bottom right corner.
ATM Banking System
[Software System]
Allows customers to perform financial transactions via physical terminals.
Notification System
[Container: Java]
Sends alerts and notifications to customers via multiple channels.
Customer Chatbot
[Container: Node.js & NLP]
AI-powered chat interface for customer support.
KYC Verification
[Software System]
Know Your Customer identity verification process.
Investment Platform
[Software System]
Provides trading and investment capabilities to customers.
Bill Payment Service
[Container: Node.js]
Allows customers to schedule and pay bills electronically.
Mobile Banking API
[Container: GraphQL & Node.js]
API gateway specifically optimized for mobile client applications.
Lastly, a core concept of C4 diagrams is this notion of zooming in and out of different
levels of abstraction. The 4 in C4 stands for the 4 levels of abstractions that it
recommends. Let's take a look at how that can be achieved. For this example, we'll define
two diagrams of code that represent a zoomed in view of the components.