Graphviz uses DOT to describe graphs and lets its layout engine place the nodes. It is a dependable choice for generated diagrams and dense relationship maps.
DOT grammar, IDs, statements, and comments
A DOT file is a graph or digraph containing node, edge, attribute, assignment, and subgraph statements.
// Line comment
/* Block comment */
strict digraph G {
graph [rankdir=LR];
A; B;
A -> B;
label = "Workflow";
}- Use digraph with -> for directed edges and graph with -- for undirected edges.
- strict prevents duplicate edges in the same graph.
- DOT statements are node, edge, attribute, assignment, and subgraph statements.
- IDs can be bare words, numerals, quoted strings, or HTML strings; use semicolons or new lines between statements.
Directed and undirected graphs
Use digraph and -> when direction matters; use graph and -- when it does not.
digraph workflow {
rankdir=LR;
start [label="Start"];
review [shape=diamond, label="Review?"];
done [shape=box, label="Published"];
start -> review;
review -> done [label="approved"];
}- rankdir=LR lays out a directed graph left to right.
- Node IDs are identifiers; label is what a reader sees.
- Use [label="..."] on nodes and edges.
Defaults and shapes
Set shared defaults once to make generated source shorter and more consistent.
digraph services {
node [shape=box, style="rounded,filled", fillcolor="#F5F3FF", color="#635BFF"];
edge [color="#667085", fontcolor="#475467"];
api [label="API"];
jobs [shape=cylinder, label="Job store"];
api -> jobs [label="enqueue"];
}- Common shapes include box, ellipse, oval, circle, point, diamond, cylinder, folder, component, tab, note, and record.
- node, edge, and graph set defaults for what follows; attribute lists can be chained.
- Quote attribute values containing commas or spaces; HTML-like labels use angle brackets.
Clusters and groups
A subgraph named cluster_* draws a visible grouping boundary.
digraph deployment {
compound=true;
subgraph cluster_app {
label="Application";
color="#C9C5FF";
api; worker;
}
subgraph cluster_data {
label="Data";
color="#B8E8D0";
db [shape=cylinder];
}
api -> db;
worker -> db;
}- Only cluster_ prefixes receive a cluster boundary.
- Use subgraphs to communicate a deployment or ownership boundary.
- Use compound=true when edges need to target a cluster boundary.
Choose the layout engine
The same DOT source can benefit from different layout engines.
dot -Tsvg architecture.dot -o architecture.svg
neato -Tpng network.dot -o network.png
fdp -Tsvg relationships.dot -o relationships.svg- dot: hierarchical, directed workflows.
- neato: spring model for general networks.
- fdp: force-directed layouts for larger undirected graphs.
Edge control, ports, ranks, and HTML labels
DOT can describe dense technical relationships with ports, constraints, custom arrowheads, and table-like nodes.
digraph detail {
rankdir=LR;
node [shape=plain];
api [label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD PORT="in">API</TD></TR>
<TR><TD PORT="out">render</TD></TR>
</TABLE>
>];
worker [shape=box];
api:out:e -> worker:w [label="job", arrowhead=vee];
{ rank=same; api; worker }
}- Attach ports with node:port:compass; compass points include n, ne, e, se, s, sw, w, and nw.
- Important edge attributes: label, headlabel, taillabel, color, style, penwidth, arrowhead, and constraint.
- Use HTML-like labels for tables; use records only when the simpler field syntax is sufficient.
Attributes and the full engine family
Attributes apply to graph, node, edge, or cluster scope. Choose the renderer based on the structure you need to reveal.
dot -Tsvg graph.dot -o graph.svg
dot -Tpng graph.dot -o graph.png
neato -Tsvg network.dot -o network.svg
sfdp -Tsvg large-network.dot -o large-network.svg
circo -Tsvg cycle.dot -o cycle.svg
twopi -Tsvg radial.dot -o radial.svg- Graph: rankdir, bgcolor, pad, margin, splines, nodesep, ranksep, and label.
- Node: shape, label, width, height, fixedsize, fontname, fontsize, URL, tooltip, and style.
- dot is hierarchical; neato/fdp/sfdp are force-directed; circo is circular; twopi is radial; osage and patchwork target clustered layouts.
Keep it useful
Three working rules
- Put layout attributes near the top so intent is easy to see.
- Use clusters to explain boundaries, not to decorate the page.
- Generated DOT stays easier to debug when IDs remain predictable.
Official sources
Further reading
Use the official references for version-specific details, niche syntax, and advanced renderer options.