Data-driven PlantUML — generating diagrams from a database or API
Use PlantUML + a few lines of script, so your diagrams always follow reality.
Why data-driven?
The most common embarrassment with business diagrams:
- A column gets added to the DB; the ER diagram forgets to follow, and people join on memory.
- A service dependency changes; the deployment diagram is the one from three months ago.
- A teammate moves to a new team; the org chart still shows them on the old one.
- Every week someone manually redraws — miss one week and someone cites the wrong link.
Idea: the “facts” of a diagram live in code / DB / API docs / config — and those are the source of truth. So let the diagram be generated from that truth. That approach is called a data-driven diagram.
A concrete example: service dependency diagram
Suppose we have a k8s namespace where every Deployment has a label app=xxx. We want to draw app=a → app=b dependencies.
Step 1: extract data from kubectl
1 | kubectl get deployments -n prod -o json | jq ' |
Output looks like:
1 | [ |
Step 2: a Node script that emits puml
1 | // scripts/gen-deps.js |
Step 3: render + commit
1 | node scripts/gen-deps.js |
Result: every CI run, the diagram is up to date.
A few common “data source → diagram” templates
| Scenario | Data source | Output |
|---|---|---|
| Service deps | k8s labels / apollo / consul | component / package |
| DB ER | pg_dump --schema-only |
entity / class |
| State machine | XState / status table | state diagram |
| Approval flow | Lark / Worktile / Jira | activity diagram |
| Org chart | HR system / LDAP | class diagram |
| API contract | OpenAPI / Protobuf | class diagram |
A pure-bash DB ER extractor
1 | pg_dump --schema-only -t "*" mydb \ |
Integration tips
1. Output small data, not the raw DB
Compress SQL / kubectl / API output into flat JSON (like the deps.json above). The puml generator only reads JSON, never the DB.
Benefits:
- The puml generator has zero dependencies, is pure text, easy to PR-review.
- When the data source changes (e.g. swapping DB), only the data extractor changes — puml stays put.
2. Keep the puml generator in the repo
Commit scripts/gen-*.puml.js alongside package.json. Put a one-liner in README:
This diagram is auto-generated from live data. To change it, change the data source (k8s labels / DB schema).
3. Enforce render-verify in CI
After every build:
1 | node scripts/gen-deps.js |
If the data source changed but the puml script didn’t, the build fails — alerting humans to refresh the diagram.
Pitfalls I’ve hit
- Cycles:
A → B → Amakes Graphviz error. Addif seen.has(a+b) continueto your generator. - Too many nodes: >100 components make SVG stall. Split into
packageblocks, paginate by layer. - CJK tofu: PlantUML SVG inlined on GitHub renders CJK as squares. Add
skinparam defaultFontName "Noto Sans CJK SC"at the top of puml. - Sensitive data: dependency graphs from prod can include internal hostnames. Anonymise (hash or codename) before writing puml.
Recap
- Diagrams should follow the truth — whoever owns the truth owns the source.
- Split extract and generate-puml into separate scripts.
- CI’s
git diff --exit-codemakes “diagram not updated” a compile error.
Next
- Title: Data-driven PlantUML — generating diagrams from a database or API
- Author: puml.online
- Created at : 2026-07-28 16:36:00
- Updated at : 2026-08-14 21:34:29
- Link: https://puml.online/blog/plantuml-data-driven-en/
- License: This work is licensed under CC BY-NC-SA 4.0.