6.1.1 Bazel as a Shared Service
A local Bazel invocation has one immediate question: did this build produce the right result? A shared Bazel service has a harder job. It must keep results reusable, workloads isolated, evidence complete, and recovery possible while many developer and CI invocations overlap and outlive one another.
That change of responsibility matters before you choose a cache product or add remote workers. Buildfarm's learning path makes remote caching and remote execution two separate steps, while REAPI defines portable client/service contracts without prescribing one production topology.1,2 A service plan should preserve that separation: first name the result each workload needs, then decide which shared component can improve it.
Start With Journeys, Not One Build-Time Number
"The build" is not one workload. An interactive edit-build-test loop, a presubmit, a postsubmit build, a release candidate, and a maintenance operation can exercise the same Bazel targets but value different outcomes.
Use a small journey ledger before designing the service:
| Journey | Result to protect | Question the service must answer |
|---|---|---|
| Interactive development | A trustworthy answer with useful feedback soon enough to keep working | What may be reused, and what happens when the shared service is unavailable? |
| Presubmit | Complete evidence for the requested change check | Can CI distinguish failed work from missing or incomplete results? |
| Postsubmit | Sustained completion of the intended workload | Which action classes create queue, transfer, or execution pressure? |
| Release | An attributable result and the artifacts its consumers require | Which invocation, producer, configuration, and result does the handoff describe? |
| Maintenance | A bounded change to the service itself | Which cohort is exposed, what signal stops the change, and how is the prior path restored? |
The ledger prevents a common design error: improving an aggregate while making one important journey worse. For example, more remote cache hits may reduce execution in postsubmit while interactive builds wait longer to download outputs. That is neither a universal success nor a universal failure. It is a reason to measure the two journeys separately in 6.1.2 Measuring Builds Fairly.
Action classes need the same separation. A profile can point toward remote cache misses, queueing, insufficient parallelism, a non-dominant critical path, or actions that still execute locally. Bazel Invocation Analyzer encodes those as distinct suggestion providers and tests rather than treating every slow invocation as a request for more remote capacity.3 The operational lesson is broader than one analyzer: keep compilation, linking, testing, fetching, and other materially different work in cohorts that preserve the behavior you are trying to explain.
Assign Responsibility at Every Transition
A shared service is a chain of responsibilities, not a single remote endpoint. REAPI supplies interoperable contracts for content-addressed storage, action caching, execution, capabilities, digests, and result messages. Queue shape, storage layout, worker protocol, and authentication remain implementation choices.2
For each journey, write down who owns these transitions:
- The Bazel client chooses the configured path and identifies the invocation and actions it requests.
- A remote cache accepts or serves shared result state.
- When execution is remote, the execution service admits, schedules, and dispatches work to a compatible executor.
- CI decides which work it requested and whether the returned evidence is complete for that request.
- If BES or another result pipeline is present, its producer, transport, storage, and consumer each need an explicit completeness and retention boundary.
Do not turn that list into a claim that every backend has the same internal shape. Buildbarn's runnable deployment separates frontend, storage, scheduler, runner, worker, and monitoring roles.4 NativeLink offers focused CAS, scheduler, executor, metrics, and integration-test surfaces with a different implementation structure.5 Those repositories are useful because they make responsibilities inspectable; neither topology is imposed by REAPI.
Trace the detailed conditional paths for one action in 6.1.4 Action and Result Lifecycle. At this point, the important test is simpler: for every handoff, can you name the component that accepts responsibility, the identity it receives, the evidence it emits, and the owner who acts when those two do not agree?
Define Success as a Vector
Shared infrastructure can be fast and wrong, available and incomplete, or cheap only because another team absorbs its failures. Define success across at least these dimensions for each journey and relevant action class:
- Correctness: reused or executed work produces the result justified by its declared identity. A hit-rate increase is reuse evidence, not a correctness proof.
- Latency: measure the wait that matters to the journey, then retain enough phase and service detail to explain it.
- Throughput: count useful completed work for a named workload, not merely requests accepted or workers busy.
- Availability: state which results remain trustworthy and obtainable in the chosen degraded mode.
- Security: identify who may read, write, execute, and consume shared state, and where one producer's authority ends.
- Cost: include the storage, transfer, execution, retained capacity, and operational work required to deliver the journey's result.
These dimensions are intentionally not one score. A design review should be able to say, for example, "interactive latency improved for this action cohort; correctness and result completeness stayed within their gates; transfer cost rose by this bounded amount." A single global average cannot express that decision.
Before prescribing remote infrastructure, locate the work. Remote cache or execution cannot repair loading and analysis cost merely by adding workers. A sequential critical path may not benefit from more parallel capacity. An incorrect or underdeclared action remains incorrect when executed elsewhere, and running an unnecessarily broad target set faster does not make its selection appropriate. Use the one-invocation evidence from Level 5 to falsify those alternatives first; 5.4.2 Critical Path and 5.5.2 Metrics & Monitoring provide the nearer diagnostic models. Only then use 6.1.3 Choosing Remote Cache or Execution to select cache, execution, both, or neither.
Make the Plan Falsifiable
A service plan needs an evidence contract that survives across clients. At minimum, retain identities that let you join an invocation to its actions and results, attribute the producer and relevant client/backend versions, and separate protocol evidence from backend observations. REAPI's digest, capability, action, and result messages provide part of that portable chain; Buildbarn's deployment also shows why component and image/configuration identity matter operationally.2,4
For every proposed change, write three statements:
- Hypothesis: which journey and action cohort should improve, through which service transition?
- Success signal: what observation would support that claim without hiding correctness, completeness, or security regressions?
- Stop signal: what observation ends the experiment or rollout before the blast radius grows?
Keep the raw identities behind aggregate dashboards. If a service average moves, you need to recover the invocations and action classes that moved it. 6.6.1 Tracing a Build Across Services develops that correlation across Bazel, cache, execution, CI, BES, and consumers.
Preserve evidence before clearing state, restarting every component, or republishing results. A global reset may restore service, but it also destroys the comparison that could distinguish a bad producer, incompatible version, incomplete result, or capacity problem. Recovery is safer when it can quarantine a bounded identity or cohort instead of treating all shared state as equally suspect.
Decide: A team reports that remote-cache hit rate increased from its previous baseline, but presubmit latency did not improve. Is adding cache capacity a justified next step?
Reveal
Not yet. First separate presubmit from other journeys and split its actions into useful cohorts. Then locate lookup, download, materialization, queueing, execution, loading/analysis, and critical-path time with invocation-level evidence. Capacity is justified only if the evidence identifies a saturated cache stage and the proposal has correctness, completeness, cost, success, and stop signals. A higher hit rate alone establishes none of those facts.
When Bazel becomes a shared service, the unit of design changes from one green invocation to many journeys sharing state over time. Plan per journey and action class, assign every client/cache/execution/CI/result transition to an owner, and judge the service across correctness, latency, throughput, availability, security, and cost.
Every change should preserve joinable invocation, action, result, producer, and version evidence and declare a falsifiable success signal and stop signal. Diagnose the workload before buying capacity, and preserve evidence before clearing shared state.
Check your understanding · 3 questions
1.Which practices make a shared Bazel-service plan accountable rather than just fast on average?
Select all that apply
2.Remote-cache hit rate rises, but presubmit latency does not improve. What should the team do before adding cache capacity?
Select one answer
3.Classify each claim about operating Bazel as a shared service:
Choose True or False for each sentence
Footnotes
-
Buildfarm — distributed cache and remote execution service — cache-first, execution-second quick start and the client/server/worker responsibility split ↩
-
Remote APIs — protocol contracts for caching and remote execution — portable service, capability, digest, action, and result contracts versus implementation topology ↩1 ↩2 ↩3
-
Bazel Invocation Analyzer — profile-driven performance suggestions — distinct profile signals and tested suggestion providers for cache, queueing, parallelism, critical-path, and local-action symptoms ↩
-
bb-deployments — runnable Buildbarn topologies — separated frontend, storage, scheduler, runner, worker, monitoring, and configuration responsibilities ↩1 ↩2
-
NativeLink — remote cache and execution implementation — focused CAS, scheduler, executor, metrics, and integration-test surfaces and their contract boundaries ↩