Some useful PlantUML architecture diagrams
PlantUML is very useful for creating architecture diagrams using text. However, the official documentation is so big (a 606 page PDF as of v1.2025.0) that it’s not always easy to find what I’m looking for. Yet, despite being so big, not everything is documented. For example, there are 45 “TODO"s, and norank
is not mentioned anywhere (but is mentioned in the unofficial but extremely helpful The Hitchhiker’s Guide to PlantUML).
So, following is a small collection of useful example architecture diagrams:
Example Diagrams §
Layered Architecture §
While the following diagram looks fairly simple, a lot of wrangling is required under the hood to ensure the layers and components are aligned correctly:
The main things to be aware of are:
- For structural purposes, a
hidden
right arrow is used between each component in a layer to ensure they are horizontally aligned in the correct order. - For structural purposes, a
hidden
down arrow is used between the first component from each layer to ensure that the layers are left-aligned. - Visible arrows:
- Use
norank
to prevent them from taking prescedence over thehidden
connections used for structural purposes and breaking the layout. - Except, if a visible arrow connects two components that were connected for structural purposes, the
hidden
arrow is omitted andnorank
is omitted. This prevents multiple arrows from connecting two components and breaking the layout.
- Use
@startuml
package LAYER_3 {
component Comp30 {
}
component Comp31 {
}
component Comp32 {
}
component Comp33 {
}
}
package LAYER_2 {
component Comp20 {
}
component Comp21 {
}
component Comp22 {
}
component Comp23 {
}
component Comp24 {
}
component Comp25 {
}
component Comp26 {
}
component Comp27 {
}
}
package LAYER_1 {
component Comp10 {
}
component Comp11 {
}
component Comp12 {
}
component Comp13 {
}
component Comp14 {
}
component Comp15 {
}
component Comp16 {
}
component Comp17 {
}
}
' Hidden connections
' ------------------
' Use hidden right connections to encourage the components
' within each layer to be placed in the desired order.
Comp30 -[hidden]r- Comp31
Comp31 -[hidden]r- Comp32
Comp32 -[hidden]r- Comp33
Comp20 -[hidden]r- Comp21
Comp21 -[hidden]r- Comp22
Comp22 -[hidden]r- Comp23
Comp23 -[hidden]r- Comp24
Comp24 -[hidden]r- Comp25
Comp25 -[hidden]r- Comp26
Comp26 -[hidden]r- Comp27
Comp10 -[hidden]r- Comp11
Comp11 -[hidden]r- Comp12
Comp12 -[hidden]r- Comp13
Comp13 -[hidden]r- Comp14
Comp14 -[hidden]r- Comp15
Comp15 -[hidden]r- Comp16
Comp16 -[hidden]r- Comp17
' Use hidden down connections between the first component in each
' layer to encourage all the layers to be left-aligned.
' NOTE: Use longer arrows to force more space between the layers, so
' that the visible arrows can be more clearly distinguished.
' NOTE: Since we later create a *visible* connection from Comp20 to
' Comp10, we omit create a hidden connection here, otherwise the
' visible connection ends up curving to avoid the hidden one.
Comp30 -[hidden]d-- Comp20
'Comp20 -[hidden]d-- Comp10
' Visible connections
' -------------------
' NOTE: Use norank to prevent these visible connections from taking
' prescedence over the hidden connections and breaking the layout,
' *except* for the visible connections which are equivalent to the
' hidden connections that we have omitted.
Comp23 -[norank,#6666ff,dotted]-> Comp10
Comp21 -[norank,dotted,#red]-> Comp10
Comp20 -d--> Comp10
Comp20 -[norank]-> Comp16
@enduml
For reference see this answer.
Block Architecture §
The Hitchhiker’s Guide to PlantUML provides some useful individual examples of C4 diagrams and of network diagrams with icons, but it does not combine the two. Following is an example of how you can combine them to get icons in your C4 diagrams:
In short, you include both C4
and osaPuml
. Then you can use the objects from C4 such as Container
, and the images from osaPuml
such as <$osa_wireless_network>
:
@startuml
set separator none
title Example RAN Architecture
left to right direction
!include <C4/C4>
!include <C4/C4_Context>
!include <C4/C4_Container>
!define osaPuml https://raw.githubusercontent.com/Crashedmind/PlantUML-opensecurityarchitecture2-icons/master
!include osaPuml/Common.puml
!include osaPuml/User/all.puml
!include osaPuml/Hardware/all.puml
!include osaPuml/Misc/all.puml
!include osaPuml/Server/all.puml
!include osaPuml/Site/all.puml
Person(User, "User")
Container(UE, "<$osa_iPhone>\nUE")
System_Boundary(CellTower, "Cell Tower") {
Container(RU, "<$osa_wireless_network>\nRU")
Container(DU, "<$osa_hub>\nDU\n")
}
Container(CU, "<$osa_hub>\nCU")
Container(Core, "<$osa_server>\nCore")
Container(Internet, "<$osa_cloud>\nInternet")
BiRel(User, UE, "")
BiRel(UE, RU, "RF", "Band n78")
BiRel(RU, DU, "eCPRI")
BiRel(DU, CU, "IP")
BiRel(CU, Core, "IP")
BiRel(Core, Internet, "IP")
@enduml
Software Layers §
Using package
, interface
, class
, <<Node>>
and some styling can be a useful way to represent software files:
The arrow directions are necessary to ensure the layout flows correctly. The <<(X,Y)>>
syntax after each interface
or class
allows specifying the text and colour for the small icon:
@startuml
' L3
package source.L3.L3_rrc <<Node>> {
interface L3_rrc_h as "L3_rrc.h" <<(H,orchid)>>
class L3_rrc_c as "L3_rrc.c" <<(C,yellow)>>
}
' L2
package source.L2.L2_pdcp <<Node>> {
interface L2_pdcp_h as "L2_pdcp.h" <<(H,orchid)>>
class L2_pdcp_c as "L2_pdcp.c" <<(C,yellow)>>
}
package source.L2.L2_rlc <<Node>> {
interface L2_rlc_h as "L2_rlc.h" <<(H,orchid)>>
class L2_rlc_c as "L2_rlc.c" <<(C,yellow)>>
}
package source.L2.L2_mac <<Node>> {
interface L2_mac_h as "L2_mac.h" <<(H,orchid)>>
class L2_mac_c as "L2_mac.c" <<(C,yellow)>>
}
' L1
package source.L1.L1_high <<Node>> {
interface L1_high_h as "L1_high.h" <<(H,orchid)>>
class L1_high_c as "L1_high.c" <<(C,yellow)>>
}
package source.L1.L1_low <<Node>> {
interface L1_low_h as "L1_low.h" <<(H,orchid)>>
class L1_low_c as "L1_low.c" <<(C,yellow)>>
}
' L3
L3_rrc_c -up[bold]-> L3_rrc_h
L3_rrc_c -up[bold]-> L2_pdcp_h
' L2
L2_pdcp_c -up[bold]-> L2_pdcp_h
L2_pdcp_c -up[bold]-> L2_rlc_h
L2_rlc_c -up[bold]-> L2_rlc_h
L2_rlc_c -up[bold]-> L2_mac_h
L2_mac_c -up[bold]-> L2_mac_h
L2_mac_c -up[bold]-> L1_high_h
' L1
L1_high_c -up[bold]-> L1_high_h
L1_high_c -up[bold]-> L1_low_h
L1_low_c -up[bold]-> L1_low_h
@enduml
Simple Stack §
Creole is the markup language used by PlantUML. As well as basic markup (e.g. bold, italic, font colour), it can do dividers, headings and icons.
Using dividers we can split up a node to create a very simple stack diagram. See 22.6 “Horizontal Lines” for more types of dividers and titles, e.g. ..My title..
.
This is quite limited. It is not possible to change the background colour of each section, but you can change the text colour:
@startuml
' Force the diagram to be wider
scale 400 width
' Specify colour for background and headings
node Node #dfd [
<b><color #262>L3</color></b>
* RRC
---
<b><color #262>L2</color></b>
* PDCP
* RLC
* MAC
===
<i>FAPI <<interface>></i>
===
<b><color #262>L1</color></b>
* PHY
]
@enduml