A dependency graph maps the relationships between parts of a software system. Its nodes represent components such as modules, services, packages, or databases. Its connections show which components call, import, read from, or otherwise rely on one another. In a legacy system, this map makes hidden change paths visible before refactoring begins.
What the graph reveals
Dependencies exist at several levels. Source files import other files. Modules call shared libraries. Services exchange data through APIs or queues. Applications also depend on databases, scheduled jobs, and external systems. A useful graph states what each node represents and what kind of relationship each connection records.
The direction matters. If module A calls module B, changing B may affect A even when A is untouched. The graph can also expose cycles, where two components depend on each other and cannot be changed or deployed independently.
| Graph signal | What it can indicate | What to check |
|---|---|---|
| Many incoming links | Widely reused component | Compatibility of any interface change |
| Many outgoing links | Component with broad reliance | Failure and upgrade paths |
| Dependency cycle | Components cannot be isolated easily | Boundary and ownership decisions |
| Unconnected node | Unused or separately operated code | Runtime use before removal |
Why legacy systems need a map
Older codebases often contain relationships that are absent from current documentation. A shared database table can connect otherwise separate modules. A scheduled process can supply data that an application assumes will exist. A library can remain pinned because several components rely on behaviour that changed in later versions.
A legacy codebase audit compares the graph with runtime configuration, deployment files, and the code itself. This avoids treating a diagram as complete when dynamic calls or operational dependencies sit outside it.
How it shapes a migration plan
The graph supports impact analysis: tracing what may be affected when a component moves, changes, or disappears. It also helps define migration order. Components at the edge of the graph may be easier to isolate. Central components usually need stable interfaces before dependent code can move.
A migration plan commonly uses the graph to:
- Find boundaries. Group code and data that change together.
- Sequence work. Move components without breaking their consumers.
- Locate shared services. Identify code that needs an interface before it can be separated.
- Plan verification. Focus tests on connections crossed by the change.
How it relates to other audit evidence
A dependency graph describes structure, not quality. It does not show whether a component is correct, well tested, or frequently changed. Those questions require test results, change history, and direct code review.
Combined with technical debt, the graph shows where structural reliance and repair cost overlap. It also provides a working map for taking over and migrating an unfamiliar codebase, because the team can trace a change beyond the file where it starts.