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
| Family | Strength | The recurring problem |
|---|---|---|
| JVM-based servers | Mature, complete, well understood | Tail latency under GC pressure, and a memory footprint that makes horizontal scaling the only answer |
| Go services | Fast on the happy path, straightforward to operate | Contention on hot artifacts and on control-plane locks, which shows up as a cluster-wide stall rather than a slow request |
| Proprietary clouds | Fast, someone else operates it | No 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
LICENSEis 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 module | What it is |
|---|---|
nativelink-util/src/metrics.rs | The metrics collection layer |
nativelink-worker/src/persistent_worker/: mod.rs, pool.rs, live_worker.rs, protocol.rs | Remote 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
The idea that came out of the rewrite rather than driving it: the same hermetic toolchain on your laptop and on the remote workers.
Local Remote Execution
What LRE actually is: a way to make your local toolchain and your remote workers the same toolchain, so both sides share one cache.
Configuration reference
Every knob in the NativeLink JSON5 configuration — types, defaults, and links to source, autogenerated from the Rust config crate.