5.2 Query

Three commands can begin with the same label and still answer different questions:

bazel query 'deps(//app:server)'
bazel cquery 'deps(//app:server)' --platforms=//platforms:linux
bazel aquery 'deps(//app:server)'

The first sees dependencies that the BUILD files can declare. The second sees configured targets for a particular build context. The third sees the actions Bazel plans after analysis. When an investigation uses the wrong one, the output can be perfectly accurate and still fail to explain the symptom.

The organizing idea for this section is therefore not a list of query commands. It is an evidence ladder: ask which graph layer can contain the fact you need, query the narrowest useful scope at that layer, and move deeper only when the remaining question demands it.

Move From Declaration To Execution Plan

Start with 5.2.1 bazel query — Static Graph Analysis. It gives you the shared language of sets, closures, reverse dependencies, and paths on the unconfigured target graph. This is the quickest lens for structural questions such as “what can this target reach?” and “which declared path connects these packages?” The basic-query snippet is a useful place to try those operations before applying them to a large repository.

Move to 5.2.2 bazel cquery — Configured Graph when flags, platforms, select(), transitions, or toolchains can change the answer. A result is no longer just a label. It is a label in a configuration and in a chosen top-level context. If the configuration ID is the clue but its option values are still opaque, 5.2.4 bazel config — Configuration Inspection is the focused companion: generate the configuration with cquery, then inspect or compare it while the same server and flags preserve it.

Continue to 5.2.3 bazel aquery — Action Graph only when the question has become about the execution plan: the command line, inputs, outputs, mnemonic, or producer of an artifact. This is a deeper view, not a universally better one. It can show what Bazel plans to run, but it cannot prove that an action ran, where it ran, how long it took, or whether it hit a cache. Those are execution and observability questions elsewhere in this level.

Taken together, these four articles form the main diagnostic path:

declared target graph -> configured target graph -> planned action graph
                              |
                              +-> configuration option values

The repeated discipline is to keep the graph layer, configuration, and scope attached to every conclusion. “This target depends on that library” is weaker evidence than “this configured target reaches that library under these roots, platforms, and flags.”

Change The Form Without Changing The Question

Two articles extend the family sideways rather than moving down the evidence ladder.

5.2.5 genquery — Query as Build Artifact keeps the unconfigured semantics of query, but turns the answer into a declared build artifact. Read it when a manifest, policy check, or other target genuinely consumes the result. It is not a way to smuggle an interactive investigation or configured-provider traversal into the build graph.

5.2.6 Sky Query Mode also stays in the query world, but changes how Bazel evaluates a universe-scoped question and adds reverse BUILD/.bzl load relationships. It is useful when allrdeps() or rbuildfiles() matches the problem. Its result is still bounded by the chosen universe, and its possible performance benefit is something to measure rather than assume.

This distinction prevents a common category error: genquery and Sky Query are not rungs between cquery and aquery. They change where an unconfigured query result lives or how a particular unconfigured search is evaluated. They do not add configuration or action semantics.

Automation Turns Scope Into A Safety Contract

An interactive query can be rerun when its scope was wrong. A CI selector can silently skip required work. 5.2.7 Query in CI Pipelines therefore treats query output as evidence whose revision, universe, and configuration scope remain attached to one bounded CI analysis. The result can justify work inside that stated scope; it cannot silently become a complete affected-target service.

Read this article after the core lenses if you are automating affected-target selection. It deliberately stops before the production architecture developed in 6.5.1 Affected-Target Service Contract. Base/head reconciliation, deletes and renames, supported-configuration coverage, unknown-state fallback, and production correctness guarantees are developed there. The goal here is to make one scoped query decision reproducible and honest about what it has not proved.

Choose A Reading Path From The Symptom

For a first pass, read the core query, cquery, and aquery articles in order. That sequence establishes the evidence ladder and the handoff points between layers. Keep the extra bazel config article for a case where cached configuration identities or option differences remain the unresolved question.

Then branch by job:

  • If another target needs the query result as a file, use the recommended genquery branch.
  • If reverse load dependencies or an explicitly universe-scoped reverse search is the problem, use the recommended Sky Query branch.
  • If query results will decide which CI work can be skipped, use the recommended Query in CI branch only after the universe and configuration rules from the core path are clear.

Do not begin with the most detailed output available. Begin with the shallowest graph that can contain the answer, narrow it, and preserve the command context. Only descend when the unresolved part of the symptom belongs to the next layer.

think

Classify: Before choosing a Bazel query command, which parts of the question must be explicit enough for the result to support a conclusion?

Reveal

Identify the required layer—declared targets, configured targets, planned actions, or configuration values—then state the roots or universe and the relevant flags. Those choices lead to query, cquery, aquery, or bazel config. An unspecified scope or configuration makes even accurate output ambiguous.

key takeaway

The query family is an evidence ladder, not a menu of interchangeable commands. Match the symptom to the declared, configured, action, or configuration-state layer. Keep the universe and flags with the result. Use genquery and Sky Query only for their specific sideways extensions, and demand a conservative safety contract before query output controls CI.