Table Relationship Diagrams with Graphviz

I recently found myself looking for a modern tool to diagram relationships between tables of data. When I came up short, I used a very old tool instead.

Specifically, I was documenting how a software system accepts data from a third party, mapping fields from external records to an internal message type:

Basically, I wanted to draw arrows between rows of tables. But I was very particular about how!


The diagrams I was producing describe software. Like software, they had to be easy to change. In particular, I sought the following properties:

  1. Arrows attach to rows of the table.
    I do not want to manually position the ends of arrows, ever.
  2. Table entries can be edited and reordered without breaking links.
  3. It works with a text-based source format.
    I intended to check these files into source control, so they needed to diff and merge nicely.

Do any tools come to mind? I searched around for a while before dusting off an old one:


Graphviz is a collection of utilities and libraries for generating diagrams from a language called DOT. Even if you haven’t used it directly, you’ve probably seen Graphviz output before, perhaps in an academic paper or a database entity relationship diagram.

I was familiar with its flowchart-like diagrams of bubbles, boxes, and diamonds, but I thought I’d check to see if it could be coaxed into producing connected tables. I fiddled with a few examples from the


graphviz_gallery, read through some documentation, and finally found just the ticket.


A relatively recent addition to Graphviz (circa 2003!) is the “HTML-Like Label.” This carefully-named feature lets you specify node appearance using familiar HTML `

syntax, with the addition of named <em>ports</em> where you can connect arrows.The documentation scared me a little when it warned that the syntax is <em>"not really HTML,"</em> but then they made up for it by providing a formal grammar of exactly what is accepted.Here's the source for the image at the top of the post:<code class="language-commandline">digraph {
graph [pad="0.5", nodesep="0.5", ranksep="2"];
node [shape=plain]
Foo [label=&lt;
&lt;table border="0" cellborder="1" cellspacing="0"&gt;
&lt;tr&gt;&lt;td&gt;&lt;i&gt;Input Foo&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td port="1"&gt;one&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td port="2"&gt;two&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td port="3"&gt;three&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td port="4"&gt;four&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td port="5"&gt;five&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td port="6"&gt;six&lt;/td&gt;&lt;/tr&gt;
Bar [label=&lt;
&lt;table border="0" cellborder="1" cellspacing="0"&gt;
&lt;tr&gt;&lt;td&gt;&lt;i&gt;Input Bar&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td port="7"&gt;seven&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td port="8"&gt;eight&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td port="9"&gt;nine&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td port="10"&gt;ten&lt;/td&gt;&lt;/tr&gt;
Baz [label=&lt;
&lt;table border="0" cellborder="1" cellspacing="0"&gt;
&lt;tr&gt;&lt;td&gt;&lt;i&gt;Output Baz&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td port="a"&gt;alpha&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td port="b"&gt;bravo&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td port="c"&gt;charlie&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td port="d"&gt;delta&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td port="e"&gt;echo&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td port="f"&gt;foxtrot&lt;/td&gt;&lt;/tr&gt;
Foo:2 -&gt; Baz:a;
Foo:3 -&gt; Baz:e;
Foo:6 -&gt; Baz:b;
Bar:7 -&gt; Baz:d;
Bar:9 -&gt; Baz:f;

It’s not beautiful, but it sure beats dragging endpoints around with a mouse.


The primary tool in the Graphviz suite is dot, which reads a source file and emits one of several output types. I’m producing SVG like this:dot input.gv -Tsvg -o out.svgNext, wanting to iterate quickly, I set up a watcher to automatically recompile when the input file changes. (Thanks, Alex, for introducing me to entr):ls *.gv |entr dot /_ -Tsvg -o out.svg None of my SVG-viewing applications pick up the file change automatically, but it’s not too bad to tab over and refresh. One last stop before I start writing: syntax highlighting. I searched Visual Studio Code’s available extensions:

I wasn’t surprised at all by the first result, which provides syntax highlighting for this arcane language. I was surprised, however, by the second, which previews the output right there in the editor, as you type!

So there I was, nearly done cobbling together my own tooling to work on Graphviz diagrams, when I found a much smoother experience presented on a silver platter. A different developer contributed each piece of the puzzle, and I discovered and installed them in about three seconds. This is what I love about large-community projects like VS Code.

Old Software

It’s obviously not perfect, but Graphviz satisfied my criteria. When I skimmed through modern diagramming tools, nothing even came close! Do you know of any other tools that can do this kind of thing? According to Wikipedia, Graphviz is 26 years old. This puts it right up there with venerable command-line utilities like curl and ImageMagick. What ancient software do you keep coming back to?

  • Uwe says:

    Nice article and example. I am still a heavy user of LaTeX, which might be a bit arcane as well. But nothing I have tried so far get me results of the same quality.

  • Tom Cooper says:

    Thanks, very helpful

    I still use SPICE circuit simulator, still has some fortran code.

  • Comments are closed.