Big PlantUML diagrams — subgraph, package, !include — staying fast past 1000 nodes
A big diagram looks clear to the reader, but the renderer pays the cost — 100 nodes is the watershed. This post distills how to keep big PlantUML diagrams readable and smooth to render.
The 100-node watershed
Empirically:
| Node count | State |
|---|---|
| <30 | Smooth (<200ms) |
| 30–80 | Occasional crowding (500ms–1s) |
| 80–150 | Borderline lag (1s–3s) |
| >150 | Graphviz stalls or crashes |
Core principle: start layering before 80 nodes (by responsibility), and must split once you cross 150.
First move: subgraph and package
package = named rectangle
1 | @startuml |
A package is a namespace with a border — visually clustering nodes.
subgraph = flexible grouping
1 | @startuml |
subgraph … end is Graphviz’s “cluster” — PlantUML supports it fully; you can colour via <<stereotype>>.
Second move: !include to split into multiple files
How to split
Split by module — but module boundaries must be clean:
1 | /docs/diagrams/ |
Pattern A: !include child diagrams
shared/styles.puml:
1 | !pragma layout: "elk" |
shared/nodes.puml (standard nodes via macros):
1 | !define SERVICE(name, label) rectangle "==label" <<service>> as name |
system.puml:
1 | @startuml system |
service/auth.puml:
1 | SERVICE(auth_service, "AuthService") |
Note: !include and render location
By default PlantUML searches relative to the current file plus the stdio include path. In the VS Code plugin, configure plantuml.includepaths; on the CLI use -I:
1 | plantuml -I docs/diagrams/shared -tsvg system.puml |
Third move: !pragma layout: “elk”
Graphviz’s dot algorithm is “hub-and-spoke” — when nodes pile up, they fight for the centre. ELK (Eclipse Layout Kernel) is a different algorithm, better for hierarchical architectures:
1 | @startuml |
Requires PlantUML ≥ 1.2024.x and an elk.js install:
1 | wget https://www.eclipse.org/elk/downloads/elk-0.7.2.js -O ~/plantuml/elk.js |
Empirically: a 150-node microservice architecture takes ~8s with dot, ~2s with elk — and elk produces clearer layering (defaults to data-flow direction).
Fourth move: tidy connections (!useVerticalIf alternative)
A tangled web of edges is another cause of slow render:
1 | ' Anti-pattern: 13 nodes randomly linked |
Fix: put nodes inside package / subgraph so Graphviz can see the spatial structure:
1 | package "Inputs" { |
Graphviz sees the clear package hierarchy and renders by cutting the layout at package boundaries — render time drops from ~12s to ~1.5s.
Fifth move: !theme
1 | !theme cyborg |
Render the whole big diagram in a unified theme — visual hierarchy comes from colour, not from cranking nodesep to 100+.
Sixth move: paginated rendering
Only useful in VuePress / Hexo / docs sites. After generating one diagram, split it with a cut/:
1 | <!-- A large diagram is auto-split by PlantUML into multiple pages, |
This is what plantuml-multipage does. After installing, {% plantuml %} auto-embeds a “Page 1/10” nav.
Performance optimization checklist
- Group nodes by business responsibility into
package - Cross-package edges are explicit (avoid fully bidirectional meshes)
- At >100 nodes,
!pragma layout: "elk" - Reuse via
!includeinstead of copy-paste - CJK via unified
skinparam defaultFontName - Big diagrams on local server mode (avoid plantuml.com cross-border)
- Use
plantuml-multipagefor “huge diagram” docs pages - When a complex sequence gets unwieldy as a component diagram, switch to sequence-diagram + state-machine diagrams as the natural decomposition
A real case: “our e-commerce mid-platform”
Old version: 300 nodes in one component diagram + 600 edges, 30+ seconds render — architecture peers gave up.
New version:
- Split into
core.puml/fulfillment.puml/marketing.puml/data.puml— 4 top-level diagrams - Each diagram
!includes its own sub-modules (30-50 nodes) - Each diagram opens with
!pragma layout: "elk"+ standardstyles.puml - Docs site embeds via
plantuml-multipage
Reading order:
1 | View core (top-level) |
Each diagram renders independently in 1-3 seconds; total reading time <8 seconds, an order of magnitude better than the previous single 30s.
Recap
- Big diagrams’ biggest bottleneck is Graphviz’s layout algorithm.
package+subgraph+!include+!pragma layout elkis the four-piece kit.- Splitting is more effective than optimizing: think about splitting past 80 nodes.
Next
- Embedding PlantUML in Hexo (server-side / client-side) (actual slug:
plantuml-render-from-hexo) - PlantUML sequence-diagram control flow — else / alt / opt / loop
- Title: Big PlantUML diagrams — subgraph, package, !include — staying fast past 1000 nodes
- Author: puml.online
- Created at : 2026-07-30 10:13:00
- Updated at : 2026-08-14 21:34:29
- Link: https://puml.online/blog/plantuml-large-diagram-en/
- License: This work is licensed under CC BY-NC-SA 4.0.