Fundamentals 45 min read

Advanced C4 Modeling: Notation, Microservices & Scaling Architecture Diagrams

This article explores advanced C4 model topics including notation independence, element and relationship design, microservices and message-driven architecture modeling, scaling techniques for large systems, and a diagramming maturity model for engineering teams.

Code Archaeology
Code Archaeology
Code Archaeology
Advanced C4 Modeling: Notation, Microservices & Scaling Architecture Diagrams

1. Notation Independence Does Not Mean Notation Does Not Matter

C4 is notation independent — you can use any shapes, colors, line styles, icons, or even UML or ArchiMate. However, not all notations are equally effective. Good notation has three traits:

Makes diagrams understandable by the widest possible audience.

All distinguishing notation (shapes, colors, line styles, icons) is explained in a legend.

Notation stays consistent across all diagrams in a set — e.g., the same element uses the same notation on both a System Context and a Container diagram.

The goal is a diagram that "speaks for itself": readers grasp most content without verbal explanation. Since diagrams often get extracted from documents or presentations, good notation increases the chance a standalone diagram remains intelligible.

1.1 Diagram Title

Titles must state the diagram type and scope. Example: System Context View: Internet Banking System. This low‑cost line sets reader expectations immediately.

1.2 Abbreviations, Short Names & Codenames

Avoid opaque abbreviations; if needed, record them in a glossary or directly on the legend. Technical acronyms (HTTP, JSON, SQL) are fine for technical audiences. Internal codenames (e.g., "Plutus" for Payment Service) should be clarified: Payment Service (also known as Plutus) or Plutus (payment service) with a short description like Provides payment services to the retail website.

1.3 Layout

Keep element positions consistent across C4 levels — e.g., users at the top on both System Context and Container diagrams. Layout may reflect cultural reading direction, but consistency aids comprehension.

2. Elements: Write More Inside the Boxes

2.1 Start with Simple Boxes

On a whiteboard, use simple rectangles of one color for all elements. This defers shape/color debates and focuses on content first.

2.2 Name, Type, Technology, Description

Most architecture diagrams are just named boxes with ambiguous meanings. Put four things inside each box:

Name : what the element is called.

Type : what kind of element it is.

Technology : implementation technology (for containers and components).

Description : one‑sentence responsibility statement.

A template for this is shown in the article's images. The extra text adds needed clarity; a simplified version without descriptions can be used for live presentations.

2.3 Color, Shape, Size, Icons

Color can differentiate existing vs. new, off‑the‑shelf vs. custom, tech debt level, ownership, internal vs. external, etc. Every color meaning must be in the legend. Ensure diagrams work for color‑blind viewers and in black‑and‑white print.

Shape helps distinguish elements at a glance. Avoid subtle shape differences that vanish when scaled down.

Size implies importance/complexity; keep elements roughly the same size unless you intentionally encode size.

Icons add interest but must be explained in the legend.

3. Relationships: Where Arrows Point

Relationships glue elements together but are often neglected, hurting readability.

3.1 Arrow Direction

Arrow direction is flexible, but guidelines help. Double‑headed arrows are ambiguous (often read as bidirectional). Prefer single‑headed arrows representing a summary of the interaction: from initiator (active) to receiver (passive). Bidirectional interactions can be split into two single‑headed arrows, then merged into one for simplicity.

Labels should be specific, not vague like "uses". End labels with a preposition ( to, from, with) to clarify direction. Read the label as a sentence: "the UI makes API requests to the backend" reads naturally; the reverse does not.

Different architectural styles favor different arrow semantics: request‑driven systems use dependency arrows; message‑/event‑driven systems use arrows showing message/event flow. Choose one style and stay consistent.

When two distinct interactions exist between the same pair (e.g., synchronous API request + asynchronous pub/sub), draw two separate arrows — they differ in intent, technology, and synchronicity.

3.2 Line Styles

Use line styles to add another information layer: solid for synchronous, dashed for asynchronous. Color can also differentiate (e.g., green for HTTPS, red for HTTP). Avoid varying arrowhead shapes — they are subtle and disappear at small scales. All line styles, colors, and arrowheads must be in the legend; check color‑blind and black‑and‑white viability.

3.3 Legend

If you define your own notation, a legend is mandatory. Explain every notation variation used to distinguish elements or relationships. Even "obvious" notation can be misread; a legend gives everyone a fair chance. Watch for terms that need a specific frame of reference (e.g., "internal" vs. "external" system — internal to what?). Capture questions that arise during diagramming or reviews into the legend.

3.4 Do We Need a Standard Notation?

Organizations often want a company‑wide standard notation. Ideal but hard: defining it precisely for all architectures, products, and technologies is tedious and requires ongoing maintenance. Tool standardization helps but is also difficult.

