P.2.4 Five Properties

Bazel gets speed and correctness by combining several properties. It stays inside the part of the graph you asked for, insists that actions describe their real inputs, reuses results whose inputs are unchanged, and spreads independent work out in parallel.1,2,3 Those user-visible behaviors are easiest to remember as five properties: laziness, slicing, hermeticity, incrementality, and parallelism. Hermeticity, incrementality, and parallelism are standard Bazel vocabulary, while laziness and slicing are the labels this book uses for two closely related scoping behaviors.

How Bazel keeps one build request small, safe, and fast
Scope decides what belongs in the build. Declared inputs and graph edges determine what Bazel can safely reuse or run at the same time.
BUILD REQUEST
Ask for one target
bazel build //app:server
LAZINESS + SLICING
Find only the relevant graph slice
Follow the needed targets and packages. Fetch referenced external repositories.
HERMETICITY
Give actions explicit inputs and tools
Avoid hidden files, host tools, and other machine state
inside that slice, Bazel uses two different checks
INCREMENTALITY
Inputs unchanged?
Reuse a valid prior result. Rebuild only the work affected by a change.
PARALLELISM
Actions independent?
Run them at the same time, locally or on remote workers
Scope limits the work. Hermetic actions make reuse trustworthy. Graph edges reveal safe concurrency.

Scope First: Laziness and Slicing

Bazel starts from a requested result and works outward through the dependencies needed for that result, instead of treating the whole repository as one undifferentiated build-sized blob.4,5 That is the intuition behind laziness: work begins from the goal, not from a full-repo sweep. The graph model itself is introduced in 2.1 Directed Acyclic Graph (DAG), and the specific laziness-vs-slicing behavior is unpacked later in 2.1.2 Laziness & Slicing. Even at this level the effect is visible: unrelated parts of the graph are not supposed to become part of the request just because they exist.

Slicing extends that same goal-directed behavior to the repository boundary. Bazel's large-repository design assumes that BUILD files can be loaded independently rather than only after reading an entire checkout, and external repositories are fetched on demand when labels actually reference them.4,5 The details of where loading stops and execution begins come later in 2.2 Three Phases of a Build. For now, the useful mental model is simple: one target request should select one relevant slice without loading the whole repository.

Laziness asks what belongs to this build at all. Incrementality asks what inside that scope still needs fresh work.4,5,6

Hermeticity Makes Reuse Trustworthy

Once Bazel has identified the relevant slice, it still needs to know whether the result is trustworthy. Hermeticity is that guarantee: with the same source inputs and configuration, the build should produce the same output because it is isolated from host-installed tools, undeclared files, and other ambient machine state.2,3 Hermeticity has two parts — isolation and source identity — and both tie directly to cacheability, reproducibility, and parallel execution.2

Tools count as inputs too. A compiler, interpreter, or downloaded dependency is not background context. It is part of what the action means.1,2 That is why hermeticity is more than a cleanliness preference. It is the foundation that later makes 2.3 Hermeticity & Sandboxing and eventually 6.3 Remote Execution Infrastructure safe instead of lucky.

Incrementality and Parallelism

If actions have explicit inputs, Bazel can reuse old results instead of rerunning everything. Bazel reruns work only when the relevant inputs have changed.3 The deeper engine story comes in 2.4 Caching & Incrementality and especially 2.4.1 Skyframe & Incrementality. After a change Bazel revisits only the affected part of the graph instead of rerunning everything.6

That same graph also exposes independence. When two actions do not depend on each other, Bazel can run them concurrently on one machine. Remote execution simply widens the worker pool without changing the dependency logic.3,7 Hermeticity matters again here: remote workers are only safe when actions arrive with declared inputs and a self-described environment, not with hidden assumptions about the host that happened to work on one laptop.2,7

These five properties are not independent features you toggle one by one. Laziness and slicing keep the request narrow. Hermeticity makes the result trustworthy. Incrementality reuses trustworthy results. Parallelism exploits the remaining independence. Together they explain what Bazel is optimizing every time you type a build command. Later lessons unpack the mechanisms.1,2,6

key takeaway

When a Bazel build feels unusually fast, the explanation is usually some combination of these five properties: the request stayed narrow, the inputs were explicit, old results stayed valid, and independent work could run at the same time. When a Bazel build feels wrong or surprisingly slow, these are also the first five questions worth asking.

Check your understanding · 3 questions

1.This book frames Bazel through five user-visible properties (hermeticity, incrementality, and parallelism are standard Bazel terms, while laziness and slicing are this book's labels). Match each to the behavior it names:

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

Answers
Laziness
Slicing
Hermeticity
Incrementality
Parallelism

2.How do laziness and incrementality differ?

Select one answer

3.True or false: hermeticity and the five-property model.

Choose True or False for each sentence

A compiler, interpreter, or downloaded dependency counts as an input to an action, not as background context.
Remote execution removes the need for hermeticity, since the work runs on someone else's machine.
The five properties are separate product features you toggle on one by one.
0 of 3 answered

Footnotes

  1. Artifact-Based Build Systems — why the artifact model enables safe parallelism, minimal rebuilds, tools as dependencies, sandboxing, and deterministic dependencies 1 2 3

  2. Hermeticity — isolation, source identity, and why explicit inputs enable reproducibility, caching, and parallel execution 1 2 3 4 5 6

  3. Why Bazel? — re-run only when inputs change, parallel execution, sandboxed actions, and same-inputs-same-binary framing 1 2 3 4

  4. External dependencies overview — on-demand fetching of external repositories and deterministic dependency resolution 1 2 3

  5. Challenges of Writing Rules — large-repository assumptions, independently loadable BUILD files, and declared inputs for incremental and remote builds 1 2 3

  6. Skyframe — top-level request evaluation, exact invalidation, change pruning, and parallel node evaluation 1 2 3

  7. Distributed Builds — reproducibility requirements for remote caching and worker-pool execution for remote builds 1 2