PlantUML object diagrams: runtime snapshots

puml.online

The object diagram is the less-talked-about sibling of the class diagram — but for debugging, doc, and live demos it earns its keep. It’s the class diagram’s “snapshot right now.”

One-line definition

An object diagram shows the instances (objects) in the system at a particular moment in time and the links between them. A class diagram says “what types exist”; an object diagram says “what instances exist right now and how they’re linked.”

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
@startuml
object "User instance" as user1 {
id = 1024
name = "Alice"
email = "alice@example.com"
}

object "Order instance" as order1 {
id = "ORD-2026-001"
status = "PAID"
total = 299.0
}

object "Product instance" as product1 {
id = "P-001"
name = "PlantUML intro"
price = 49.0
}

object "Product instance" as product2 {
id = "P-002"
name = "PlantUML templates"
price = 99.0
}

user1 --> order1 : placed
order1 --> product1 : contains
order1 --> product2 : contains
order1 -- "200.0" : calc 1
order1 -- "99.0" : calc 2

note right of order1
A snapshot of state
from production data
end note
@enduml

Element cheat sheet

Element Keyword Render
Instance object "name" as alias Rectangle; class name underlined
Field values key = "value" Inside the box
Inter-instance reference --> Solid + label
Multiple references --> "label1" then --> with another label Stack two arrows
Annotation note right of Folded-corner note

Four canonical uses

1. Show what an object looks like at a state

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@startuml

object "Cart instance" as cart1 {
customerId = 1024
couponCode = null
total = 0.0
}

object "Line item A" as item1 {
productId = "P-001"
quantity = 2
lineTotal = 98.0
}

object "Line item B" as item2 {
productId = "P-002"
quantity = 1
lineTotal = 99.0
}

cart1 --> item1
cart1 --> item2

@enduml

Easier to read than dumping raw toString().

2. Demonstrate object relationships during a flow

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
@startuml

object "Guest browser" as browser {
cookie = null
session = null
}

object "Request instance" as req1 {
method = "POST"
path = "/login"
body = "..."
}

object "Auth service instance" as auth1 {
dbConnection = "..."
cacheHit = false
}

object "User data instance" as user {
id = 1024
email = "alice@example.com"
failedAttempts = 0
}

object "Audit log instance" as audit {
eventType = "LOGIN_ATTEMPT"
}

browser --> req1 : sends
req1 --> auth1 : calls
auth1 --> user : reads
auth1 --> audit : writes

@enduml

3. State-of-pattern in design-pattern talks

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@startuml

object "Concrete subject" as concreteSubject {
state = 42
}

object "Observer A" as obs1 {
name = "Logger"
}

object "Observer B" as obs2 {
name = "Metrics"
}

concreteSubject -> obs1 : holds ref
concreteSubject -> obs2 : holds ref

note right of concreteSubject
Observer pattern:
subject maintains a list of observers
notifies all on state change
end note

@enduml

4. Describe a specific configuration or migration step

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@startuml

object "Kafka cluster config" as kafkaConfig {
brokers = "kafka-0:9092,kafka-1:9092"
topicPrefix = "puml-events"
partitionCount = 6
replicationFactor = 3
}

object "Consumer group A" as cgA {
groupId = "user-events-consumer"
consumerCount = 3
}

object "Consumer group B" as cgB {
groupId = "audit-events-consumer"
consumerCount = 1
}

kafkaConfig --> cgA : active
kafkaConfig --> cgB : active

@enduml

Real example: debugging inconsistent order state

Dump a real production state from the bug tracker:

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
@startuml

object "Order A" as oA {
id = "ORD-2026-001"
status = "PAID"
paidAt = "2026-07-29 14:00"
customerId = 1024
}

object "Order B" as oB {
id = "ORD-2026-002"
status = "PROCESSING"
customerId = 1024
}

object "User A" as uA {
id = 1024
email = "alice@example.com"
vip = true
}

object "Refund request X" as rX {
id = "REF-001"
orderId = "ORD-2026-001"
status = "PENDING_APPROVAL"
amount = 299.0
}

oA --> uA : belongs_to
oB --> uA : belongs_to
rX --> oA : references

note right of rX
Key points:
- Refund X references Order A
- Order A status is PAID (not REFUNDED)
- Until REFUNDED is set, rX stays PENDING_APPROVAL
- This is a legitimate intermediate state
end note

@enduml

Such an image in an issue comment is worth a thousand words — and easier than reading a hundred-line System.out.println.

Object vs class

Dimension Class diagram Object diagram
Depicts Relationships between types Current instances + their links
Keyword class object
Fields Type signatures Actual values
Relations Static dependencies Runtime references
Use Design / doc Debug / demo
Quantity One per type One per moment (each may differ)

Use them together: class diagram first for “structure”, object diagram second for “what that looks like right now.”

Anti-patterns

1. Putting type info into object diagrams

1
2
3
4
object "User instance" {
id: Long // ❌ that's class-diagram content
name: String
}

Right form — actual values, not types:

1
2
3
4
object "User instance" {
id = 1024
name = "Alice"
}

2. Too many objects in one picture

Object diagrams capture one moment. Past 10 objects, split into multiple diagrams.

  • Title: PlantUML object diagrams: runtime snapshots
  • Author: puml.online
  • Created at : 2026-07-29 15:30:00
  • Updated at : 2026-08-14 21:34:29
  • Link: https://puml.online/blog/plantuml-object-diagram-en/
  • License: This work is licensed under CC BY-NC-SA 4.0.