C4 Model

2 minute read

How do you explain the architecture of your most favorite or challenging project? Do you draw all these nice squares and circles on a board (or perhaps, MS Paint?) and connect them with the fancy lines and arrows? Finally, you would add the labels here and there - it looks just great! Then you are asked to zoom into a particular area, and everything becomes a mess. The more you need to draw, the messier it becomes.

C4 Model is to the rescue. This approach provides a top-down way to see the architecture from four perspectives. You show the system from the most abstract Context diagram to the most detailed Code diagram. Learn more about the C4 architectural approach on wiki.

Recently I’ve struggled to explain the architecture during the Systems Design interview. Here I will be using one of my past projects to describe the Parking System according to the C4 Model architectural approach.

Context diagram

context diagram

@startuml
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml

' caption Context Diagram for Parking Services

LAYOUT_WITH_LEGEND()

Person_Ext(parking_customer, "Customer", "A customer using parking services")
Person_Ext(enforcement_customer, "Enforcement Officer", "An enforcement officer verifying parked vehicles")
Person_Ext(city_customer, "City Council", "A city council maintains parking zones and permits")

System(onboard, "On-board Computer (OBC)", "Displays parking tariff and zone information")
System(parking, "Parking System", "Parking system that starts and stops parking actions")
System(enforcement, "Enforcement System", "Provides information to the enforcement officers and handles fines")

System_Ext(payments, "Payment Gateway", "Provides payment service") 

Rel(parking_customer, onboard, "Start parking")
Rel(parking, payments, "Redirects payment to")
Rel(onboard, parking, "Dispatches parking request")

Rel(parking, enforcement, "Exports parking details")
Rel(enforcement, enforcement_customer, "Handles license plate scan")


Rel(city_customer, parking, "Request consolidated report")
@enduml

Containers diagram

containers diagram

@startuml
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml

AddElementTag("micro service", $shape=EightSidedShape(), $bgColor="CornflowerBlue", $fontColor="white")
AddElementTag("storage", $shape=RoundedBoxShape(), $bgColor="lightSkyBlue", $fontColor="white")

SHOW_PERSON_OUTLINE()
Person(customer, Customer, "A customer using mobile parking app")

System_Boundary(c1, "Parking system") {
    Container(api_gateway, "Orchestration", "ASP.NET WebAPI", "Entrypoint, coordinates workflows")
    Container(auth_service, "Auth Service", "dotnet", "The point of access for customer information", $tags = "micro service")
    Container(tariff_service, "Tariff Service", "dotnet", "Handles tariffs and related business rules", $tags = "micro service")
    Container(inventory_service, "Inventory Service", "php", "Handles location and POIs", $tags = "micro service")
    Container(parking_service, "Parking Service", "dotnet", "Handles parking actions", $tags = "micro service")
}

Container(message_bus, "Message Bus", "SQS")
Container(enforcement_service, "Enforcement Service", "dotnet", "Supports enforcement officers", $tags = "micro service")
Container(reporting_service, "Reporting Service", "Ruby", "Creates normalised data for reporting purposes", $tags = "micro service")
Container(audit_service, "Audit Service", "C#/.NET", "Provides organisation-wide auditing facilities", $tags = "micro service")
ContainerDb(scan_db, "Scan Database", "AmazonDb", "Stores denormalized information for fast license plate scans", $tags = "storage")
ContainerDb(reporting_db, "Reporting Database", "SQL Server", "Stores a normalized version of all business data for ad hoc reporting purposes", $tags = "storage")
Container(audit_store, "Audit Store", "Event Store", "Stores information about events that have happened", $tags = "storage")

Rel_D(customer, api_gateway, "/api/parking/start", "POST")
Rel_D(api_gateway, auth_service, "get OAuth2 token")
Rel_D(api_gateway, inventory_service, "check location")
Rel_D(api_gateway, tariff_service, "calculate tariff")
Rel_D(api_gateway, parking_service, "create parking action")

Rel(parking_service, message_bus, "ParkingStarted")
Rel(message_bus, enforcement_service, "Updates scan database")

Rel(message_bus, reporting_service, "Sends customer update events to")
Rel(message_bus, audit_service, "Sends customer update events to")

Rel(reporting_service, reporting_db, "Stores data in")
Rel(audit_service, audit_store, "Stores events in")
Rel(enforcement_service, scan_db, "Stores data in")

Lay_R(reporting_service, audit_service)

SHOW_LEGEND()
@enduml

Final thoughts

I like the idea of C4 Model and use it successfully with my customers. It’s got me thinking about using the C4 Model for Systems Design. The C4 Model offers an elegant approach to decomposing a system and providing different perspectives.

Updated: