The UML Audit: Which Diagrams Are Actually Used
UML 2.x defines 14 diagram types across two categories: structural (what the system is) and behavioral (what the system does). Here's an honest assessment of real-world usage:
| Diagram | Category | Used in Practice | Why (or Why Not) |
|---|---|---|---|
| Class Diagram | Structural | Yes | OOP design, API contracts, library documentation |
| Sequence Diagram | Behavioral | Yes | The single most useful diagram for backend engineering |
| Activity Diagram | Behavioral | Yes | Business process flows, algorithm visualization |
| State Machine Diagram | Behavioral | Yes | Order lifecycles, auth states, UI state machines |
| Use Case Diagram | Behavioral | Yes (limited) | Requirements gathering, stakeholder communication |
| Component Diagram | Structural | Yes (limited) | Now mostly replaced by C4 L2/L3 for clarity |
| Package Diagram | Structural | Rarely | Too abstract; C4 or module diagrams communicate better |
| Object Diagram | Structural | Rarely | Useful for debugging — rarely for architecture |
| Deployment Diagram | Structural | Rarely | Replaced by cloud provider architecture diagrams or C4 L2 |
| Communication Diagram | Behavioral | No | Sequence diagrams convey the same info more clearly |
| Timing Diagram | Behavioral | No | Only in real-time embedded systems |
| Interaction Overview | Behavioral | No | Too complex; split into multiple sequence diagrams |
| Composite Structure | Structural | No | Academic; rarely seen outside UML tools |
| Profile Diagram | Structural | No | UML tooling extension — not for engineering communication |
1. Class Diagram: Document Your API, Not Your Implementation
Class diagrams are most valuable for documenting the public interface of a module or library — what other developers need to use it, not how it's implemented internally. A class diagram that shows every private field and helper method is noise; one that shows public methods, constructor parameters, and key relationships is signal.
classDiagram
class PaymentService {
<<interface>>
+createCheckoutSession(userId, plan) CheckoutSession
+createPortalSession(userId) PortalSession
+handleWebhook(payload, signature) void
}
class StripePaymentService {
-stripeClient StripeClient
-userRepo UserRepository
+createCheckoutSession(userId, plan) CheckoutSession
+createPortalSession(userId) PortalSession
+handleWebhook(payload, signature) void
}
class CheckoutSession {
+String sessionId
+String url
+String plan
+Instant expiresAt
}
class SubscriptionPlan {
<<enumeration>>
PLUS_MONTHLY
PLUS_YEARLY
PRO_MONTHLY
PRO_YEARLY
}
PaymentService <|.. StripePaymentService : implements
StripePaymentService ..> CheckoutSession : creates
StripePaymentService ..> SubscriptionPlan : usesRelationship notation: <|-- = inheritance/extends, <|.. = implements interface, --> = association (has-a), ..> = dependency (uses), *-- = composition (owns), o-- = aggregation (part of).
2. Sequence Diagram: The Backend Engineer's Essential Tool
If there's one diagram type every backend engineer should know deeply, it's the sequence diagram. It shows time-ordered message exchanges between system components — perfect for documenting API flows, auth handshakes, and microservice choreography.
Only draw arrows that cross a process boundary (different service, different machine, different database). Never draw internal function calls within the same service. This keeps diagrams readable and meaningful.
sequenceDiagram
autonumber
participant Client
participant Gateway as API Gateway
participant Order as Order Service
participant Inventory as Inventory Service
participant Payment as Payment Service
participant Notify as Notification Service
Client->>Gateway: POST /orders {items, paymentMethodId}
Gateway->>Order: createOrder(items, userId)
Order->>Inventory: reserveItems(items)
Inventory-->>Order: reservation confirmed
Order->>Payment: charge(amount, paymentMethodId)
Payment-->>Order: payment succeeded
par Async notifications
Order-)Notify: order.confirmed event
and Update inventory
Order-)Inventory: items.deducted event
end
Order-->>Gateway: 201 { orderId, status: "confirmed" }
Gateway-->>Client: 201 { orderId }3. Activity Diagram: Flowcharts with UML Semantics
Activity diagrams are UML's version of flowcharts, with richer notation for parallel flows, swimlanes, and object flows. They're best for business processes, algorithms, and any flow that involves parallel execution or cross-team responsibility.
When activity beats a plain flowchart: You need swimlanes to show which team/system owns each step, or you have parallel branches (fork/join) that Mermaid flowcharts express awkwardly.
Tool: PlantUML handles activity diagrams with swimlanes better than Mermaid. For simpler flows without swimlanes, Mermaid's flowchart is sufficient.
@startuml
|Customer|
start
:Submit return request;
:Pack item for return;
|Warehouse|
:Receive returned item;
:Inspect condition;
if (item undamaged?) then (yes)
:Restock item;
|Finance|
:Process refund;
|Customer|
:Receive refund notification;
else (no)
:Flag for review;
|Customer Service|
:Contact customer;
:Offer partial refund or replacement;
endif
stop
@enduml4. State Machine Diagram: Model Entity Lifecycles
State machine diagrams are essential when an entity has a defined lifecycle with named states and explicit transition triggers. Orders, subscriptions, tasks, and payments all benefit from this treatment — it makes the lifecycle explicit and prevents invalid state transitions from being coded.
stateDiagram-v2
[*] --> Draft : user creates task
Draft --> Open : assignee set
Draft --> Deleted : user deletes
Open --> InProgress : assignee starts work
Open --> Blocked : dependency flagged
Open --> Cancelled : PM cancels
InProgress --> InReview : PR submitted
InProgress --> Blocked : blocker found
Blocked --> Open : blocker resolved
Blocked --> Cancelled : PM cancels
InReview --> Done : approved and merged
InReview --> InProgress : changes requested
Done --> [*]
Deleted --> [*]
Cancelled --> [*]The diagram above immediately reveals design decisions: Can a Draft task be deleted? (Yes.) Can an InProgress task be cancelled? (No — it must go through Blocked or InReview first.) These constraints come out clearly in a state diagram but are buried in code.
5. Use Case Diagram: Requirements Gathering, Not Design
Use case diagrams have a narrow but valuable role: capturing what a system should do from a user's perspective, before any technical decisions are made. They're a communication tool for requirements, not an architecture or design tool.
The key mistake: Using use case diagrams too late (after design is done) or too deep (showing technical implementation details). Keep them at the level of "what the user can accomplish", not "how the system works".
@startuml
left to right direction
actor Developer as Dev
actor "Admin" as Admin
actor "Stripe" as Stripe <<external>>
rectangle "Tools-Hut" {
usecase "Use any tool anonymously" as UC1
usecase "Sign in / Register" as UC2
usecase "Manage profile" as UC3
usecase "Upgrade to Plus/Pro" as UC4
usecase "Process payment" as UC5
usecase "View audit logs" as UC6
usecase "Manage users" as UC7
}
Dev --> UC1
Dev --> UC2
Dev --> UC3
Dev --> UC4
UC4 ..> UC5 : <<include>>
Stripe --> UC5
Admin --> UC6
Admin --> UC7
@enduml6. Component Diagram: Mostly Replaced by C4 L2
UML component diagrams show the major components of a system and their provided/required interfaces. In practice, the C4 Level 2 container diagram communicates the same architectural information more clearly, with less formalism. If your team already uses C4, you don't need UML component diagrams.
Where component diagrams still earn their keep: documenting a complex library's internal modules and their dependency graph, particularly when the library has multiple extension points (provided interfaces) that external code plugs into.
Tools for UML in Practice
| Tool | Best UML Types | Approach | IDE Integration |
|---|---|---|---|
| Mermaid | Class, Sequence, State, ER | Code | VS Code extension |
| PlantUML | All 14 types, Activity with swimlanes | Code | IntelliJ, VS Code |
| IntelliJ IDEA Ultimate | Class diagrams (generated) | Auto-generated | Native |
| draw.io | Any — visual drawing | Visual | VS Code extension |