Diagrams

Your architecture diagram belongs in the repository

TALA went open source last week, so we are using the occasion to explain why every diagram we hand a client is a text file under version control, and why the ones that are not are always out of date.

On 7 September the Terrastruct team open-sourced TALA, the layout engine for D2. It was the one paid piece of an otherwise free tool; it is now MPL-2.0, the same licence as D2 itself, bundled in D2 v0.9.0 and selected with --layout=tala. The discussion on Hacker News ran to a few hundred points, mostly people who had wanted exactly this.

We have used D2 internally for about two years. Our reasons have less to do with diagrams than with the argument we already make about firewalls and servers.

Diagrams drift

Every estate we inherit has an architecture diagram. It is a PNG in a wiki, or a .drawio file somebody exported once, or a Visio document that only opens on one person’s laptop. It is always wrong, and it is wrong in a specific way: it describes the system as it was on the day somebody had time to draw it.

Nobody updates it, because updating it means opening a drawing program, finding the right box, moving the arrows so they do not overlap, exporting, and uploading: fifteen minutes of fiddling for a change that took one line of configuration, so nobody does it.

A diagram that is a text file fails differently. It goes stale in the same commit that changes the system, where a reviewer can see it, so either nixos-rebuild and the diagram move together or the difference shows up in the pull request.

What it looks like

Here is a typical example of what we draw: a client’s laptop reaching a host over WireGuard, and that host shipping backups to a second country:

direction: right

goteborg: Göteborg {
  laptop: ThinkPad
}

sto: you.sto — Stockholm {
  nginx
  redmine: Redmine
  pg: PostgreSQL {shape: cylinder}
  nginx -> redmine -> pg
}

cra: craiova.cra — Romania {
  backup: Backup target {shape: cylinder}
}

goteborg.laptop -> sto.nginx: wg0
sto.pg -> cra.backup: nightly, encrypted

That is the entire source. It produces this:

A diagram: a ThinkPad in Göteborg connects over wg0 to a Stockholm host running nginx, Redmine and PostgreSQL, which ships nightly encrypted backups to a target in Craiova.

Nineteen lines, and D2 handles the layout. Add a second host and the arrows rearrange themselves.

Two more examples

A migration, before and beside after. This is the diagram that does the most work in a proposal, because the left side is what the client is paying for now:

before: Before — eu-west-1 {
  alb: Application Load Balancer
  ecs: ECS tasks
  rds: RDS Postgres {shape: cylinder}
  s3: S3 {shape: cylinder}
  alb -> ecs -> rds
  ecs -> s3
}

after: After — Falkenstein + Stockholm {
  pf: pf
  nixos: NixOS host
  pg: PostgreSQL {shape: cylinder}
  minio: MinIO {shape: cylinder}
  pf -> nixos -> pg
  nixos -> minio
}

before -> after: one service a week, rehearsed rollback

An estate, with the evidence attached. NIS2 Article 21(2)(a) wants risk analysis and security policies written down. An assessor does not want a picture; they want to know the picture is generated from the same repository as the thing it describes:

net: Perimeter {
  pf: pf ruleset
  wg: WireGuard mesh
}

hosts: Hosts declared in one repository {
  a: you.sto
  b: kalmar.sto
  c: craiova.cra
}

net.pf -> hosts.a
net.pf -> hosts.b
net.wg -> hosts.c: site-to-site
hosts -> audit: nixos-rebuild --target-host
audit: "Every change is a commit" {shape: document}

All three compile. We checked them against d2 before publishing, as we would with any example we put on the internet.

Where it is weaker

The announcement is unusually open about TALA’s limits, and we would rather repeat them than bury them. It uses randomness, so a small change to the source can produce a noticeably different layout. It handles directed acyclic graphs worse than Dagre or ELK, and most infrastructure diagrams are exactly that. It also scales nonlinearly, so a large diagram gets slow.

That matches our experience. We reach for --layout=elk for anything that is mostly a flow, and TALA for the messier network pictures where its freedom to move things around helps. Switching is one flag.

The broader caution is that automatic layout does not rescue a diagram that is trying to show too much. If your picture has sixty nodes, the problem is the picture: D2 will lay out sixty nodes tidily, and nobody will read them.

When we would not use it

If a diagram is drawn once for a pitch and thrown away, use whatever is fastest; version control does not help something that will never have a second version. If your team collaborates on diagrams visually, in real time, a canvas tool is a better fit and we would say so.

If the diagram is not generated from, or reviewed alongside, the thing it describes, it does not matter which tool drew it: it will be wrong within a quarter. That was true before last week’s licence change too.

Nästa steg

Tell us what you are running.
We will tell you what it should be.

A first conversation costs nothing and takes forty minutes. You will leave it with our opinion of your stack, which is occasionally that you should change nothing at all.