Architecture: Document architecture in a way that everyone understands
Nikita Rykhlov

Nikita Rykhlov @nikita_rykhlov

About: Senior backend engineer with 5+ years in Go, microservices, and high-load systems. Sharing practical insights, real-world cases, and tips for developer growth.

Location:
Abu Dhabi, Abu Dhabi Emirate, United Arab Emirates
Joined:
May 18, 2025

Architecture: Document architecture in a way that everyone understands

Publish Date: May 27
1 0

In the world of backend development and designing complex systems, it's not enough just to write good code — it's equally important to clearly communicate architectural ideas to your team, clients, or new developers joining the project. One of the most effective tools for this is the C4 Model — a simple yet powerful way to document and visualize software architecture.

Created by Simon Brown, the C4 model offers a hierarchical approach to diagramming, allowing you to gradually zoom in from broad concepts to detailed implementation. The model consists of four levels:

  1. System Context
  2. Containers
  3. Components
  4. Code

What makes it especially convenient is that C4 is often used together with PlantUML, a powerful text-based tool for creating UML diagrams. This allows you to describe your system structure directly in code, easily keep diagrams up to date, and automate their rendering.

Let’s explore each level and provide examples using PlantUML.


1. System Context Diagram

At the highest level of abstraction, we see the whole system within its environment. The goal of this level is to show:

  • What system is being built
  • Who interacts with it (users, external systems)
  • How it connects to other systems

Example:

Suppose you're building a food delivery platform . The diagram would include: the core service itself, users (customers, couriers, restaurant owners, admins), payment gateways, SMS services, geolocation APIs, and analytics systems — everything your platform interacts with externally to function effectively.

System Context Diagram: Food Delivery Service

PlantUML:

@startuml
title System Context Diagram: Food Delivery Service

skinparam rectangle {
    roundCorner 20
}

actor "User" as user
actor "Courier" as courier
actor "Admin" as admin
actor "Restaurant Owner" as restaurant_owner

[Food Delivery Service] as foodservice

user --> foodservice : Orders food, views menu
courier --> foodservice : Receives tasks, updates status
restaurant_owner --> foodservice : Manages menu, accepts orders
admin --> foodservice : Administers system, analytics, moderation

foodservice --> [Payment Gateway] : Payment processing
foodservice --> [SMS Service] : Sends notifications
foodservice --> [Geolocation API] : Location detection
foodservice --> [Analytics System] : Sends metrics

note right of foodservice
  A full-featured food delivery platform
  supporting multiple restaurants, users,
  couriers and analytics.
end note

@enduml
Enter fullscreen mode Exit fullscreen mode

2. Container Diagram

At this level, we look inside the system and show its main containers — these are separate processes or hosts that communicate with each other. A container can be:

  • A web application (e.g., Node.js API)
  • A database (PostgreSQL, MongoDB)
  • A message broker (RabbitMQ, Kafka)
  • Microservices
  • Frontend app (React)

Example:

In a food delivery platform, possible containers could be:
API Gateway — routes incoming requests to the appropriate services
Order Service — manages order lifecycle (creation, modification, queueing)
Restaurant Service — handles restaurant and menu data
User Service — manages user profiles and authentication
Notification Service — sends alerts and updates via SMS or push
Payment Service — processes payments through an external gateway
Location Service — integrates with geolocation APIs for couriers and users
Analytics Service — collects and analyzes system metrics
PostgreSQL Cluster — stores core data like users, orders, and restaurants
Redis Cache — improves performance by caching frequently accessed data
RabbitMQ — handles internal service communication via events
Kafka — logs all events for analytics and system recovery

Container Diagram: Food Delivery Service

PlantUML:

@startuml
title Container Diagram: Food Delivery Service

package "Food Delivery Service" {
  [API Gateway] as gateway
  [Order Service] as orderservice
  [Restaurant Service] as restaurantservice
  [User Service] as userservice
  [Notification Service] as notificationservice
  [Payment Service] as paymentservice
  [Location Service] as locationservice
  [Analytics Service] as analyticsservice
  [PostgreSQL Cluster] as database
  [Redis Cache] as cache
  [RabbitMQ] as messagebroker
  [Kafka] as eventlog

  note bottom of orderservice
    Manages order lifecycle:
    creation, modification, queueing.
  end note

  note bottom of messagebroker
    Used for internal communication
    between services via events.
  end note

  note bottom of eventlog
    Stores all system events
    for analytics and recovery.
  end note
}

gateway --> orderservice
gateway --> restaurantservice
gateway --> userservice
gateway --> paymentservice
gateway --> locationservice

orderservice --> database
orderservice --> messagebroker
orderservice --> cache

restaurantservice --> database
restaurantservice --> cache

userservice --> database

paymentservice --> [Payment Gateway]

locationservice --> [Geolocation API]

