See it as a diagram
Everything below, as a diagram you can edit. Describe yours and see it in seconds.
No account needed · Editable canvas, not a picture
Strategy 1: diagram source in git, next to the code
Committing the diagram source, Mermaid text, draw.io XML, into the repo buys the full git feature set: the diagram branches with the code, a PR that adds a service can update the picture in the same atomic commit, and checking out an old tag shows the diagram as it stood then. For teams already running docs-as-code, this is the default instinct.
The cost is the merge conflict problem, and it is worse than for code. Text-based diagram formats fall into two camps. Hand-positioned formats like draw.io XML store an mxGraphModel full of x and y coordinates, so two people nudging different boxes produce a conflict no human can resolve by reading the diff; the practical fix is treating the file as binary and re-doing one side's change. Generated-layout formats like Mermaid diff cleanly as text, but the rendered layout can reshuffle when unrelated nodes are added, so a reviewer approving the text diff has not necessarily seen what readers will see. The wider tradeoffs of the text-based approach are covered in docs as code for diagrams.
Strategy 2: always-latest, with history in the tool
One canonical diagram lives in the diagramming tool, every README and wiki page embeds it by URL, and edit history stays in the tool rather than in git. This maximizes truth-in-the-moment: there is exactly one current picture, and an edit propagates to every page embedding it. A Datadef diagram embedded via its image URL behaves this way, serving the current render with a five minute cache lifetime so edits appear everywhere within minutes; the embed exists for projects shared public.
The strategy gives up per-branch variants by design: a reader on the v2.3 maintenance branch sees the v3 diagram. For most internal documentation that is the right trade, current beats historically precise. It stops being right the day someone needs the old picture with guarantees, which is the next strategy's job. This is the single source of truth approach applied to diagrams.
Strategy 3: frozen exports per release
Some diagrams must be provable at a point in time. PCI DSS expects a current network diagram and assessors sample historical evidence; SOC 2 change-management reviews ask what the system looked like when a control operated; incident postmortems want the topology at incident time, not at writing time. For all three, a live diagram is the wrong artifact, because live means retroactively different.
The mechanics are one CI job: on every release, export the current diagram to a file named for the tag and commit it to an append-only directory. Frozen copies are exports, deliberately, PNGs that no one can quietly edit, with the live diagram remaining the editable source.
name: freeze-architecture-diagram
on:
release:
types: [published]
jobs:
snapshot:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Save a point-in-time export of the live diagram
run: |
mkdir -p docs/architecture/releases
curl -fsSL -o "docs/architecture/releases/${{ github.event.release.tag_name }}.png" \
"https://datadef.io/api/embed/my-platform-a1b2c3d4?format=png&width=2400&height=1400"
- name: Commit the frozen export
run: |
git config user.name "release-bot"
git config user.email "[email protected]"
git add docs/architecture/releases
git commit -m "docs: freeze architecture diagram at ${{ github.event.release.tag_name }}"
git pushChoosing, and the hybrid most teams land on
Choose by who reads old versions. Nobody reads them: always-latest, alone. Engineers read them, diagrams reviewed alongside code on branches: source in git, and accept the merge cost. Auditors read them: always-latest plus frozen exports per release, which is the hybrid most teams end up running because it splits the two jobs cleanly. The live diagram answers what is, the tagged exports answer what was, and neither is asked to fake the other.
The hybrid also dissolves the merge conflict problem for the live half: the canonical diagram is edited in one place rather than merged across branches, and the per-release history accumulates in git where auditors and postmortems can reach it with a checkout.
Decision in one line
Keeping the live half actually live
Every strategy above assumes someone updates the diagram when the architecture changes, and that assumption is where diagram versioning usually fails in practice, a perfect version history of a stale diagram is still a stale diagram. The update becomes cheap when an agent can do it: connected to Datadef's MCP server, an agent redraws the diagram from what the repo contains, on request or as a pipeline step after merges. Datadef does not watch the repository itself; the trigger belongs to your process, and when to regenerate is worth deciding explicitly. Schema diagrams have their own version-tracking pattern against migrations, covered in keeping ER diagrams in sync with the database.
FAQ
Should architecture diagrams be version controlled?
How do I handle merge conflicts in draw.io files?
Do auditors need old versions of architecture diagrams?
Can one diagram serve multiple code versions or branches?
Where should diagram edit history live if not in git?