Change Size: Why Small Changes Are Safer, and When They Are Not
Small changes make cause and effect legible, review effective and rollback cheap — but diff size and blast radius are different axes, and confusing them is how one-line outages happen.
The question, the obvious approach, and why it breaks
Every lesson starts where the work starts: an operational problem, a first attempt that is entirely reasonable, and the way production disagrees with it.
Why does shipping smaller changes more often make a system safer, and what does "small" fail to guarantee?
The cost of a bad change is paid in the time it takes to identify which change was bad and to undo it. Both of those grow with how much shipped at once, and both are paid at the worst moment.
Batch changes into a weekly release. Fewer releases means fewer opportunities for something to go wrong, and one careful, well-tested release is safer than twenty casual ones.
Fewer releases does not mean less change. It means the same change arrives in larger units, so each release carries more suspects and a harder attribution problem (Change Correlation).
- Fewer releases does not mean less change. It means the same change arrives in larger units, so each release carries more suspects and a harder attribution problem (Change Correlation).
- Review effectiveness falls off sharply with size. A reviewer reading a very large diff is not reviewing it, they are approving it — and everyone knows this while continuing to do it.
- Rollback becomes coarse: reverting the release removes twenty good changes to undo one bad one, so the pressure is to fix forward under load instead (Roll Forward: When Going Back Is the Harder Option).
- The interactions between changes are the part that grows fastest. Twenty independent changes have far more pairwise interactions than four, and interactions are where the surprises are.
- Large releases feel risky, so they attract process; process makes them slower; slowness makes them larger. The batch size and the ceremony reinforce each other.
What is actually happening
Underneath the tooling, which is the part that survives a change of tool.
- A deploy is an experiment with one hypothesis: the system still works. The number of independent changes in it is the number of candidate explanations when the hypothesis fails, and diagnosis time scales with that number rather than with lines of code.
- Small changes make three things cheap that are otherwise expensive: attribution (one suspect), review (a reviewer can actually hold it in their head), and reversal (undoing one thing costs one thing).
- The dynamic that produces large batches is a loop: deploys are expensive → deploy less often → each release is larger → releases are riskier → add process → deploys become more expensive. It runs in both directions, which is why making deploys cheap is the highest-leverage intervention available (The Deployment Pipeline).
- Diff size and blast radius are orthogonal. A one-character change to a global configuration value, a flag default, a DNS record or a shared library reaches everyone immediately. A large feature behind a flag reaches nobody. Estimating risk from the diff is the error this lesson exists to prevent (Blast Radius: If This Is Wrong, How Much Does It Affect?).
- Small changes reduce the *probability* of a bad deploy and the *cost* of diagnosis. They do not reduce the reach of any individual change, which is what containment mechanisms are for.
The same work, two batch sizes
Nothing differs here except how the work was grouped. The right-hand column is not more careful — it is the same changes with a shorter distance between cause and effect.
20 changes merged over 5 days
-> one release, one deploy
-> error rate rises
-> which of 20? bisect, read diffs, ask people
-> revert the release: lose 19 good changes
-> next week's release now has 21 changeschange merged -> deployed within the hour
-> error rate rises
-> one suspect, named on the timeline
-> revert one change
-> the other 19 are unaffected
-> next change ships normallyBoth shapes contain the same defect. What differs is the number of candidate explanations at the moment it is found, and the cost of the reversal — one change instead of nineteen. That is why smaller batches reduce incident *duration* even when they do not reduce incident *frequency*.
The loop that produces large batches
Batch size is not a discipline problem. It is the equilibrium of a feedback loop, and every arrow is a rational local decision. That is why exhorting people to ship smaller does not work and making deploys cheap does.
Size is not reach
This table is the correction to the lesson's own headline. Every row on the left is tiny and reaches everyone; every row on the right is large and reaches almost nobody. Judging risk by diff size gets all eight of these exactly backwards.
| Change | Diff size | Blast radius | Why they differ |
|---|---|---|---|
| Global configuration value edited | One line | everyone | Configuration usually has no rollout mechanism; every instance reads the new value at once (A Config Change Is a Production Change) |
| Feature flag default changed | One line, or none — a console click | everyone | A flag flip has the reach of a deploy, in seconds, with none of the pipeline (Feature Flags: Deploy Is Not Release) |
| DNS record or TTL change | One record | everyone, and slow to reverse | Propagation is global and eventual, and reversal is a second propagation (DNS in Production) |
| Shared library version bump | One line in a manifest | everyone who depends on it | The radius follows the dependency graph, not the diff (Dependency Management) |
| Index dropped from a large table | One statement | everyone, immediately | Query plans change fleet-wide the moment it commits (Destructive Migrations) |
| IAM or authentication policy change | A few lines | everyone, including responders | Authentication is a dependency of everything, including your own tooling (Break-Glass Access) |
| A large new feature behind a flag, default off | Thousands of lines | nobody, until released | The code is deployed and inert; reach is set by the targeting rule |
| A rewritten internal module with identical behaviour | Very large | one-percent under a canary | Ordinary code change, ordinary containment — the size affects review effort, not reach |
How to do it properly
Most important first.
- Ship in the smallest unit that is independently valuable and independently revertible.
- Split by risk as well as by size: separate migrations from code, config from artifact, dependency upgrades from behaviour changes. Each of those pairs has a different failure signature, and separating them makes the signature legible (A Migration and a Deploy Are One Event).
- Make deploys cheap and boring. Cost per deploy is the variable that determines batch size, and it is the one you control (Continuous Delivery).
- Use flags to keep a large feature's *deploy* small: many small merges that are inert, then one release decision (Feature Flags: Deploy Is Not Release).
- Estimate blast radius separately from size, every time. Ask what it touches, not how big it is.
- Treat a long-lived branch as an accumulating batch — the merge is the deploy, and its size is the size of everything on it (Long-Lived Branches).
How much can this affect
Every production change has a blast radius. Stated as a scale so it is comparable between changes rather than adjectival — and paired with what actually contains it, because a wide scope with a real containment mechanism is a different situation from a wide scope with none.
A small change is contained by whatever exposure mechanism the deploy uses, plus the fact that reversing it costs one revert. That containment is entirely absent when the small change touches a shared surface — config, flag default, shared library, DNS — where reach is set by the surface and not by the size, and the honest scope becomes everyone.
What can go wrong
- Small changes shipped so frequently that a rollout is always in progress, so several partially rolled-out changes overlap and attribution is as hard as with a batch.
- A "small" change with global reach — config, flag default, shared library, DNS — treated as low risk because the diff was one line.
- Splitting a change into pieces that are not independently valid, so an intermediate state is broken and the safety of small steps is lost.
- Per-change overhead — approvals, forms, sign-offs — that makes small changes uneconomic and pushes teams back to batching (Guardrails, Not Gates).
- Frequent deploys without deploy annotations, so the debugging benefit of knowing exactly what changed is not actually available (Deploys on the Same Timeline as the Symptom).
- Small changes used as an argument against review depth: fast and unreviewed is a different thing from small and reviewed.
- "Small change, low risk." Size and reach are different axes. Ask what it touches.
- "Deploying more often means more incidents." It means more deploys and fewer suspects per incident. The rate of *bad changes* is a property of the changes, not of the deploy frequency.
- "We batch because we are careful." Batching converts many small risks into one large one and makes each harder to diagnose. That is the opposite of careful, however it feels.
- "Small changes remove the need for staged rollout." They make attribution and rollback cheap. They do not bound reach, which is a separate problem with separate mechanisms (Reducing Blast Radius).
Operating it
Evidence is the signal, not the intention. Rollback is sometimes 'you cannot, and that is the point'.
- Time from merge to production is short and consistent, and it is measured rather than estimated (Continuous Delivery).
- During the last few incidents, identifying the responsible change took minutes rather than a bisect — that is the payoff, and it is observable.
- Rollbacks are uneventful and reverse one thing, rather than being a negotiation about which good changes to lose.
- The main benefit: reverting one small change removes one small change. There is no negotiation about collateral, so the decision to roll back is easy and therefore made early.
- Small changes also make the rollback target recent and well understood, which makes forward compatibility much more likely to hold (Version Coexistence: N and N+1, in Both Directions).
- The caveat is that a small change with global reach still needs a full reversal plan. Small does not mean self-contained (Rollback: Only Useful If It Is Actually Safe).
- Automate everything that makes a deploy expensive, because deploy cost sets batch size. That is the whole intervention.
- Automate change annotation so every deploy is visible on the timelines an operator reads (Deploys on the Same Timeline as the Symptom).
- Do not automate away review for small changes. Small is the condition that makes review effective, not a reason to skip it.
- More deploys means more rollout windows, more mixed-version periods, and more total time spent in a state where two versions coexist (Version Coexistence: N and N+1, in Both Directions).
- Splitting work into independently valid pieces is real design effort, and sometimes the intermediate states are genuinely awkward to define.
- A high deploy rate demands automation, observability and reversibility that a weekly release does not — the practice is cheap only after that investment.
Where this applies
This domain is unusually tool- and organisation-dependent. These labels say what each claim is specific to, and what a different platform, provider or organisation does instead.
- GENERALThe attribution argument — fewer changes means fewer suspects — is arithmetic and holds on any stack and at any scale.
- ORG-SPECIFICHow small a change may be is often set by governance rather than engineering: mandated approvals, change windows or release boards impose a per-change cost that makes batching rational. Where that is fixed, the available lever is reducing the cost of each approval — pre-approved change classes, standing authorisation for low-radius changes — rather than arguing for more deploys (Change Management).
Where the depth lives
This domain teaches delivery and operation, and hands the mechanism off to the domain that owns it.
- — Testing & Reliability Engineering — how test suite speed sets the floor on how cheap a deploy can be.