Part 1 · 2 chapters · ~20 min
Monorepos and Build Systems
The hermetic build as a pure function of declared inputs (targets, sandboxes, content addressing, remote cache and execution, exact affected sets) with its cost and the signal that it pays, and operating a monorepo at scale: virtual file systems, code search, OWNERS, a merge queue that keeps the trunk green, and automatic reverts.
3
A hermetic build
the build as a pure function
- The target: a BUILD file declares sources, dependencies and toolchain; an import of something not in
depsfails the build. The dependency graph stays true because the build refuses what it does not know (the Architecture course part 0's boundaries, enforced by the build). - The sandbox: an action sees only its declared inputs, a scrubbed environment and a toolchain pinned by hash. A build that depends on something undeclared fails everywhere, not on one laptop; "works on my machine" is structurally impossible.
- Content addressing: the action key is the hash of inputs and command; outputs live under that key; two engineers at the same commit share outputs; one changed file re-keys its target and downstream and nothing else. The Architecture course part 1's cache hierarchy with every level present and provably correct.
- Remote cache and execution: CI populates a company-wide cache; laptops pull from it; a farm runs actions in parallel so a clean build of the world takes minutes. A local build is mostly downloading what others already produced.
- Affected-only, exactly: "what does this change affect" is a graph query (
bazel query rdeps), so CI builds and tests exactly the affected targets. Nx and Turborepo approximate with file hashes; Bazel computes from the declared graph. - The cost and the signal: everything declared (npm through a lockfile translation; every generated file a declared action), a BUILD file per package, weeks to learn, a build team, slow first builds for small projects. It pays when build failures are environment-specific, CI runs the world on every change, and nobody can state the dependency graph.
A HERMETIC BUILD
every input declared, every action sandboxed, every output a function of its inputs, the same bytes on every machine
swipe the figure sideways, or tap expand for full screen
1/6
the target
The target: a BUILD file next to the code declares ts_project(name = "checkout", srcs = glob(["*.ts", "*.tsx"]), deps = ["//packages/ui-kit", "//packages/api-client", "@npm//react"]). The dependency list is the whole dependency list: an import of something not in deps fails the build, which is how the dependency graph stays true (the Architecture course part 0's boundaries, enforced by the build rather than a lint).
4
Operating a monorepo at scale
the repo as a system with a team
- Version control: a virtual file system (Piper and CitC, Sapling and EdenFS, VFS for Git) materialises files on access; sparse checkouts per team; a linear trunk-based history (squash on land) so bisect works; branches short-lived or absent.
- Code search: indexed and cross-referenced over the whole repo, per commit, with structural queries fed by the build graph. "Can we delete this?" is a search, not a meeting; codemods (part 4) are targeted by it.
- Ownership: OWNERS files per directory, inherited up the tree, enforced by the review tool (every changed file needs an approving owner); cross-cutting changes split by owner or approved under a global policy; owners are the on-call for their surface (part 8).
- The merge queue: approved changes are rebased on the current head, built and tested on their affected targets (mostly cached), and landed only if green, in batches with bisection on failure, at thousands a day. The trunk is never red for longer than a revert takes.
- Reverts and culprits: automatic culprit finding over a failed batch, automatic revert with a notification, re-land after the fix. A revert is a mechanism, not a judgement; the trunk's greenness is a machine's job.
- Costs and buys: a VCS team, a search team, a merge queue that is itself a distributed system, and a culture that follows the tooling. It buys a trunk deployable every minute, atomic cross-cutting changes across the company, and one answer to "what is the current state of the code". Below this scale, git and a task runner suffice (the Architecture course part 4).
the signal
You have reached this scale when a fresh clone takes an hour, "who imports this" needs a grep that takes ten minutes, and the trunk is red for hours a week. Before that, the ideas (declared deps, affected-only CI, OWNERS, a queue) transfer with ordinary tools.
OPERATING A MONOREPO AT SCALE
version control, code search, ownership, and the trunk that never breaks
swipe the figure sideways, or tap expand for full screen
1/6
version control
Version control: a virtual file system over the repo (Google's Piper with CitC, Meta's Sapling with EdenFS, Microsoft's VFS for Git) so a checkout materialises files on access; sparse checkouts for the directories a team works in; a history that is linear (trunk-based, squash on land) so bisecting works. Branches are short-lived or absent; the trunk is the only long-lived line.