Using UML or ArchiMate as C4's notation is possible — C4's core is hierarchical abstractions (Software System, Container, Component, Code) and hierarchical diagrams (System Context, Container, Component, Code). These map to UML component diagrams, packages with stereotypes, or a UML profile. However, most teams lack UML experience, UML tools struggle to produce rich, readable notation, and many tools cannot place descriptive text inside elements.

Conclusion: a standard visual notation is not required . C4's shared vocabulary is abstract — abstractions and diagram types — enabling unambiguous conversation regardless of notation, provided a legend explains the visuals.

3.5 Pre‑Diagram Checklist

A short notation review checklist:

Does the diagram have a title showing type and scope?

Is there a legend explaining all notation variations?

Does every element have a name, clear type, and clear responsibility?

Are container/component technology choices clear?

Are all abbreviations, short names, codenames understandable?

Are meanings of colors, shapes, icons, borders, sizes clear?

Does every arrow have a descriptive label matching its direction?

Is the relationship technology (e.g., protocol) clear?

Are arrow colors, shapes, line styles explained?

Most answers should be "yes"; a "no" likely marks where a standalone diagram would confuse readers.

4. Going One Layer Deeper

4.1 The Model‑Code Gap

New C4 teams should focus on the top two layers — System Context and Container diagrams — because they are quick to draw and change slowly. Lower layers change faster: Component diagrams change frequently during active development; Code diagrams can change on every commit (assuming hand‑drawn, not reverse‑engineered).

C4 defines four static structure diagrams to support conversations at different detail levels for different audiences. The four layers provide traceability: a logical zoom from Software System down to Code, with Code anchoring all upper layers to reality.

The model‑code gap (George Fairbanks, Just Enough Software Architecture ) is the mismatch between architectural abstractions (components, layers) and programming language constructs. Java has no "component" or "layer" keyword; teams implement abstractions via conventions — naming ( LoggingComponent), packages ( com.example.application.logging), modules/libraries ( application-logging). These conventions are often inconsistent within and across teams, leading to "wall architecture says one thing, code says another."

Top‑down mental models produce high‑level diagrams; bottom‑up reverse engineering produces detailed but overwhelming diagrams. Abstraction bridges the gap by providing simplified views of the code relevant to the current conversation.

4.2 Hardware Systems

For hardware‑control software (cameras, robots, medical devices), C4 does not model hardware internals, but hardware can appear as a Software System or a dedicated Hardware System abstraction to show integration points. Example: a camera modeled as a single box with a camera icon, hiding lenses, sensors, processors, etc.

5. How to Diagram Microservices

Two main choices: model microservices as a set of Containers or as a Software System . The choice depends on what "microservice" means in your context.

5.1 Phase 1: Monolith

Startup builds a single Software System (XYZ) delivering capabilities A and B. System Context shows customers using XYZ. Container diagram: one web app + one database schema inside XYZ boundary.

5.2 Phase 2: Microservice Architecture

Growth leads to microservices (per James Lewis & Martin Fowler: small services, own processes, lightweight HTTP APIs, built around business capabilities, independently deployable). In C4 terms: a single Software System decomposed into small services. System Context unchanged (still one team, one repo). Container diagram now shows the original web app plus separate microservices for capabilities A and B, each an API + database schema. All containers stay inside the XYZ system boundary — microservices are an internal implementation detail. Group related containers with a box to highlight the API+DB pairing.

5.3 Phase 3: Reorganizing Engineering Teams

Large team splits into smaller teams owning separate codebases/repos: Team XYZ (UI), Team A (Service A), Team B (Service B), Team C (Service C). Each team maintains its own System Context and Container diagrams from its perspective. The former microservices (containers inside XYZ) are promoted to independent Software Systems outside XYZ's boundary. Team XYZ's System Context now shows Services A, B, C as external systems. Team A's diagrams show inbound dependencies from XYZ and its internal containers. The label "service" replaces "microservice" because the promoted services may not meet the strict microservice definition (industry usage varies).

Key insight: how to diagram microservices depends on ownership and whether they are internal implementation details of one Software System or independent Software Systems owned by different teams .

Container diagrams are defined to show a single Software System. Showing multiple systems' internal containers on one diagram is discouraged — it exposes coupling (you know how XYZ internals talk to Service A internals). If teams own different systems, treat the other systems as opaque boxes (Software Systems) and rely on API contracts.

5.4 Message‑Driven Architecture

Common but tricky. Naïve hub‑and‑spoke diagram shows producers sending to a central "message bus" container, which forwards to consumers. This hides point‑to‑point coupling between specific producers and consumers via specific queues/topics.

