NativeLink
Concepts

History and licensing

What NativeLink was built to replace, the three properties that drove the rewrite, and exactly how the source is licensed.

Who this is for: anyone evaluating NativeLink against an existing build farm, and anyone who needs to answer a licensing question precisely. What you'll have at the end: the design pressures that produced the current system, and a file-by-file account of what license applies. Time: ten minutes.

Remote build execution is not a new idea. Google shipped an internal version of it long before the Remote Execution API was published, and by the early 2020s there were several open implementations of the published protocol. NativeLink started in December 2020 as a Rust implementation of the CAS half of that protocol (first called Rust CAS, then Turbo Cache from April 2022), was renamed to NativeLink in December 2023 (the cas executable became nativelink at the same time), and cut its first tagged release, 0.1.0, on 2023-12-20. The argument for writing a new implementation rather than running an existing one is the one below: the protocol is narrow enough that a rewrite is tractable, and what was expensive in the existing options was the substrate.

What the existing options traded away

FamilyStrengthThe recurring problem
JVM-based serversMature, complete, well understoodTail latency under GC pressure, and a memory footprint that makes horizontal scaling the only answer
Go servicesFast on the happy path, straightforward to operateContention on hot artifacts and on control-plane locks, which shows up as a cluster-wide stall rather than a slow request
Proprietary cloudsFast, someone else operates itNo source access, and pricing that scales with the thing you are trying to do more of

Two of those three problems are runtime problems rather than design problems. That observation is the whole argument for the rewrite: the protocol was fine, the storage model was fine, and what was expensive was the substrate.

The three properties that drove the design

Predictable latency. In a build system, the p99 is the number developers experience: a single stalled action blocks everything downstream of it in the graph. Removing the garbage collector removes a class of latency spike that is very hard to tune away rather than eliminate.

Memory safety without a runtime. A build cache that serves a wrong artifact is a far worse incident than one that serves no artifact: it is silent, and it propagates to everyone who pulls from the cache. Rust removes the memory-corruption path to that outcome at compile time, without adding a managed runtime back in.

One binary, many roles. CAS, action cache, scheduler and worker are the same executable with different configuration. It makes the small deployment trivial and the large deployment a scaling exercise rather than a re-architecture. Architecture covers what that means in practice, and the deep dive covers what the binary does with the config it is handed.

A fourth property arrived with the project rather than driving it: because the toolchain definitions could be shared between the local machine and the remote workers, the same hermetic build could run in both places. That became Local Remote Execution, and it is the part of NativeLink with no real equivalent elsewhere.

Licensing, precisely

This question gets answered vaguely often enough to be worth stating exactly.

The repository's root

LICENSE

is the Functional Source License 1.1 with an Apache 2.0 future grant (FSL-1.1-Apache-2.0). In practice that means two things. You may use, read, modify and deploy the software for any purpose except offering it to others as a competing commercial product or service. And each release converts to plain Apache 2.0 on the second anniversary of its publication; the grant is irrevocable and written into the license itself, not a promise made elsewhere.

Five files are Business Source License instead, and they are worth knowing by name because they are the ones an internal license review will flag:

File or moduleWhat it is
nativelink-util/src/metrics.rsThe metrics collection layer
nativelink-worker/src/persistent_worker/: mod.rs, pool.rs, live_worker.rs, protocol.rsRemote persistent workers

Copy the header, don't recall it

When you add a file, copy the license header from the file next to it rather than from memory. A new file under persistent_worker/ needs the BUSL header; a new file in the same crate's src/ does not.

Nothing in the repository requires a contributor license agreement or a Developer Certificate of Origin sign-off. What it does require is cryptographically signed commits; see the contribution guidelines.

Versioning

NativeLink versions look like SemVer and are not.

module()

declares compatibility_level = 0, which is Bazel's way of saying no compatibility promise is being made across versions. The config schema and the metrics surface have both changed in minor releases; the changelog marks such entries as breaking.

The wire protocol is the exception, and it is the one that matters for most deployments: NativeLink implements the Remote Execution API, which is versioned upstream and changes slowly. A client that worked against one NativeLink release will keep working against the next. Release and versioning is the page for the details.

Why these docs were rewritten

The previous documentation accumulated during the period when the project was changing shape weekly. It described commands that no longer existed, components that had been renamed, and performance numbers with no source. This rewrite holds every page to the same contract: every command is run or schema-checked before it ships, every claim about the code links to the code, and pages that cannot meet that bar say what they do not know.

The source lives in

content/docs/

and corrections are the most welcome kind of pull request. Working on documentation is the how.

Common questions

NextLocal Remote Execution

The idea that came out of the rewrite rather than driving it: the same hermetic toolchain on your laptop and on the remote workers.

On this page