6.1.4 Action and Result Lifecycle
When an action is slow or appears to vanish inside “remote Bazel,” the useful question is not which remote component is generally slow. Ask which path this action actually took, and at which handoff the observations first stopped matching the expected path. One invocation may mix local cache hits, remote cache hits, local execution, and remote execution, while its build events take a separate optional route.
An action first checks local or remote cache state. A usable hit makes outputs available according to the selected output policy; a miss chooses local or remote execution. Build-event reporting is a separate optional route.
6.1.1 Bazel as a Shared Service established the responsibility boundary between the Bazel client and shared services. Here we turn that boundary into an orientation map for one action. It is deliberately shallower than cache-key design, protocol configuration, a complete REAPI transaction, or cross-service trace correlation.
The Lifecycle Is a Decision Tree
Start from an action that analysis has already declared. The Bazel client has enough information to decide whether an existing result is reusable and, on a miss, which permitted execution strategy to try. A useful high-level trace is:
- Choose a route. Client configuration and action requirements determine which cache and execution routes are eligible.
- Look for a reusable result. Local state may satisfy the action. If a shared cache is configured, the client may also ask it for a result and the referenced output data.
- Execute on a miss. The client can run the action locally, or submit an eligible action to a remote execution service. Remote execution adds admission, scheduling, compatible-worker placement, input availability, execution, and result publication.
- Make outputs available. Required output data is available locally or is obtained from shared content storage according to the chosen path and output policy.
- Report what happened. The client records profile and execution evidence and produces Build Event Protocol (BEP) events. It may write those events locally or send them to a Build Event Service (BES); this reporting route is not a prerequisite for the action to execute.
Buildfarm's quick start intentionally enables remote caching before remote execution. That progression is useful evidence that cache reuse and worker execution are separate branches, even when one deployment supplies both.1 NativeLink likewise exposes separate cache and remote-execution configurations and integration tests.2 A single invocation can therefore take different branches for different actions; there is no one “remote pipeline” that every action traverses end to end.
The cache branch itself has two interface families that must not be collapsed.
Bazel can use an HTTP remote cache without using the Remote Execution API. A
REAPI service instead exposes versioned protobuf/gRPC contracts such as Action
Cache, content-addressed storage (CAS), ByteStream, Capabilities, and Execution.
The remote-apis repository defines those contracts, while leaving scheduler,
queue, storage, and authentication topology to implementations.3
6.2.1 How Remote Cache Keys Work explains the identities that make reuse safe, and
6.2.2 Setting Up a Shared Remote Cache follows the actual HTTP or REAPI cache exchange.
For this map, the decisive distinction is simpler: an HTTP cache interaction is
not evidence that an REAPI Execute request, scheduler, or worker participated.
Follow Control, Data, and Results Separately
The three views below are diagnostic lenses, not three mandatory protocol services. One transition may produce evidence in more than one view.
Follow control
Control answers who decided what happens next. Begin with the client's strategy choice and any capability or compatibility checks. On a remote execution branch, continue through request acceptance, admission, queueing, matching, dispatch, and worker assignment. A configured remote strategy proves intent, not placement. An accepted operation proves that a service accepted responsibility, not that a compatible worker started the process.
Buildbarn's runnable topology separates frontend, storage, scheduler, runner,
worker, and monitoring responsibilities.4 That is one implementation shape,
not a REAPI requirement, but it demonstrates why “the backend accepted it” is
too coarse to locate a control failure. The successful observable Execute and
Operation sequence is developed in 6.3.4 Remote Action Tracing.
Follow data
Data answers which bytes had to be present, and where they moved. Track the declared input and tool data, the cache lookup, any CAS availability or upload work, outputs produced by execution, and the output data the client or another consumer must obtain. Keep metadata from bytes: finding a result description does not by itself show that every referenced output is reachable.
On the HTTP-cache branch, describe the HTTP cache's result and blob exchange as that protocol's path. On a REAPI branch, name the Action Cache, CAS, and ByteStream roles when the evidence supports them. Do not paste the REAPI object model over an HTTP interaction merely because both can reuse outputs. Likewise, slow input fetch or output materialization is data-path evidence, not scheduler delay.
Follow results
Results answer what each observer can legitimately conclude. The action's execution result and output data are one result path. Bazel's profile and execution logs are client evidence about another. BEP events are generated by the Bazel invocation; optional BES delivery adds transport, storage, and consumer boundaries after generation.
This separation prevents two common false conclusions. A missing BES event does not prove that the action never executed, because event delivery can fail after or independently of execution. Conversely, a successful action does not prove that every required event and referenced artifact reached a downstream consumer. Distributed result completeness is handled by 6.5.8 Complete CI Results with BEP/BES.
Diagnose the First Differentiating Transition
Do not begin by collecting every log from every component. Write two plausible paths, then choose the earliest observation whose outcomes differ. This is the first differentiating transition.
| Competing explanations | First useful transition to inspect | What the observation separates |
|---|---|---|
| Remote cache hit vs local execution | Cache lookup outcome joined to client execution evidence | Reuse from actual execution |
| HTTP cache use vs remote execution | Presence of an REAPI execution request or operation | Cache transport from worker execution |
| Waiting for placement vs running on a worker | Accepted/queued state versus dispatch or worker-start evidence | Scheduler ownership from executor ownership |
| Scheduler delay vs CAS delay | Queue/match timestamps versus input fetch or blob-transfer evidence | Control-path wait from data-path wait |
| Execution failure vs BES delivery failure | Terminal action evidence versus BEP generation and delivery evidence | Build result from reporting failure |
For example, suppose a compile action is slow and the dashboard calls all of its time “remote.” One hypothesis is that it waited for a compatible worker; another is that a worker was assigned promptly but waited for inputs. Inspect the queue-to-dispatch boundary first. If dispatch is late, continue in the control path. If dispatch is prompt, inspect CAS/input-fetch evidence in the data path. Looking at average worker CPU before that transition would not distinguish the hypotheses.
Bazel Invocation Analyzer treats cache misses, queueing, critical-path shape, parallelism, and actions that still execute locally as distinct profile signals, which reinforces this evidence-first separation.5 When the diagnosis must join invocation, action, operation, result, blob, BES, and downstream identities across several services, continue with 6.6.1 Tracing a Build Across Services. This article supplies the map of candidate transitions; it does not claim one universal trace identifier or teach the joins.
Trace: A remote-execution flag is present, the build completes, and no event for one action appears in the BES-backed dashboard. Which transition should you inspect first if the competing hypotheses are “the action never ran remotely” and “the action ran, but reporting was incomplete”?
Reveal
Start with placement and terminal action evidence from the client and execution service, not with the dashboard. A remote operation, dispatch/worker evidence, and terminal action result can establish the execution branch independently of BES. If those exist, move to BEP generation and then BES delivery. If they do not, move backward through strategy selection, cache outcome, and execution submission. The flag proves only configured intent, while the missing dashboard event proves only that this consumer lacks the event.
Treat one Bazel action as a conditional decision tree, not a fixed remote pipeline: local or remote cache reuse may satisfy it; a miss may execute locally or remotely; output data must become available; and BEP/BES reporting follows a separate optional route. Keep HTTP cache interactions distinct from REAPI cache and execution services.
Trace control decisions, data movement, and result evidence separately. When a symptom fits several layers, inspect the earliest lifecycle transition whose outcome would differ between the candidate paths. Configuration shows intent, while transition evidence shows what actually happened.
Check your understanding · 3 questions
1.Match each diagnostic lens to the question it answers:
Drag each answer onto the matching prompt, or click an answer and then click a prompt
2.A build completes with a remote-execution flag, but one action is absent from a BES-backed dashboard. What is the justified first inference?
Select one answer
3.Which first differentiating transitions can separate the listed competing explanations?
Select all that apply
Footnotes
-
Buildfarm — distributed cache and remote execution service — cache-first, execution-second quick start and distinct server/worker responsibilities ↩
-
NativeLink — remote cache and execution implementation — separate cache and remote-execution configurations, metrics, and integration-test surfaces ↩
-
Remote APIs — protocol contracts for caching and remote execution — Action Cache, CAS, ByteStream, Capabilities, and Execution contracts versus implementation topology ↩
-
bb-deployments — runnable Buildbarn topologies — separated frontend, storage, scheduler, runner, worker, and monitoring roles ↩
-
Bazel Invocation Analyzer — profile-driven performance suggestions — distinct profile evidence for cache, queueing, critical path, parallelism, and local-action symptoms ↩