The familiar complaint that it works on my machine is a statement about build hermeticity. The build depended on something the developer's machine had and the build server did not — a tool version, an environment variable, a file outside the repository. A hermetic build cannot have that problem, because it does not have access to anything it did not declare.
The property sounds academic and produces very practical benefits.
What changed in 2026
- Supply chain requirements pushed adoption. Buyers and regulators asking for verifiable build provenance made reproducibility a compliance concern rather than an engineering preference.
- Container-based sandboxing became routine. Running builds in isolated environments with only declared inputs mounted moved into ordinary CI practice.
- Toolchain pinning became a baseline expectation. Specifying exact compiler and tool versions, rather than relying on whatever the runner has, became standard.
- Partial hermeticity got respected. Recognition spread that most of the benefit is available without the full commitment of a hermetic build system.
What breaks hermeticity
| Leak |
Effect |
Fix |
| Unpinned toolchain versions |
Different compiler, different output |
Pin exact versions |
| Network fetches during build |
Remote content can change |
Vendor or pre-fetch dependencies |
| Embedded timestamps |
Output differs every build |
Set a fixed build timestamp |
| Hostnames and usernames in output |
Machine-specific artifacts |
Strip or normalize them |
| Absolute paths in artifacts |
Differ by checkout location |
Use relative paths |
| Locale and timezone |
Affects sorting and formatting |
Set explicitly |
| Non-deterministic ordering |
File iteration order varies |
Sort explicitly |
| Parallelism affecting output |
Race in artifact assembly |
Make assembly order-independent |
Most of these are small and individually easy to fix. Timestamps and paths are the two that appear in nearly every codebase, because compilers and packaging tools embed them by default and nobody notices until they compare two builds byte for byte.
Getting most of the benefit
Full hermeticity requires a build system that enforces it, which is a substantial commitment covered in Bazel build explained. You can get most of the practical value without that.
Pin the toolchain. Exact compiler, runtime, and tool versions specified in the repository rather than inherited from the runner. This alone removes the most common source of divergence.
Vendor or lock dependencies. A lockfile with checksums, and dependencies fetched before the build rather than during it. Network access during a build means the build depends on the state of a remote server at that moment.
Sandbox the build. Run it in a container with only the repository and declared tools mounted. This turns implicit dependencies into loud failures rather than silent successes that break elsewhere.
Normalize the obvious sources of variance. Fixed build timestamp, explicit locale, sorted file ordering, relative paths. A handful of settings that remove most byte-level differences.
Verify by building twice. Build the same commit twice on different machines and compare the artifacts. That single test tells you where you actually stand, and it usually surfaces one or two leaks nobody suspected.
Common mistakes
- Assuming a lockfile is sufficient. It pins libraries, not the toolchain or environment.
- Network access during builds. Introduces a dependency on a remote server's current state.
- Never verifying. Most teams have never built twice and compared.
- Chasing full hermeticity without a driver. Pinning and sandboxing capture most of the value.
- Ignoring embedded metadata. Timestamps and paths break byte-identical output for no functional reason.
FAQ
Is hermetic the same as reproducible?
Closely related. Hermetic describes the build's isolation; reproducible describes whether repeated builds produce identical output. Hermeticity is the main route to reproducibility — see reproducible builds guide.
Do I need a special build system?
For enforcement, yes. For most of the benefit, disciplined use of ordinary tooling and containers gets you there.
Does it slow builds down?
Sandboxing adds small overhead. The caching it enables typically saves far more than it costs.
How do I handle code generation?
Generators must themselves be deterministic and pinned, or they become a leak. Committing generated output is a common pragmatic answer.
Where to go next
For the verification property, read reproducible builds guide. For enforcement tooling, Bazel build explained, and for the caching payoff, CI/CD caching strategies.