How to Draw a Power Topology Diagram from Utility to Server
Build a power topology diagram that stays readable: the node and edge schema, a TSV worklist, validation checks, and a Graphviz script that renders the same graph every time.

On this page
A power topology diagram fails in two opposite ways. The first is a drawing that looks beautiful but cannot be regenerated, so it becomes a historical artifact the week after it is published. The second is a complete graph of every outlet and port, which is technically accurate and practically unreadable. The useful version sits between them: a diagram that shows the electrical path from source to load, labels the breaker on each feed, and can be rebuilt from records when something changes.
This procedure uses a plain node file, a plain edge file, and Graphviz to render the diagram. The files are easy to review in a pull request, the validation checks catch endpoints that do not exist, and the DOT source can be diffed between runs. The same schema works whether you are drawing one rack, one panel, or one site, and it maps cleanly to the records a power distribution inventory already holds.
Decide what the diagram must answer
A power topology can serve three different purposes, and each one needs a different level of detail. A capacity diagram needs sources, panels, feeds, and the load attached to each feed. A failure analysis diagram needs the same path plus the redundancy groups and source links, so a failure can be traced through the chain. A physical routing diagram needs cable paths, rack positions, and outlet numbers, which is a different drawing with a different audience.
Start with one purpose. For most teams, the first useful diagram is the failure analysis view: which source feeds which panel, which breaker protects which feed, and which rack or device is downstream. It answers the question that starts every maintenance window, which is what will lose power if I open this breaker. Capacity and physical routing can be added later without changing the basic node schema.
The scope matters as much as the purpose. One site, one source chain, and one or two panels is a good first graph. A complete site with every rack and outlet will be dense even when the data is perfect. Keep the identifiers stable and render the larger diagram by combining smaller files later, rather than trying to solve the whole site in the first pass.
Model the chain as nodes and edges
The graph has four node types: source, panel, feed, and device. It has three edge types: a source link from a source to another source or a panel, a panel to feed edge that carries the breaker position, and a feed to device edge that represents the physical cable to an inlet or rack.
The breaker is deliberately an edge label rather than a node. A breaker is a protective device inside a panel, and its position is the detail a technician needs when isolating a feed. Making every breaker a node usually doubles the node count and pushes the labels into each other. If you need to track breaker inspection status separately, add a breaker node later and keep the panel to feed edge as the parent relationship.
The device node can represent a rack, a PDU, or a server, depending on the question. For a first diagram, use one device node per rack and put the rack name in the label. When you need to show A/B inlets, replace the rack node with two inlet nodes and connect each feed to the correct inlet. The graph should reflect the level of detail you can actually maintain.
Build the node and edge files
Use two tab separated files. The node file has id, type, label, and status. The edge file has from, to, and label. Keep the IDs short and stable, and put the human readable name in the label. The IDs are what make the graph reproducible, so do not use the label as the key.
Create the example files with printf so the tabs are written literally. A block copied from a rendered web page may contain spaces, and the generator expects tabs.
printf 'id\ttype\tlabel\tstatus\nsrc-utility\tsource\tUtility feed\tactive\nsrc-ups-a\tsource\tUPS A\tactive\npnl-a3\tpanel\tPNL A3\tactive\nfeed-r07-a\tfeed\tR07-A\tactive\ndev-web\tdevice\tweb-prod-01\tactive\n' > nodes.tsv
printf 'from\tto\tlabel\nsrc-utility\tsrc-ups-a\tutility\nsrc-ups-a\tpnl-a3\tinput A\npnl-a3\tfeed-r07-a\tbreaker 42\nfeed-r07-a\tdev-web\tC13\n' > edges.tsv
$ column -t -s "$(printf '\t')" nodes.tsv
id type label status
src-utility source Utility feed active
src-ups-a source UPS A active
pnl-a3 panel PNL A3 active
feed-r07-a feed R07-A active
dev-web device web-prod-01 active
$ column -t -s "$(printf '\t')" edges.tsv
from to label
src-utility src-ups-a utility
src-ups-a pnl-a3 input A
pnl-a3 feed-r07-a breaker 42
feed-r07-a dev-web C13
The example is intentionally small. It contains one source chain, one panel, one feed, and one device. A second feed for the same rack would add another feed node and another edge from the same panel or from a different panel. An A/B pair would add a second source chain, a second panel, and a second feed, with the rack or device node shared at the end.
Validate before drawing
The diagram is only as good as the edge list. Run the checks before you render, because a broken endpoint produces a graph that looks plausible and is wrong. The first two checks catch a wrong column count. The next two catch duplicate identifiers and duplicate edges. The last two compare every edge endpoint against the node list.
awk -F'\t' 'NR>1 && NF!=4 {print "nodes line " NR ": " NF " fields"}' nodes.tsv
awk -F'\t' 'NR>1 && NF!=3 {print "edges line " NR ": " NF " fields"}' edges.tsv
tail -n +2 nodes.tsv | cut -f1 | sort | uniq -d
tail -n +2 edges.tsv | sort | uniq -d
comm -23 \
<(tail -n +2 edges.tsv | cut -f1,2 | tr '\t' '\n' | sort -u) \
<(tail -n +2 nodes.tsv | cut -f1 | sort -u)
comm -13 \
<(tail -n +2 edges.tsv | cut -f1,2 | tr '\t' '\n' | sort -u) \
<(tail -n +2 nodes.tsv | cut -f1 | sort -u)
The first comm prints endpoints that appear in the edge file but not in the node file. The second prints nodes that never appear in the edge file, which is how orphan racks and disconnected sources show up. An empty output from all six checks is the condition for rendering, not a perfect guarantee that the records are correct.
Generate the Graphviz file
The generator reads both files in one awk pass. Run it from the directory that contains nodes.tsv and edges.tsv, because the script selects each file by its base name. The first line of each file is a header and is skipped. Source nodes get a different shape so the upstream side of the graph is obvious, and the edge labels carry the role, breaker position, and cable type.
cat > build-power-dot.awk <<'AWK'
BEGIN {
print "digraph power {";
print " rankdir=LR;";
print " node [shape=box, style=\"rounded,filled\", fontname=\"Helvetica\", fontsize=11, color=\"#52525b\", fontcolor=\"#e3e4e6\", fillcolor=\"#141617\"];";
print " edge [color=\"#71717a\", fontcolor=\"#a1a1aa\", fontname=\"Helvetica\", fontsize=10];";
}
FNR==1 { next }
FILENAME=="nodes.tsv" {
if ($2=="source") { shape="component"; color="#00CBAA"; }
else if ($2=="panel") { shape="box"; color="#38BDF8"; }
else if ($2=="feed") { shape="box"; color="#F59E0B"; }
else { shape="box"; color="#7B66FF"; }
printf " \"%s\" [label=\"%s\", shape=%s, color=\"%s\"];\n", $1, $3, shape, color;
next;
}
FILENAME=="edges.tsv" {
printf " \"%s\" -> \"%s\" [label=\"%s\"];\n", $1, $2, $3;
}
END { print "}"; }
AWK
awk -F'\t' -f build-power-dot.awk nodes.tsv edges.tsv > power.dot
The script assumes the labels do not contain double quotes. If a label does, normalize it before the render or escape it in the generator. It also assumes tab separated input with exactly the column order shown above. Check the field count first, because a space separated file will render as one long label rather than a graph.
Render and review the diagram
Render the DOT file with the layout direction enabled. The dot command produces a layered graph, which reads well for a power chain. Use SVG for review and PNG only when a ticket or a document requires a raster image.
dot -Tsvg power.dot -o power.svg
dot -Tpng -Gdpi=150 power.dot -o power.png
If dot is not installed, install Graphviz with your package manager before the first render. The command itself is standard and the output does not depend on a cloud service, which matters when the diagram contains site names and breaker positions.
Review the rendered graph against the records, not against memory. Every source should have an outgoing edge, every panel should have an incoming source link and at least one feed, and every feed should show a breaker position and a target. A device node with no incoming feed edge is either a device outside this scope or a missing connection. A feed node with no downstream edge is a feed that has not been assigned to a rack or endpoint.
Do not publish the first render until the edge labels are readable. The breaker position should be visible without hovering, and the A/B roles should be distinguishable in text as well as by color. If the graph becomes dense, split it by panel or by room rather than shrinking the font. A diagram nobody can read is not more accurate than a smaller one.
Make the diagram current
The diagram is a build artifact, so treat it like one. Keep nodes.tsv, edges.tsv, and the generator in version control. Regenerate after every panel change, feed move, or new rack, and compare the DOT output against the previous run. A diff in the edge labels is usually a cable or breaker change, and that is exactly the change you want to see before it reaches production.
A quarterly review is enough for a stable site, and a change triggered review is better for an active one. The validation commands are fast enough to run in a precommit hook or a small CI job. When the graph is generated from the same records that answer capacity and failure questions, the diagram stops being a separate documentation project and becomes another view of the inventory.
Obelinf’s power topology view renders the same four node types from the source, panel, feed, and device records, so teams that already keep those records do not need to maintain a second edge file by hand. For a site that is still on spreadsheets, the files in this procedure are a good intermediate step: they make the missing records visible before you commit to a tool.
Start with one site and one panel. Fill the node file, add the edges, run the checks, and render the graph. The first diagram does not need to be complete. It needs to be correct enough that the next change makes it better instead of starting over.
Frequently Asked Questions
What should a power topology diagram show?
Should a breaker be a node or an edge in a power diagram?
Why draw a power topology instead of a single line diagram?
How do you keep a power diagram from going stale?
What is the difference between a network topology and a power topology?
How many nodes should a power topology diagram have?
Stop reaching for a spreadsheet
Obelinf keeps every subnet, device, circuit, and rack in one live source of truth, with audit logs and a topology view. Free for personal use.
Related Articles

How to Document Power Sources, Panels, Breakers, and Feeds
A working procedure for building a power distribution record from source to rack: the order to create each record, the API calls, the fields that matter, and the checks that catch gaps.
Read more
What Is a Power Feed? Panels, Breakers, and Rack Power Explained
A plain explanation of power feeds, panels, breakers, circuits, and PDUs, with the fields to record, the capacity math, and a checklist you can use at the rack.
Read more
How to Prove A/B Power Redundancy in Practice
Use rack, feed, panel, and device power records to prove A/B redundancy: the commands, the failure domain counts, the common false positives, and a worked example.
Read more