Chapter Deep Read · SRE · Ch 8
Site Reliability Engineering · Ch 8 · Dinah McNutt · Google · 2016
The app on your phone was 3.2.1 yesterday and is 3.2.2 today. Between an engineer typing the last line of code and that new version actually running on your phone sits a whole sequence of moves: compile, package, test, roll out in stages. Chapter 8 of Google's SRE book is about that stretch of road — and it takes a firm position: this should not be odd-job work that whoever is free picks up. It is a discipline, with dedicated engineers, stated principles and purpose-built tooling, called release engineering.
Think of releasing software as running a pharmaceutical plant. Writing code is developing the formula; releasing is turning that formula into actual pills. What such a plant cares about most is never «how much did we produce today». It is three other things: the same formula, on any production line, months apart, must yield identical pills; every batch must be traceable — who made it, from which raw materials, on which day; and if something goes wrong you must be able to recall exactly that batch rather than shut the whole plant. Software releases want precisely those same three things.
The old way: on release day, the person who knows the machine best logs in and types out a procedure they keep in their head. That hurts in three places. Move to another machine and you can no longer produce the same thing — their laptop happened to have a library nobody else had, hence «but it works on mine». Ship twice a year and each release carries thousands of changes, so when something breaks nobody knows which change did it. And going back to the previous version means building it all over again — tens of minutes at best, and what comes out may not even match what was there before.
① Self-service. The central team builds tools rather than guarding a gate; every team ships on its own schedule. Otherwise that central team becomes the queue the whole company waits in.
② Small steps, often. The more often you ship, the fewer changes ride along each time; when something breaks there are only a handful of suspects, and you spot the culprit at a glance.
③ A sealed kitchen that brings its own ingredients. When compiling, nothing «already lying around on this machine» may be used — every tool and ingredient is pinned to an exact version and stored alongside the source. So the same source, on this machine today and that machine three months from now, bakes the identical loaf. The payoff is concrete: when production is on fire you can go back to the version from three months ago and add just that one fix, instead of dragging along everything everyone else changed since.
④ Turnstiles and a ledger. Who may change code, who may approve a release, who may push to production — all of it enforced by the tools, with every step recorded automatically.
What actually takes production down is often not the program itself but the configuration — the flags, the parameters, the addresses. This chapter's advice: treat configuration as goods too — package it, version it, and be able to roll it back on its own. Shipping config bundled with the program is the least effort, but then flipping one flag means re-releasing the whole program; letting the program read config from somewhere outside at runtime is the most flexible, but then nobody can say for sure which version is actually in effect right now.
Release engineering is not after «ship fast» — it is after shipping something you can reproduce, trace, and roll back on its own: the same source builds the same program on any machine, configuration and program each carry their own version number, and every approval leaves a record. Speed is what naturally follows once those hold. One honest cost: this takes real up-front investment in people and tooling, so a small team copying Google's exact setup is a poor trade — what travels is the principles, not the headcount.
Want the mechanisms, the branching model and the diagrams? → switch to the deep read
SRE Chapter 8 promotes «releasing» from a one-off act at the end of a project to an engineering discipline with its own job function, explicit principles and dedicated tooling. Its four philosophies — self-service, high velocity, hermetic builds, enforcement of policies — all point at one goal: make the path from source to production reproducible, auditable and independently reversible. The counterintuitive lesson is that the foundation is not how fast you ship, but whether the same source builds the same binary on any machine at any time — and that the most underrated element in outages is how configuration gets shipped.
dev / canary / production.The author, Dinah McNutt, is a Google release engineer; the chapter sits in Part II, «Principles», following Chapter 7 on the evolution of automation at Google and leading into Chapter 9 on simplicity. It meshes directly with Chapter 3 («Embracing Risk») and Chapter 4 (SLOs): the error budget decides whether you dare ship, release engineering decides whether you can ship safely. Its real-world counterparts are CI/CD pipelines, Bazel, container registries, Spinnaker / Argo, and later on software supply-chain security.
In most companies «releasing» looks like this: at the end of the project, whoever knows the environment best follows a half-written procedure to upload a package, edit a few configs and restart. That works while the team is small and collapses once it is not. Google's scale gives a reference point: their 2016 published figures were over 2 billion lines of code in a single repository and roughly 40,000 commits per working day (Potvin & Levenberg, CACM 2016). At that size, manual releasing cannot even enumerate which commits are shipping today.
It collapses in four places, each answered by one part of the chapter:
The cost of not fixing it is quantified in this book's own introduction: SRE has found that roughly 70% of outages are due to changes in a live system. The release path is itself the number-one risk surface for reliability.
The chapter opens by asserting that release engineering is a distinct engineering discipline, not somebody's side task. Google's release engineers understand source control, compilers and build configuration languages, automated build tooling, package managers and installers — and they sit with product developers and SREs at the start of a project to settle how this service will be built, shipped, rolled back and configured. The counterintuitive part is right there: most teams treat releasing as cleanup after development, whereas this chapter's position is that how you release is an architectural decision. Release engineering is not an afterthought — budgeting for it at the beginning is far cheaper than retrofitting a grown system.
These four are the chapter's skeleton, and they interlock: drop one and the other three leak.
① Self-service. The central release team builds tools and defines best practices; it does not press everyone's release button. The reasoning is plain: at a scale of thousands of services, any central step requiring a human becomes a queue.
② High velocity. User-facing software should ship frequently, ideally as Push on Green — if all tests pass, that build goes out. Some Google teams build hourly and then select a build to deploy. The real payoff of frequent releases is not that features arrive sooner, but that adjacent versions differ by very little: the suspect set shrinks from thousands of commits to dozens, which makes both diagnosis and rollback cheap.
③ Hermetic builds. The build is insensitive to what the build machine has installed — compilers, libraries and toolchain are pinned to specific versions and kept under version control, and the process is self-contained. The benefit lands in two scenarios: reproduction (take a month-old revision and build a binary byte-identical to what was in production) and hot-fixing (return to that revision and cherry-pick one patch, without carrying a month of everyone else's changes into production).
④ Enforcement of policies and procedures. «Who may do what» stops being a verbal agreement and becomes a gated operation in the tooling: approving a source change, creating a release branch, approving a cherry-pick, pushing a version to production, editing the build configuration — each behind an ACL. The by-product matters just as much: an automatically generated audit trail, so every release can answer which commits it contains, who approved it and when it went out.
The branching model has just two rules. All code is committed to the head of the mainline — that is trunk-based development. And releases are not cut from the mainline directly; a release branch is taken at a specific revision, and changes on that branch are never merged back — to fix a bug you fix it on the mainline first, then cherry-pick that commit onto the branch.
Why build it this way? Releasing straight from mainline head means the contents of your release keep moving — by the time the build runs, dozens of other people's commits have landed. Branching freezes the release contents at one definite revision, and the one-way cherry-pick guarantees that fixing one bug brings in exactly that one fix. This is also where hermetic builds pay off: rebuilding on the branch produces a binary byte-identical to the original.
Testing happens twice: continuous integration runs unit tests against the mainline on every submit, catching broken builds fast; and at release time all unit tests are re-run at the branch revision — that pass is not only about finding bugs, but about producing an audit record bound to this specific release.
Build outputs are packaged by Google's package manager, MPM (Midas Package Manager): binaries, data files and necessary config in one versioned unit, uniquely identified by name + version + build ID and signed to prove provenance. The key design is the label: nameplates such as dev, canary and production can be attached to a package version, and labels can be moved. So «which version is production running» stops being something a human remembers and becomes a single query, while releasing and rolling back reduce to moving a label to a different package version — no rebuild required. Insisting on image digests rather than latest in Kubernetes today is the same idea in modern dress.
Rapid is Google's automated release system: a blueprint describes the project's build targets, test targets and deployment method, and Rapid then automatically creates the release branch, runs the hermetic build, runs tests in parallel, produces and signs MPM packages and applies labels — with the work itself running as jobs on Borg.
Sisyphus is a general-purpose rollout automation framework developed by SRE: a rollout is defined as a sequence of tasks, expressing anything from «push everywhere at once» to «phase across clusters, bake between batches, canary first». The division of labour is clean — Rapid produces a trustworthy, labelled artifact; Sisyphus decides the pace and order in which it reaches production. That separation is itself portable advice: the correctness of the artifact and risk control during the spread are two different problems, and they do not belong in one script.
The chapter says it plainly: configuration management is a notoriously subtle source of instability. The difficulty is that configuration and binaries have mismatched lifecycles — the binary is frozen on a release branch while the config wants to change at any moment. The book lists four schemes, which are really four points along a coupling axis.
The concrete costs of all four are in Table 1 below. The one point worth stating here: the chapter's recommendation is to package configuration separately — applying the same hermetic, versioned discipline to config, so binary and configuration each carry a version, ship independently, and roll back independently. Helm charts, Kustomize and GitOps all descend from this idea.
Table 1 · The four places configuration can live (the chapter's own taxonomy)
| Scheme | Re-release the binary to change config? | Independent rollback? | Main cost | Fits |
|---|---|---|---|---|
| Config at mainline head | No | Possible, but version pairing is fuzzy | Config skew: branch binary against head config | The earliest approach; weak binary/config coupling |
| Same package as binary | Yes, the full pipeline | Only together with the binary | Inflexible; flipping one flag is expensive | Few config files that rarely change |
| Separate config package | No | Yes, with explicit versions | A second release path to maintain | The chapter's recommended default; today's Helm / GitOps |
| External store, read at runtime | No, and it takes effect immediately | Depends on that store's own versioning | Escapes the release flow's versioning and audit | Rate limits, feature flags — config that must be dynamic |
Table 2 · Release cadence: what each gear actually costs
| Push on Green | Release train (fixed cadence) | Big release (quarterly / half-yearly) | |
|---|---|---|---|
| Changes per version | A few to a few dozen commits | Hundreds | Thousands |
| Diagnosis when it breaks | Tiny suspect set | Bisect; hours | Needle in a haystack; days |
| Rollback granularity | One version ≈ a few commits | One version = a week of features | Effectively irreversible; fix forward |
| Prerequisites | Tests strong enough to be the only gate + canary + fast rollback | Reasonably complete regression suite | Manual acceptance + release windows |
| Fits | Server-side systems you can canary and revert | Mobile apps needing store review | Shrink-wrapped software, embedded firmware |
Table 3 · Branching: why Google picked mainline plus a one-way release branch
| Ship straight from mainline head | Mainline + one-way release branch (Google) | Long-lived branches merged both ways (GitFlow-style) | |
|---|---|---|---|
| Release contents | Moving until the build runs | Frozen at a definite revision | Whatever got merged; hard to state |
| Unrelated changes riding along | High | Low: one cherry-picked fix at a time | High: a merge drags in whole histories |
| Hot-fix cost | Low, but ships other people's work too | Low: branch rev plus one patch | High: resolve merge conflicts first |
| Branch upkeep | None | Low (branches short-lived and one-way) | High, and it climbs with branch age |
| Prerequisites | Very strong CI and canarying | Hermetic builds, or you cannot rebuild the same binary | None in particular |
How should a small team cut this down? Hermetic builds and independently versioned configuration have the best return and are worth doing at any size (a pinned base image plus dependency lockfiles gets you most of the way). Self-service is satisfied for free while headcount is low. Enforcement can start from a single minimal rule: production deploys require one code review and leave a record of who approved. What should not be copied is the org chart — a dedicated release engineering team is the answer at a scale of thousands of services.
The value of this chapter is that it states the criteria underneath every CI/CD practice in use today. Use it as a checklist against your own pipeline: can you take a three-month-old commit and reproduce the binary that was running then (hermetic builds)? Can you say in one sentence which artifact production is running, which commits are in it and who approved it (labels + audit)? Does changing one timeout require re-releasing the whole program (config packages)? Is the release button held by a central team or by each team (self-service)?
All four internal tools have public counterparts now: Blaze → Bazel, MPM packages + labels → container images + digests + registries, Rapid → GitHub Actions / Cloud Build and similar pipelines, Sisyphus → Spinnaker and Argo Rollouts. In an interview, answering «how do you release» with «builds are reproducible, config is versioned separately, producing and spreading are separate steps, and every step has an ACL and an audit trail» already lands at this chapter's level.
2 billion lines of code in one repository and roughly 40,000 commits per working day — at that size, trunk-based development plus self-service releasing is not a preference but the only shape that holds. R. Potvin & J. Levenberg, CACM, 2016 ↗① In one sentence: release engineering is a discipline of its own, aimed at making the path from source to production reproducible, auditable and independently reversible — speed is the result, not the goal.
② Four principles: self-service (the centre builds tools, not gates), high velocity (Push on Green, shrinking the delta per version), hermetic builds (independent of the build machine), enforcement (gated operations plus an automatic audit trail).
③ Branching: trunk-based development plus a release branch cut at a revision, never merged back, fixed by one-way cherry-picks — freezing release contents without dragging in unrelated changes.
④ Two rounds of testing: CI against the mainline on every submit; all unit tests re-run at the branch revision at release time, generating an audit record.
⑤ Packaging: packages are uniquely identified by name + version + build ID and signed; movable labels turn «which version is in production» into a query, and rollback into moving a label.
⑥ Rapid produces, Sisyphus spreads — artifact correctness and rollout risk control are separate problems.
⑦ Configuration is the subtle number-one source of instability; the four schemes are points on a coupling axis, and a separate config package is the recommended default.
⑧ Release engineering is not an afterthought: budgeting at the start beats retrofitting later. Today's counterparts are Bazel, image digests, GitHub Actions, Spinnaker / Argo, and the supply-chain layer that SLSA added on top.