Glossary · Structure and dead code

What is a dependency graph?

A dependency graph is a directed graph in which each node is a unit of software, such as a file, module or package, and each edge means one unit depends on another. Package managers build one from declared libraries. Code analysis builds one from import statements. Either shows what breaks when something changes.

Last reviewed: November 2026

Also called Import graph, Module dependency graph, Code dependency graph

In depth Building a dependency graph for any codebase: how imports are parsed and resolved per language, then ranked and clustered.

How a dependency graph is measured

The graph itself is a list of edges. What you measure is its shape:

  • Fan-in and fan-out per node: incoming and outgoing edges.
  • Cycles: strongly connected components with more than one node, meaning a group in which every member can reach every other.
  • Centrality: PageRank scores a node highly when important nodes depend on it, and betweenness finds nodes that sit on many paths between others.
  • Communities: clustering algorithms such as Leiden group nodes that depend on each other more than on the rest, which often differs from the folder layout.

A small example:

FileImportsFan-outImported byFan-in
api.pyauth.py, db.py2none0
auth.pydb.py1api.py1
db.pynone0api.py, auth.py2

db.py is the load-bearing file. If db.py imported auth.py, the two would form a cycle.

A package graph (npm, pip, Cargo) comes from manifests and lock files and shows what you ship. A code graph comes from parsing imports and shows what the code uses.

Why a dependency graph matters

High fan-in files turn a bug into a system-wide failure, so they deserve more tests and review. Cycles make refactoring all-or-nothing. A node with no incoming edges is a dead code candidate. Communities that cut across folders show where the real module boundaries are, which feeds architecture views such as the C4 model. Function-level edges are a finer layer, the call graph.

How to measure a dependency graph yourself

  • JavaScript and TypeScript: madge --circular src/ lists cycles, madge --image graph.svg src/ draws the graph, and depcruise src (dependency-cruiser) adds rules such as "UI must not import data access".
  • Python: pydeps mypackage draws module dependencies.
  • Go: go mod graph prints module-level edges.
  • Rust: cargo tree prints the crate dependency tree.
  • Java: jdeps analyzes class and package dependencies.

Each is the right pick for a single-language repository, and dependency-cruiser is the better choice if you want to enforce import rules in CI. A repository with several languages has no single tool among these, which is the case repowise targets. See best dependency graph tools for monorepos.

How repowise measures the dependency graph

repowise parses every file with tree-sitter and resolves imports per language into one directed graph of file and symbol nodes. No LLM is involved, so the same code gives the same graph.

  • Algorithms: PageRank over the file tier, betweenness for bridges, strongly connected components for cycles, and Leiden clustering (Louvain as fallback, fixed seed). Co-change edges from git are excluded from centrality, so "changes alongside many files" is not mistaken for "many files depend on it".
  • Views: an explorable architecture map in the dashboard, C4 views, and repowise export --format structurizr for a Structurizr DSL model.
  • MCP: the graph feeds get_context, get_risk and get_dead_code. The get_dependency_path tool explains how two files connect; enable it with --tools +get_dependency_path.

How it is built is in building a dependency graph for any codebase.

FREQUENTLY ASKED

Dependency graph: questions

What is the difference between a package dependency graph and a code dependency graph?

A package graph shows which libraries a project declares, from files such as package.json or Cargo.toml. A code graph shows which files import which, found by parsing source. A package can be declared and never imported, so the two disagree in real projects.

What is a circular dependency?

A cycle in the graph: A depends on B and B depends on A, directly or through a chain. Cycles make modules hard to build, test or reason about separately. They are found as strongly connected components.

What are fan-in and fan-out?

Fan-in is how many units depend on a node; fan-out is how many it depends on. High fan-in marks load-bearing code that is risky to change. High fan-out marks code that breaks whenever any of its many dependencies changes.

How do you visualize a dependency graph?

For JavaScript, madge or dependency-cruiser render SVG graphs. For Python, pydeps. For Go, go mod graph prints module edges, and for Rust cargo tree prints the crate tree. For Java, jdeps analyzes class and package dependencies.

See it on your own repository.

Index a repository free and read the result for your own code and history. Rolling it out to a team? We will walk you through it.