6.3.12 Remote Execution Capacity

Adding executors because a dashboard shows a queue is a tempting response—and often an expensive one. An action can wait because no compatible worker has the right memory, device, image, or isolation mode; because the worker is fetching inputs; or because a shared CAS, network path, or scheduler is saturated. Conversely, a pool can show spare average CPU while its memory-heavy or device-bound actions starve. Capacity is therefore a prediction about a named action class reaching a compatible, usable executor, not a fleet-wide executor count.

6.3.8 Scheduling Actions on Remote Executors established the queue and matching evidence needed before this point. Start with actions that are already admitted and matchable. If a request has no compatible destination, fix the property-to-pool contract in 6.3.2 Remote Executor Matching; buying another incompatible worker cannot help. Heterogeneous fleets make this distinction concrete: an embedded test pool may be the only place a hardware test can run, while ordinary compilation continues elsewhere.1

Model an occupied executor, not just a command

For each action class and compatible pool, make a small capacity record. An action class is a workload with similar execution requirements and behavior—not merely a mnemonic. A Java compile and a simulator UI test can have quite different memory, device, input, and lifetime demands even when both happen to use one CPU at a particular instant. Simulator tests are an especially clear case: a UI test may need an exclusive simulator lease while logic tests can share one.2

RecordWhat the model needsWhy an average hides it
Arrival and burst shapeArrivals by cohort and action class, including concurrent build starts and retry/fallback trafficA quiet hourly average erases a short presubmit surge that fills the only compatible pool.
Occupancy distributionAssignment-to-release stages: input/CAS fetch, execution-root and isolation preparation, command time, output upload, cleanup, and any deliberate warm-state workA short command can hold a worker for a long fetch or upload; a long tail can consume the last suitable slot.
Resource distributionCPU, memory, local disk and I/O, network, device or license leases, and image/runtime constraints at the concurrency actually observedOne worker is not one interchangeable slot, and average CPU does not reveal memory or I/O pressure.
Usable supplyExecutors that are healthy, matchable, correctly provisioned, and able to accept this class, plus their effective concurrencyA nominally idle macOS, ARM, or small-memory worker is not spare capacity for an incompatible request.
Change and failure timeMeasured request-to-usable scale lag, cold-image/input effects, a burst horizon, and the capacity lost during one declared failure scenarioA pod reported as created is not yet an executor that can successfully claim the next action.

Keep the records joined to the action, attempt, pool, and worker identities from 6.3.4 Remote Action Tracing. The worker stages matter here: input presentation, isolation startup, command execution, output upload, and cleanup are distinct occupancy causes, not all “execution.” 6.3.9 Remote Executor Environments and Isolation explains how to attribute those stages. A Snowflake deployment found low IOPS in network-attached worker and cache storage, along with an undersized scheduler, and used action traces to distinguish execution, queuing, upload, and download while right-sizing memory-different pools.3

A useful model has no universal executor-count formula. For each pool, project the arriving work during the scale-lag and burst interval against the distribution of time it will occupy each required resource. Then compare that demand with usable compatible supply after reserving the failure headroom the service promises. State the prediction in observable terms: which class will queue, which resource or stage limits admission or release, how much burst can be absorbed before scale-out is useful, and what changes after a worker or availability domain is unavailable. The model must retain uncertainty rather than convert a thin sample into a precise-looking threshold.

think

Decide: A Linux compile pool has low average CPU utilization, but its memory-intensive compiles queue during presubmit bursts. The autoscaler sees a modest fleet-wide queue and adds general-purpose workers. Which model record is wrong or missing first?

Reveal

Start with usable supply and the class's resource distribution. The new workers may not have enough memory, may not be in the compatible pool, or may not become usable before the burst ends. Then check the arrival burst and full occupancy distribution: fetch, setup, upload, or cleanup can keep the suitable workers occupied after the compiler process has stopped. Neither the fleet-wide queue nor average CPU establishes that a compatible memory slot was available.

Treat autoscaling as a delayed capacity change

Autoscaling can move capacity; it does not remove the need for a model. Measure the whole lag from the backend's scaling decision through instance allocation, image or runtime readiness, registration, eligibility, and the first successful claim by the intended action class. Include the extra fetch and network demand created by cold workers. A fixed pool that cannot meet bursts and an autoscaler that arrives after the burst are equivalent for that protected journey.

Choose scale signals from the prediction, not from a generic CPU target. For example, sustained queue age and queued resource demand within a compatible pool can be evidence to add that pool; a rising CAS-fetch or network stage may instead show that scaling workers would worsen the bottleneck. BuildBarn's automatic resource management learns that an action needs a larger worker after an observed small-worker failure, and routes later executions accordingly. That is useful evidence for an implementation-specific class-sizing mechanism, not a portable rule for every REAPI backend.4 BuildBarn's related size-class case also shows why broad “large” annotations can spend most compute time on unnecessarily large workers.5

