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.

Trace the branch this action actually took
Choose the earliest transition where two explanations would produce different evidence.

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.

control decisions data and blobs results and evidence diagnostic cut
BAZEL CLIENT
Analyzed action ready
Configuration selects eligible routes
Control: look for a reusable result
LOCAL BAZEL STATE
Local result can satisfy action
No shared service needed
HTTP REMOTE CACHE
HTTP result and blob exchange
No Execute or worker
REAPI CACHE
Action Cache with CAS data
Portable cache interfaces
DECISION
Usable cache result?
Hit → apply the output-availability policy. Miss → choose an execution strategy.
HIT → OUTPUT PATH
Result metadata names outputs
Metadata is not bytes
CLIENT APPLIES OUTPUT POLICY
Outputs are available as the policy requires
Bytes may stay remote or be downloaded when needed
Miss → choose execution
Configured intent is not placement proof. A remote strategy says what the client may try. It does not prove a worker started the action.
Control: cache miss chooses an execution strategy
LOCAL EXECUTION
Client runs the action locally
No remote placement path
LOCAL RESULT
Outputs and client evidence appear
Execution result is observable
REMOTE SUBMISSION
Capability and compatibility boundary
Eligible remote request
ADMISSION AND QUEUE
Service accepts and waits
Accepted is not dispatched
DISPATCH AND WORKER
Compatible worker starts action
Placement evidence begins
DECLARED DATA
Inputs and tools must be available
CAS availability or upload
WORKER INPUT FETCH
Bytes reach the executing worker
Data wait differs from queue wait
EXECUTION AND PUBLICATION
Action result references output data
Terminal result is separate evidence
CLIENT OUTPUT AVAILABILITY
Fetch required output blobs
Materialize for the chosen policy
Parallel results and evidence: optional, not the next execution stage
BAZEL CLIENT
Records what the invocation observed
Reporting does not execute the action
PROFILE
Profile and execution-log evidence
Client-side observations
BEP GENERATION
Invocation emits build events
Generated independently of delivery
LOCAL BEP OUTPUT
Events remain available locally
Optional sink; no service required
Independent optional sinks
OPTIONAL BES AND CONSUMER
Delivery can fail after execution
Dashboard is a downstream observer
Five diagnostic cuts: inspect the first one that separates your hypotheses
CUT 1
Cache outcome → client execution evidence
Reuse versus execution
CUT 2
HTTP exchange → REAPI Execute
Cache versus worker path
CUT 3
Accepted or queued → worker start
Scheduler versus executor
CUT 4
Queue or match → input fetch
Control wait versus data wait
CUT 5
Terminal action → BEP or BES delivery
Build result versus reporting
Portable interfaces: bazelbuild/remote-apis Separate cache and execution routes: Buildfarm and NativeLink Separated responsibilities are one Buildbarn implementation example, not a REAPI mandate
One action can reuse a local, HTTP, or REAPI cache result, execute locally or remotely on a miss, and report through a separate optional BEP and BES route. Follow the earliest differentiating transition, not the word “remote.”

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:

  1. Choose a route. Client configuration and action requirements determine which cache and execution routes are eligible.
  2. 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.
  3. 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.
  4. Make outputs available. Required output data is available locally or is obtained from shared content storage according to the chosen path and output policy.
  5. 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 explanationsFirst useful transition to inspectWhat the observation separates
Remote cache hit vs local executionCache lookup outcome joined to client execution evidenceReuse from actual execution
HTTP cache use vs remote executionPresence of an REAPI execution request or operationCache transport from worker execution
Waiting for placement vs running on a workerAccepted/queued state versus dispatch or worker-start evidenceScheduler ownership from executor ownership
Scheduler delay vs CAS delayQueue/match timestamps versus input fetch or blob-transfer evidenceControl-path wait from data-path wait
Execution failure vs BES delivery failureTerminal action evidence versus BEP generation and delivery evidenceBuild 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.

think

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.

key takeaway

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

Answers
Control
Data
Results

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

0 of 3 answered

Footnotes

  1. Buildfarm — distributed cache and remote execution service — cache-first, execution-second quick start and distinct server/worker responsibilities

  2. NativeLink — remote cache and execution implementation — separate cache and remote-execution configurations, metrics, and integration-test surfaces

  3. Remote APIs — protocol contracts for caching and remote execution — Action Cache, CAS, ByteStream, Capabilities, and Execution contracts versus implementation topology

  4. bb-deployments — runnable Buildbarn topologies — separated frontend, storage, scheduler, runner, worker, and monitoring roles

  5. Bazel Invocation Analyzer — profile-driven performance suggestions — distinct profile evidence for cache, queueing, critical path, parallelism, and local-action symptoms