2.1 Directed Acyclic Graph (DAG)

bazel build //app:server names one target. Yet bazel query 'deps(//app:server)' can reveal a much larger set. The useful question is why those targets and files appear while most of the repository does not. Each included node is reachable from //app:server along a dependency path. Branches with no such path stay outside the request.

Once you can see that boundary, several Bazel behaviors line up. A narrow build is a small reachable slice. A compiler target you never wrote in deps may arrive through an implicit edge. A missing direct dependency can stay hidden behind another path until a refactor removes it. A cycle leaves Bazel without a valid dependency order.

Trace The Request Outward

2.1.1 Nodes, Edges & Acyclicity gives you the map: labels name nodes, dependency attributes create directed edges, and the graph must stay acyclic. 2.1.2 Laziness & Slicing shows Bazel using that map for one command, following only the paths reachable from the requested target. Read these two together: the first defines the structure, and the second explains why a large repository does not automatically mean a large build request.

Explain The Edge You Did Not Expect

Finding an unexpected node is only the start. The next question is who added the edge that led there. 2.1.3 Dependency Types separates dependencies written in BUILD files from those supplied by rules and toolchains, and asks separately whether each dependency lives in the main repository or an external one.

2.1.4 Common Dependency Issues covers the cases where the path itself needs attention: code relying on an undeclared direct dependency, an accidental re-export, or two branches that introduce incompatible external versions. Together, these articles turn “why is this here?” into a concrete investigation: classify the edge, trace its path, and decide whether the relationship is intentional.

Ask The Graph In Both Directions

2.1.5 Inspecting the Graph — Query Preview maps query, cquery, and aquery to the graph layers they inspect. For the target graph, three questions cover most first investigations: what does this target need, why does this dependency path exist, and who depends on the target I am about to change? 2.1.6 Reverse Dependencies & Change Impact develops that last question into a change-impact check by walking the graph backward.

Stay with the declared target graph while the question is structural. Move to configured targets when flags or platforms choose the edge, to the action graph when you need the concrete execution plan in 2.2.1 Loading, Analysis & Execution, and to 2.4.1 Skyframe & Incrementality when the question is about reuse across commands. This keeps an unexpected dependency, a configuration choice, and a cache miss from collapsing into one vague “Bazel did too much” problem.

key takeaway

Start from the requested target and trace reachability. If the resulting slice surprises you, classify the edge and explain its path. Before changing a shared target, walk the graph in reverse. Switch graph layers only when configuration, actions, or incremental reuse become part of the question.