PlantUML component & deployment diagrams: code to production
Class diagrams show “how classes relate.” Component diagrams show “how files / modules assemble.” Deployment diagrams show “how nodes connect at runtime.” Stack the three — that’s the standard recipe for complete architecture docs.
Three-tier architecture diagrams
Level
Describes
Audience
PlantUML keyword
Class diagram
Fields / methods / inheritance
Developers
class / abstract / interface
Component diagram
File / module / service / library
Architects / tech leads
component / package
Deployment diagram
Node (server / container / process) network layout
Architects / ops
node / cloud / database
Component diagram 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 @startuml title Monolith — component view package "Web App" { [Auth Controller] as Auth [Article Controller] as Article [Comment Controller] as Comment } package "Service Layer" { [User Service] as UserSvc [Article Service] as ArticleSvc [Notification Service] as NotiSvc } package "Data Layer" { database "PostgreSQL" as DB [Redis Cache] as Cache } Auth --> UserSvc Article --> ArticleSvc Comment --> CommentService UserSvc --> DB ArticleSvc --> DB ArticleSvc --> Cache NotiSvc --> ArticleSvc @enduml
Notes:
[name] is a component; renders as rounded rectangle with lollipop interface
package "X" { ... } is a package; renders as a labeled big rounded rectangle
database "X" as alias is a database; renders as a cylinder
--> is dependency
With interfaces and implementations 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 @startuml title Component interfaces interface "IDataStore" as IDataStore interface "INotifier" as INotifier package "Implementations" { [PostgresStore] as PgStore [EmailNotifier] as EmailN [SmsNotifier] as SmsN } package "Domain" { [OrderService] as OrderSvc } PgStore ..|> IDataStore EmailN ..|> INotifier SmsN ..|> INotifier OrderSvc --> IDataStore : uses OrderSvc --> INotifier : calls @enduml
..|> means “implements” (solid line + open triangle).
Nested components 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @startuml package "frontend" { package "src/components" { [LoginForm.tsx] [ArticleList.tsx] } package "src/api" { [userApi.ts] [articleApi.ts] } } [LoginForm.tsx] --> [userApi.ts] [ArticleList.tsx] --> [articleApi.ts] @enduml
A glance shows the code organization.
Deployment diagram 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 @startuml title Microservice production deployment node "Client Browser" { [React SPA] } node "CDN" { [Static assets] } node "API Gateway (Nginx)" { [nginx] } node "Kubernetes Cluster" { node "Pod: user-svc" { [User Service] } node "Pod: article-svc" { [Article Service] } node "Pod: payment-svc" { [Payment Service] } } node "AWS RDS" { database "PostgreSQL" } node "AWS ElastiCache" { database "Redis" } [React SPA] --> [Static assets] : loads [React SPA] --> [nginx] : API [nginx] --> [User Service] : HTTP [nginx] --> [Article Service] : HTTP [nginx] --> [Payment Service] : HTTP [User Service] --> [PostgreSQL] [Article Service] --> [PostgreSQL] [Article Service] --> [Redis] [Payment Service] --> [PostgreSQL] @enduml
node "X" { ... } is a deployment node (server / container / cluster). Arbitrarily nested: “Pod runs in cluster”, “container runs in Pod”, etc.
Node type keywords 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @startuml node browser [ <&desktop> Browser ] node server [ <&server> App server ] node lb [ <&gear> Load balancer ] database "PostgreSQL" { } cloud "Cloud Service" { } browser --> server server --> database server --> cloud @enduml
<&name> inserts Font Awesome–like icons.
Keyword
Meaning
Render
node
Generic node
Rectangle
cloud
Cloud service
Cloud shape
database
Database
Cylinder
frame
Browser / iframe
3D rectangle
component
Component
Lollipop rectangle
package
Package
Big rounded rectangle
<<device>> etc.
Custom stereotype
Custom
Association arrows 1 2 3 4 5 6 A --> B : HTTP/JSON A ..> B : async message A ==> B : strong relation A --|> B : extends A ..|> B : implements A .. B : dashed dependency
Arrow
Meaning
Visual
A --> B
association
solid + filled
A ..> B
dependency
dashed + filled
A ==> B
strong relation
solid + double
A --|> B
generalization
solid + open triangle
A ..|> B
realization
dashed + open triangle
Side-by-side: architecture + deployment 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 @startuml left to right direction frame "Component view" { [User Service] [Article Service] [PostgresDB] [User Service] --> [PostgresDB] [Article Service] --> [PostgresDB] } frame "Deployment view" { node "k8s cluster" { node "pod 1" { [User Service] } node "pod 2" { [Article Service] } } node "AWS RDS" { [PostgresDB] } } @enduml
Real example: e-commerce 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 @startuml title E-commerce — component view package "frontend" { [Web SPA] [Mobile App] } package "gateway" { [API Gateway] } package "microservices" { [User Service] [Product Service] [Order Service] [Payment Service] [Inventory Service] [Notification Service] } package "message bus" { queue "Kafka" as K } package "datastores" { database "User DB" as UDB database "Product DB" as PDB database "Order DB" as ODB database "Cache" as Cache } [Web SPA] --> [API Gateway] [Mobile App] --> [API Gateway] [API Gateway] --> [User Service] [API Gateway] --> [Product Service] [API Gateway] --> [Order Service] [Order Service] --> [Payment Service] [Order Service] --> [Inventory Service] [Order Service] --> K [Payment Service] --> K K --> [Notification Service] [User Service] --> UDB [Product Service] --> PDB [Order Service] --> ODB [Order Service] --> Cache [Inventory Service] --> PDB @enduml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 @startuml title E-commerce — deployment view node "Client" { [Web SPA] [Mobile App] } cloud "AWS Cloud" { node "Region: us-east-1" { node "ALB" { [API Gateway] } node "EKS Cluster" { node "namespace: svc" { node "pod: user" { [User Service] } node "pod: product" { [Product Service] } node "pod: order (3 replicas)" as PodOrder { [Order Service] } node "pod: payment" { [Payment Service] } node "pod: inventory" { [Inventory Service] } } node "MSK" { queue "Kafka" as K } } node "RDS" { database "PostgreSQL Multi-AZ" as RDS } node "ElastiCache" { database "Redis Cluster" as Cache } } } [Web SPA] --> [API Gateway] : HTTPS [Mobile App] --> [API Gateway] : HTTPS [API Gateway] --> [User Service] [API Gateway] --> [Product Service] [API Gateway] --> [Order Service] PodOrder --> RDS PodOrder --> Cache [Inventory Service] --> RDS @enduml
Component view: code organization. Deployment view: runtime.
Review checklist
Pitfalls
Too many components : aim for 5-15 per diagram. Beyond that, group or split.
Mixing concerns : component is compile-time; deployment is runtime. One diagram, one concern.
Deep node nesting : deeper than 3 levels and diagrams get unreadable. Use namespace / cluster as top-level layers.
Inconsistent arrow semantics : pick one (A → B means “depends on” / “calls” / “sends to”) and stick to it.
Mixing C4 with homegrown : pick one expression convention.
vs sequence diagrams
Diagram
Describes
One-liner analogy
Component
Code modules
“How many rooms in my house”
Deployment
Runtime nodes
“Where these rooms are in the city”
Sequence
Call order
“How a guest enters, moves through rooms”
Component + deployment + a few sequences = complete documentation.
TL;DR Component diagrams express “how it’s written”; deployment diagrams express “how it runs.” PlantUML covers both well — keep them versioned with the code.