Better: model each individual queue and topic as a C4 Container (data store) . A queue/topic is essentially a data store holding messages. This reveals direct coupling (Service A ↔ Queue 1 ↔ Service C). It also decouples logical architecture from deployment topology — queues/topics may share a broker in dev but be split across brokers/clusters in prod.

For simple point‑to‑point coupling, you can omit the queue box and put the queue name on the arrow label — simpler visually, less explicit. Both variants tell the same story; choose per context.

Arrow direction and labels can emphasize pub/sub (publishers → topic ← subscribers) for one‑to‑many relationships. Core rule: queues and topics should be modeled as C4 Containers ; visualization choices (show/hide queues, arrow direction, labels) are up to you.

If services are modeled as independent Software Systems, consider queue/topic ownership: who defines the message format, operates the queue? Ownership affects the diagram.

5.5 Software Systems vs. Feature Teams

C4 Software Systems often align with team boundaries, but not always. Feature teams, Spotify squads, or Team Topologies' stream‑aligned teams cut horizontally across systems to deliver a single capability. Modeling a business capability (X) as a Software System leads to duplicated subsets of Services A and B across multiple diagrams when different feature teams modify the same services. Recommendation: maintain one C4 diagram set per service (A, B); feature teams update those diagrams as part of their work.

6. Putting It Into Practice

6.1 Not a Silver Bullet

C4 suits typical enterprise software teams, not embedded or platform‑customization scenarios. It's a lightweight diagramming technique for teams that don't diagram or don't want heavy modeling (UML/ArchiMate). It doesn't cover state charts, ER diagrams, or enterprise architecture (business processes, functions). Use C4 as one tool among others (UML, ArchiMate, ER diagrams).

C4 diagrams show decision outcomes , not decision rationale . Supplement with lightweight documentation (e.g., arc42 template) and Architecture Decision Records (ADRs). C4 does not prescribe a software design process; using diagram layers to assign roles (BA draws Context, architect draws Container, etc.) is not its intended purpose.

6.2 Diagrams Give Feedback

Complex diagrams (many serverless functions, DynamoDB, cross‑triggering) become messy. Instead of only simplifying the diagram, ask whether the underlying design needs simplification. The diagram is a feedback loop for design quality.

6.3 Scaling C4

Real systems have 70, 700 components, not 7. Several combinable techniques:

Omit for Clarity : Cross‑cutting elements (logging, auditing) connect to almost everything. Options: (a) don't draw them; note in diagram or docs "all components log via Logging Component (omitted for clarity)". (b) draw the element but omit its connections; mark dependent elements with a symbol (e.g., asterisk) explained in legend.

Perspectives (from Woods & Rozanski, Software Systems Architecture ): Instead of new diagrams for ownership, security, tech debt, overlay a layer on existing diagrams. Toggle perspectives to highlight relevant elements, show details via tooltips. Keeps base diagrams clean. Implementation depends on tooling.

Split Diagrams : Break one large, cluttered diagram into several smaller ones, each telling part of the story. Split by: organizational grouping (System Landscape per group), business capability (System Context per capability), architectural slice (Container/Component diagram per feature, use case, functional area). Drawing tools make this hard (copy/paste, sync issues); modeling tools excel because views are subsets of a single model. Trade‑off: lose the big picture.

Alternative Visualizations : Beyond boxes‑and‑arrows. Force‑directed graphs (interactive, auto‑layout, click node to see neighbors) show the same model differently. Tree visualizations of deployment hierarchies (nodes as squares, software instances as circles) with tooltips for details. With a modeling tool, the model is just data — visualize it any way, or load into a graph database for queries.

7. From Diagramming to Modeling: Maturity & Next Steps

7.1 Diagramming Maturity Model

A five‑level maturity model to structure improvement:

Initial : No architecture diagrams.

Ad hoc : Loose boxes‑and‑arrows diagrams. Better than nothing, much room to improve.

Defined : Adopt C4 abstractions, diagram types, and notation guidelines (more text, legends). Tooling still irrelevant at this level.

Modeled : Shift mindset from drawing tools to modeling tools . Models still hand‑crafted (drag‑and‑drop or textual DSL).

Optimizing : Optimize how models are created, used, shared across teams. Automation via reverse engineering code/deployment; decentralized team work with auto‑generated organization‑wide System Landscape; treat models as datasets for multi‑visualization and querying.

Moving from drawing to modeling turns diagrams from liabilities into organizational assets.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

software architecturemicroservicesC4 modelarchitecture diagrammingdiagramming maturitymessage-driven architecturemodel-code gapnotation
Code Archaeology
Written by

Code Archaeology

Learn from the past to understand the present

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.