notificationservice <-- messagebroker
analyticsservice <-- eventlog

@enduml
Enter fullscreen mode Exit fullscreen mode

3. Component Diagram

Now we go one level deeper and look at what components reside inside each container. At this point, developer-level design decisions begin to emerge:

  • Which modules, services, repositories are used
  • How they interact with each other
  • Which frameworks and technologies are involved

Example:

Inside the Order Service container, there might be these components:
HTTP Handler — receives and routes incoming HTTP requests
Order Use Case — contains core business logic for creating, updating, and retrieving orders
Order Repository — interacts with the database to persist and retrieve order data
Event Publisher — publishes events (e.g., “OrderCreated”) to the message broker
Config Manager — provides configuration values to all components
Validator — ensures input data is valid before processing
Metrics Collector — gathers performance and usage metrics for monitoring

Component Diagram: Order Service

PlantUML:

@startuml
title Component Diagram: Order Service

package "OrderService" {
  [HTTP Handler] as handler
  [Order Use Case] as usecase
  [Order Repository] as repo
  [Event Publisher] as publisher
  [Config Manager] as config
  [Validator] as validator
  [Metrics Collector] as metrics

  note right of usecase
    Contains business logic for creating,
    updating and retrieving orders.
  end note

  note bottom of validator
    Validates order data before
    performing any operations.
  end note
}

handler --> usecase : Create / Get order
usecase --> validator : Validates input data
usecase --> repo : Works with DB
usecase --> publisher : Publishes event
usecase --> metrics : Logs metrics

config -down-> handler
config -down-> usecase
config -down-> repo
config -down-> publisher

@enduml
Enter fullscreen mode Exit fullscreen mode

4. Code Diagram

This is the lowest level — the source code level. Here you can show:

  • Class diagrams
  • Object interactions
  • Method or function calls

However, code diagrams can quickly become outdated if not maintained. They’re best used to explain key algorithms or complex parts of the logic that are hard to understand without visual representation.

Example:

A diagram demonstrating the internal structure of the OrderUsecase, showing how it interacts with core components like OrderRepository, EventPublisher, and Validator. This UML diagram clarifies the flow of operations during order creation — from validation and persistence to event publishing, helping developers understand the logic and dependencies at the code level.

Code Diagram: Order Usecase

PlantUML:

@startuml
title Code Diagram: Order Usecase

class OrderUsecase {
  +CreateOrder(*Order) error
  +GetOrder(string) (*Order, error)
}

class OrderRepository {
  +Save(*Order) error
  +FindByID(string) (*Order, error)
}

class EventPublisher {
  +Publish(event Event) error
}

class Validator {
  +ValidateOrder(*Order) error
}

OrderUsecase --> OrderRepository : Uses
OrderUsecase --> EventPublisher : On create
OrderUsecase --> Validator : Before save

note right of OrderUsecase
  Executes business logic for order creation,
  calls repository and event publisher.
end note

@enduml
Enter fullscreen mode Exit fullscreen mode

Why Use the C4 Model?

The C4 model is valuable because it:

  • Simplifies communication between developers, analysts, testers, and managers.
  • Allows you to see the big picture while having the ability to zoom into specific areas.
  • Improves architecture documentation — especially important in long-term projects.
  • Eases onboarding of new team members.
  • Helps with risk assessment, threat modeling, and architectural reviews.

How to Start Using C4 and PlantUML

If you want to start applying C4 in your work, here are some steps:

  1. Start with the System Context level — define who interacts with what.
  2. Move to the Containers level — show the main technical blocks.
  3. Add the Components level for key containers — reveal their internal structure.
  4. Use the Code level when necessary — only where it adds real value.
  5. Write diagrams in PlantUML — this will help you maintain them easily.
  6. Integrate into documentation — for example, via Markdown or Confluence with PlantUML support.

Conclusion

The C4 model is more than just a set of diagrams — it's a structured approach to understanding and describing architecture. It helps everyone on the project — from technical specialists to business stakeholders — speak the same language.

If you're working on complex backend systems, microservices, or simply want to better organize your thoughts during design, the C4 model will be a great addition to your toolkit. And using PlantUML will make working with diagrams easy, repeatable, and well-documented.

More about C4

More about PlantUML

📌 What do you think?

Have you tried C4 or PlantUML yet?

What tools or methods do you use to document your system architecture?

👇 Leave a comment below — I’d love to hear your experience!

👍 Don’t forget to like and share if you found this helpful — so more people can benefit from it too!


📣 Follow me and read my content on other platforms:

Check out this and other articles on my pages:

🔗 LinkedIn
📚 Medium
📘 Facebook
✈️ Telegram
🐦 X

Oh, almost forgot — my personal website.

🔔 Follow me not to miss new articles and guides on hot topics!

Comments 0 total

    Add comment