Scale-down needs the same care. Do not remove an executor simply because its instantaneous CPU is low if it is the only warm compatible capacity, holds a scarce device, or would leave no failure headroom. One production incident combined overly aggressive scale-down with slow scale-up, producing recurring queue spikes even though the fleet sometimes looked healthy.6 Record the chosen drain behavior, the capacity it temporarily removes, and the fallback load it can create. Cancellation, retries, and local fallback have their own correctness and amplification rules in 6.3.13 Remote Action Failure Handling; do not quietly count their extra work as free headroom.

Make the model predict a load test

The test is the decision point, not a decorative benchmark. Select a representative workload cohort with the relevant action-class mix, platforms, input/output shapes, cache temperature, and burst pattern. Hold the configured pool vocabulary and autoscaling policy known. Then write down the model's prediction before the run: expected queue-age shape, which compatible pool should fill first, which stage should saturate, how long added workers will take to become useful, and the point at which the stated failure headroom is spent.

During the test, join client, scheduler, worker, CAS, and network evidence in one clock domain. Check correctness and complete output publication first; a fast failed attempt is not capacity. 6.3.7 Remote Execution Storage defines what proves that remote result is actually reachable. Then compare prediction and observation:

ObservationCapacity conclusion it supportsNext move if it disagrees with the model
Compatible-pool queue age rises while suitable workers are fully occupiedThe pool's usable executor/resource supply is short for this workloadRevisit the class resource and occupancy distributions, then evaluate a pool change or scale policy.
Workers begin commands slowly despite idle executor slotsA fetch, image, CAS, network, scheduler, or preparation stage may be the limiterTrace the stage; do not call the number of executors the saturated resource.
Added workers register after the demand has drainedScale lag, cold start, or signal timing is ineffective for this burstChange the policy or protect warm/failure headroom, then rerun the same cohort.
Some queues grow while global capacity remains idleCapacity is unmatchable or the class/pool routing is wrongReturn to matching evidence rather than increasing fleet size.
The predicted pool saturates but another stage fails firstThe model omitted a dependency or mismeasured its distributionRevise the model from the residual; keep the failed prediction as evidence.

This test should include a bounded failure case—such as losing the declared worker slice or preventing a scale-out from becoming usable—so the recorded headroom is demonstrated rather than assumed. It should also distinguish a warm run from cold input and output paths. Large, repeatedly transferred artifacts can saturate network delivery even when commands themselves have available CPU; Snowflake encountered this when large statically linked test binaries had to reach many workers.3

Do not turn an autoscaling demonstration into a generic cluster tutorial. The result needed here is narrower: a revised, action-class and compatible-pool model that correctly predicts a representative load test and identifies the stage that actually saturates. 6.3.10 Remote Input Presentation and 6.3.11 Remote Output Availability deepen the input and output choices that change worker occupancy. 6.6.7 Planning Capacity for Build Infrastructure extends this same evidence discipline to cache, scheduler, BES, and CI services; it does not replace the executor-pool model.

key takeaway

Remote-executor capacity is usable compatible capacity for a named action class, not average CPU, queue depth, or worker count. Model arrivals and bursts, full-stage occupancy, resource distributions, compatible supply, measured scale lag, and an explicit failure scenario for every pool that protects a workload.

Make the model predict a representative load test before running it. Join queue, worker, CAS, network, and completion evidence to discover whether the limiting stage is matching, fetch, preparation, execution, upload, or scale lag. Revise the model from the mismatch; adding executors is justified only when that is the stage the evidence actually identifies.

Check your understanding · 4 questions

1.Hardware-in-the-loop tests queue while the fleet has many idle general-purpose executors and low average CPU. What should the capacity model examine first?

Select one answer

2.Match each observation to the capacity-model evidence it should change:

Drag each answer onto the matching prompt, or click an answer and then click a prompt

Answers
Actions arrive together when several presubmits start.
An assigned worker spends substantial time fetching inputs before process start.
A new executor registers but cannot claim the intended action until its runtime is ready.
Losing one worker slice leaves no capacity for the protected cohort.

3.Which observations should be included when qualifying an autoscaler for a compatible executor pool?

Select all that apply

4.A load test predicted executor CPU saturation. Instead, assigned actions start commands slowly, executor slots remain idle, and CAS-fetch time rises. What is the strongest next conclusion?

Select one answer

0 of 4 answered

Footnotes

  1. Embedded platform testing with Remote Execution — separate x86 and embedded worker pools illustrate capacity that is compatible with different action classes.

  2. State of Swift and iOS in Bazel — simulator manager uses exclusive UI-test and shared logic-test leases, demonstrating scarce non-CPU capacity.

  3. How Snowflake Transformed its C++ and Java Build Systems — trace-based right-sizing, IOPS, scheduler CPU, and transfer bottlenecks in one BuildBarn deployment. 1 2

  4. Buildbarn - Remote execution with 100 to 100,000 CPUs — automatic resource management and worker-side lazy/prefetch input behavior as one backend's capacity implementation.

  5. Ed Schouten on Buildbarn's Evolution and Impact — size-class cache learns suitable worker size and reduces over-allocation to large workers in one implementation.

  6. Post Mortems for 4 Years of Remote Execution — aggressive scale-down plus slow scale-up produced intermittent long queues in production.