Type 1 vs Type 2 Decisions
Teams spend the caution meant for irreversible decisions on ones they could easily undo.
Ask whether you can undo it before you ask how sure you are
Print on A4 at 100% scale, double-sided, flipping on the long edge, then cut along the faint lines. Each card has the law on the front and its counter-force and what to do on the back.
Teams spend the caution meant for irreversible decisions on ones they could easily undo.
Ask whether you can undo it before you ask how sure you are
A broken rule that causes no immediate harm quietly becomes the new normal.
An exception that caused no harm is not proof that it is safe
Code or rules whose origin you don't know look like clutter, which makes them tempting to delete.
Learn why it is there before you remove it, but set a deadline on the search
Faced with a real anomaly, people reach for the familiar, harmless explanation.
Ask what it would mean if it were real before you explain it away
Discussion goes to the parts everyone understands, not the parts that matter.
Spend the discussion where the risk is, not where the opinions are
Complex systems that work usually grew from simple systems that worked; designed ones rarely do.
Distrust a design that has to work all at once to work at all
Systems end up shaped like the communication paths of the teams that build them.
To change the architecture, change the teams first
With enough users, every observable behavior of a system, bugs included, is depended on.
Assume everything users can observe has been promised
Adding people to a late project tends to make it later, because ramp-up and coordination cost more than they add.
When a project is late, cut scope or move the date before adding people
§ 3 Chesterton's Fence
taken absolutely the rule removes nothing ever, because the reason is sometimes gone with the person who had it
You are forbidden from removing a "fence" (code/rule) until you can explain why it was put there — but put a deadline on the search. When it expires, take the fence down behind a flag, with a rollback ready, and watch what complains.
§ 2 Normalization of Deviance
not every deviation is a precursor; a team that investigates every one stops shipping and starts ignoring the investigations, so an agreed allowance keeps the real alarms visible
When a check fails and you ship anyway, write down who decided, why, and when it will be reviewed. In postmortems, ask which past exceptions made this one look normal.
§ 1 Type 1 vs Type 2 Decisions
many decisions look reversible and are not (a public API, a data format written to disk, a price announced to customers), and fast-tracking them ships a commitment you cannot take back
Classify a decision before you schedule the debate. If you could undo it within a sprint at a cost you would accept, let one person or a small group decide it this week. Keep the full review for decisions that touch persisted data, public interfaces, security, or something already promised to customers.
§ 6 Gall's Law
a payments ledger, a safety interlock or a protocol with many independent implementers has to be right in its first version, and evolving it in production means running the incorrect versions on real money or real people
Ship the smallest version that does one real job end to end, and grow it in steps that each keep it working. When a rewrite is proposed, ask which working system it will grow from.
§ 5 Law of Triviality
the small, easy-to-discuss things are sometimes the permanent ones; a public API name or a config key is cheap to argue about and expensive to change after release
Move everything a tool can decide (format, import order, lint rules) out of human review. When a review thread is mostly style, stop it and ask one question about the riskiest part of the change. In meetings, put the most expensive or riskiest item first on the agenda.
§ 4 Normalcy Bias
treating every anomaly as the start of a collapse burns out the on-call rotation, and an engineer who escalates everything is soon ignored; most anomalies really are the usual thing
When an error occurs, ask: "If this were the start of a total system collapse, what would the next 10 minutes look like?" If that scares you, investigate now.
§ 9 Brooks' Law
Brooks introduced the law as "oversimplifying outrageously": people added early, to work that splits cleanly with little communication, do speed it up
If a project is late, cut scope or move the date first. Add people only to work that splits cleanly and that they can start without a veteran's daily help, and do it early, not in the last month.
§ 8 Hyrum's Law
if every observable behavior were sacred nothing could ever change, so vary what you never promised — randomized iteration order, planned outages — and the dependency never forms
"Internal" doesn't exist once you have users. Version and feature-flag what you promise; deliberately vary what you do not, so nobody can build on it in the first place.
§ 7 Conway's Law
giving every team its own service imports the costs of a distributed system; sometimes one team should own one deployable unit whatever the org chart says
If you want a modular architecture, create modular, independent teams first. Do not fight the org chart with code.
People ask for help with their attempted fix instead of the problem they actually have.
Look past the question to what the asker is trying to do
Systems that assume every peer follows the spec exactly tend to be brittle against the first one that doesn't.
Be exact in what you send, and explicit about what you tolerate
People read malice into delays and bugs that are better explained by fatigue or missing context.
Look for what was missing before you look for who meant it
Work takes longer than estimated, even when the estimate already allows for that.
Trust what past work actually took over how this work looks today
A number stops measuring well once people are rewarded for moving it.
Watch the outcome, not the number that stands for it
For ideas and software, the longer something has survived, the longer it is likely to last.
For things that must last, bet on what has already lasted
Teams keep funding a failing project because of what they have already spent on it.
Decide on what lies ahead, not on what is already spent
Teams copy another company's practices without the conditions that made them work.
Copy a practice only if you have the problem it solved
Speeding up one part of a system barely helps when the bottleneck is somewhere else.
Find the bottleneck before you speed anything up
§ 12 Hanlon's Razor
some failures are malicious, and an attacker relies on looking like an honest mistake; the xz utils backdoor (2024) came from a helpful, patient contributor
Before you attribute a failure to intent, find out what the person could see at the time, and fix what was missing. Raise intent only with evidence, and then privately.
§ 11 Postel's Law
tolerating malformed input lets broken senders ship, every receiver then has to copy the tolerance, and the de facto protocol drifts from the spec; the IAB now asks protocol designers to keep maintaining their specifications so tolerance does not become permanent, and calls ignoring faulty input almost always the wrong fix
Send exactly what the spec says. Accept small deviations at the edge only where they are documented and logged, and set a date to stop accepting them.
§ 10 XY Problem
sometimes the asker has already weighed X and needs Y for reasons they do not owe you; interrogating every question is patronizing and slows down the people who knew what they were doing
When someone asks "How do I do Y?", answer Y if it is cheap, then ask once what they are trying to achieve.
§ 15 Lindy Effect
age measures survival under past conditions; when the hardware, scale or threat model shifts, the long-lived choice can be the one that was optimized for a world that no longer exists
If you need a stable system for 10 years, choose a technology that has already been around for 10 years (e.g., PostgreSQL over a new NoSQL).
§ 14 Goodhart's Law
you still have to steer by numbers; several measures that are hard to game together, read alongside the work itself, keep the signal longer than refusing to measure
Never use a single metric to judge performance. Observe the system's output, not its proxies.
§ 13 Hofstadter's Law
padding an estimate does not bank the slack; the work expands into it, so a generous estimate can be as late as a tight one
Estimate from what similar past work actually took, not from how this work looks today. Write down, at the start, which scope you will cut when the date is at risk, and re-estimate when a milestone lands rather than only at the end.
§ 18 Amdahl's Law
when the problem grows with the machine, the serial fraction shrinks and speedup keeps climbing
Profile first; time usually concentrates in a small part of the code, often around 1% of it taking 90% of the time. Optimize that part only, and ignore the rest.
§ 17 Cargo Cult Engineering
deriving everything from first principles throws away other people's hard-won lessons; copying a practice that is widely known to work is usually cheaper than reinventing it
Do not adopt a tool/process because Google uses it. Adopt it because you have the exact problem Google had at that scale.
§ 16 Sunk Cost Fallacy
many worthwhile projects look worst in the middle, and a team that kills everything at the first trough never finishes anything; past investment says nothing, but the remaining cost to finish may be small
Ask: "If we started today with zero investment, would we choose this path?" If no, kill it.
Every non-trivial abstraction eventually exposes the details it was meant to hide.
Use the abstraction, but keep someone who knows what is under it
Most of the effect comes from a small share of the causes, such as bugs in a few modules.
Find the few causes that matter and start there
Conclusions drawn only from successes ignore the failures that used the same strategy.
Count the failures before you copy the success
Debugging is harder than writing, so code written at your cleverest is beyond your debugging.
Write code a tired stranger could debug
An incentive meant to reduce a problem rewards people for producing more of it.
Ask how each incentive could be earned without fixing anything
People keep only about 150 stable relationships. Engineers extrapolate: past shared context, added headcount goes to coordination.
When people lose track of each other's work, it is time to split
A simpler design that is easy to build and adopt tends to beat a more correct but complex one.
Keep the implementation simple and spend the care on the interface
People are quicker to correct a wrong answer than to answer a question.
Post your best guess and let others correct it
The more people who see a problem, the less likely any one of them is to act on it.
If everyone owns it, no one does, so name one person
§ 21 Survivorship Bias
studying only failures misses why things usually go right; most of the time the same messy practices succeed, and that is evidence too
Before adopting a strategy because "Company X succeeded with it," research how many companies failed using the same approach. The dead don't write blog posts.
§ 20 Pareto Principle
the many small causes can add up to more than the few big ones; in availability and security, the rare path you deprioritized is where the outage or breach comes from
Before a quality push, rank modules by defects or incidents over the last quarter and start at the top. Re-rank every quarter; the vital few move.
§ 19 Law of Leaky Abstractions
most users of an abstraction never hit the leak, and the point of a layer is that most people do not have to learn what is underneath (Parnas, 1972)
Use abstractions to move fast, but ensure at least one person on the team understands the layer beneath it.
§ 24 Dunbar's Number
large groups do ship coherent systems (the Linux kernel has thousands of contributors) when the interfaces between parts are stable enough that most people never need each other's context
Watch for the symptom, not a number: when the people on one team can no longer say what everyone else is working on, or status meetings start multiplying, split along the seams of the system. Treat any specific size limit as a convention, not a finding.
§ 23 Cobra Effect
most bounties and targets do move behavior the intended way; refusing to reward the outcome because it could be gamed leaves the problem unpaid-for
For every incentive, ask how someone would earn it without fixing the problem, pay for the outcome rather than the evidence where you can, and decide in advance how you will wind it down.
§ 22 Kernighan's Law
the clever version is sometimes the short, correct one; a well-chosen data structure or library can remove whole classes of bugs that the "simple" hand-written loop keeps
In review, ask whether the next on-call engineer could explain the code without the author. If a trick is worth keeping, name it, link to where it is explained and add a test that pins its behavior.
§ 27 Bystander Effect
naming one owner every time makes that person the bottleneck and the bus factor; the owner should coordinate the response, not do all of it
Never say "Can someone look at this?" Instead, say "@name, you are investigating this." Assign a single, named owner for every incident.
§ 26 Cunningham's Law
the correction does not always arrive, and the wrong answer gets copied and indexed in the meantime; in shared docs, a guess must be labeled as a guess
When documentation is missing, write your best understanding, mark it as unverified, and send it to the person most likely to know.
§ 25 Worse is Better
Gabriel's own opposite: when the interface is hard to change later (a protocol, a file format, a security boundary) getting it right first can matter more than getting it out first
For anything users will build on, ship the simplest version whose interface you can live with for years; keep the implementation simple and spend the care on the interface.
Given enough time and traffic, a failure mode that can happen eventually will.
Build the failure path as if it will run, because in time it will
Code decays because cleanup tends to be deferred to a refactor that rarely happens.
Leave what you touch a little better, in the same diff
A system's inherent complexity can't be removed, only moved to someone else.
Complexity only moves, so know who you moved it to
People who are least skilled at something tend to overrate their ability the most.
Treat confidence as a reason to check the record, not as evidence
Once you know something, you can't easily imagine what it's like not to know it.
You cannot see your own assumptions, so watch a newcomer try
Every safeguard has holes; accidents happen when the holes in several layers line up.
Never stop at the one layer that failed
Optimizing before measuring spends effort on code that isn't the bottleneck.
Tune only what you measured; decide early only what you cannot tune later
A bug that stumps one person is often obvious to someone else looking at the same code.
When the same bugs slip through, add different eyes, not harder looks
During a network partition, a data store must give up either consistency or availability.
Choose what to give up before the partition chooses for you
§ 30 Tesler's Law
Brooks split complexity into essential and accidental; much of what a system carries is the accidental kind, and that can be deleted rather than moved
When a "simple API" feels too clean, ask: who absorbed the complexity I just removed? If you can't name them, you didn't simplify — you displaced.
§ 29 Boy Scout Rule
cleanup riding along with a behavior change hides the change, and a pull request that also renames forty things is one nobody reviews
Always leave the code cleaner than you found it, and keep the cleanup small enough to read inside the same diff — a one-line rename, a clearer comment, a deleted dead branch. Anything bigger gets its own commit.
§ 28 Murphy's Law
defending against every conceivable failure costs more than some of the failures; rank failure modes by likelihood and cost and accept the cheap, rare ones
Treat every external dependency, retry, and timeout as something that *will* fail in production. Build the failure path before the success path.
§ 33 Swiss Cheese Model
layers are not independent and each one adds interactions of its own; past a point, another safeguard is another way to fail
During an incident review, do not stop at "the one thing that failed." Enumerate every layer that should have caught the failure and ask why each hole was open at exactly that moment. The fix is rarely a single layer; prefer changes that make the layers fail independently of each other.
§ 32 Curse of Knowledge
docs that explain everything bury the expert reader; an operator at 3 AM needs the command, not the tutorial
Before shipping documentation or a public API, have someone who has never touched the system attempt the task while you watch silently. Their confusion points exactly at the assumptions you forgot to spell out.
§ 31 Dunning-Kruger Effect
the effect is contested — much of the classic pattern is reproduced by regression to the mean in noisy self-assessment, so treat overconfidence as a prompt to check the record rather than as a diagnosis
When someone declares a hard problem "easy," check their domain history before trusting the estimate. During scoping, pair confident newcomers with quiet veterans and weight the quiet voice.
§ 36 CAP Theorem
partitions are rare; the trade-off you pay every day is latency against consistency (Abadi, 2012), so a design argued only in CAP terms ignores the normal case
Decide *before* an outage whether each operation prefers consistency or availability. The partition will happen; the only question is what your system does when it does.
§ 35 Linus's Law
visibility is not review; the Heartbleed bug sat in OpenSSL's public source for two years before its disclosure in 2014, and some code needs a few paid, expert eyes rather than many casual ones
If the same class of bug keeps slipping through, the fix is not more careful review by the same people — it is exposing the code to more, differently-shaped eyes. Rotate reviewers, open up internal libraries, run bug bounties.
§ 34 Premature Optimization
some performance is set by early design (data layout, number of round trips, sync vs async) and cannot be profiled in later; for those decisions, think about speed before there is anything to measure
Write the obvious code first. Only optimize hot paths that a profiler proves are bottlenecks. Leave the other 97% of the code simple — that's where the next maintainer will live.
In a stable system, the average number of items inside equals arrival rate times average time spent.
To finish faster, start less
Over an unreliable channel, two parties can never be certain they have agreed.
Sent is not received, so design for retries
People tend to get promoted until they reach a role they are bad at, and stay there.
Promote for the next role, not as a reward for this one
Work expands to fill the time available for it.
Give open-ended work a short box
Software gets slower faster than hardware gets faster.
Treat faster hardware as a budget to protect, not to spend
The last 10% of the work tends to take as long as the first 90% did.
Expect "almost done" to hide as much work again
Your own code that you haven't read in six months might as well be someone else's.
Write for the stranger you will be in six months
The more options people are given, the longer they take to choose one.
Make each option earn its place
Small, distant targets take longer to hit and get missed more often.
Make frequent actions big and close, and dangerous ones small and far
§ 39 Peter Principle
promoting only those already proven at the next level means nobody gets the chance to learn it; stretch roles with support and a way back are how most good managers were made
Do not promote your best engineer into management as a reward — it removes a great engineer and risks creating a poor manager. Offer a technical ladder, and evaluate candidates for the role above, not the one they already mastered.
§ 38 Two Generals Problem
certainty is impossible but rarely needed; TCP, payments and every RPC run on high probability plus a way to reconcile, and waiting for proof means never acting
Never assume "I sent it, so they got it." Make every cross-network action safely retryable and idempotent, and reconcile state instead of trusting a single round-trip.
§ 37 Little's Law
cut work-in-progress too far and servers sit idle between arrivals; throughput drops and the work you refused still has to be done somewhere
To cut time-in-system without adding capacity, start less work: cap work-in-progress and shed, reject or defer what exceeds the cap, so the excess is refused quickly instead of queuing slowly. A cap without shedding just moves the queue somewhere you are not measuring.
§ 42 Ninety-Ninety Rule
the last 10% is sometimes not worth doing; polish nobody uses and edge cases nobody hits can be cut, and the hard part is deciding which
When something looks "almost done," assume an entire second project remains: the last-10% of hardening, edge cases, and integration. Schedule it explicitly instead of treating it as a rounding error.
§ 41 Wirth's Law
hardware is cheap and engineers are not; much of the "bloat" is abstraction that let a feature ship in weeks instead of months
Treat the speed a faster machine buys you as a budget to protect, not a license to spend. Set a performance budget and fail the build when a release regresses against it.
§ 40 Parkinson's Law
work that is always squeezed into the shortest box has no room for the thinking, learning and recovery that keep quality up (DeMarco, Slack, 2001)
Set deliberately short timeboxes for open-ended work and review at the deadline. A tight box forces the scoping decisions an open one defers forever.
§ 45 Fitts's Law
the same law that makes a button easy to hit makes it easy to hit by accident; for irreversible actions a slower, harder target is the point
Make frequent actions big and close to where the pointer already is; make destructive ones small, far from the frequent ones, and behind a confirmation. Screen edges and corners are effectively infinite targets, because the pointer stops there, so put primary actions there.
§ 44 Hick's Law
hiding options behind menus and defaults costs frequent users clicks and discoverability; a dense screen that experts learn once can be faster than a sparse one
Cut the number of choices on any screen or API surface to the few that matter; push the rest behind defaults and progressive disclosure. Fewer doors, faster decisions.
§ 43 Eagleson's Law
the code is the only description that is guaranteed current; a comment or ADR that is not maintained becomes a confident lie, which is worse than nothing
Write code and commit messages for the stranger you will become in six months. If a decision is not obvious from the code, record the *why* in a comment or an ADR — not just in your head.
Working memory holds only a handful of chunks (Miller said about seven; later estimates are lower).
Don't make people hold more than a few things at once
Networked code quietly assumes eight things about the network that are false in production.
Write as if the network will fail, lag and cost you
Automation leaves people only the hardest cases, after their skills have faded from disuse.
The more you automate, the more people must practise by hand
Every permission a component doesn't need widens the damage when something goes wrong.
Start from nothing and grant only what is proven necessary
A system that is secure only while its design stays secret is not secure.
Assume the attacker has read your design, and keep the secret in the keys
When the problem grows with the machine, parallel speedup keeps growing nearly linearly.
Ask whether the problem grows with the machine
When one request fans out to many servers, the slowest one sets the response time.
In a fan-out, watch the tail, not the average
A controller can only handle a system if it can respond to as many states as the system has.
Match the system's variety, or cut it down
Code that reaches through other objects' internals breaks when anything in the chain changes.
Talk to your neighbours, not to their neighbours
§ 48 Ironies of Automation
keeping people on routine manual work only to keep them practiced has its own cost: repetitive work that scales with load, burns time and invites slips, so the push to automate is real, and the tension is resolved by better human-machine teaming rather than by automating less
Keep operators sharp with regular game-days and hands-on drills, and design handoffs so a human takes over with context, not cold.
§ 47 Fallacies of Distributed Computing
Fowler's first law of distributed object design; the cheapest way to survive the eight fallacies is not to make the call remote in the first place
Before shipping any cross-process call, name which of the eight assumptions you are relying on and add an explicit timeout, retry, and failure path for each.
§ 46 Miller's Law
every grouping is a level of indirection; split a short list into named groups and people now have to remember the groups as well
Group related items into a handful of named chunks — phone-number style — wherever a person must hold state in their head: function arguments, form fields, menu groups, on-call steps.
§ 51 Gustafson's Law
for a fixed-size workload, the serial fraction still hard-caps speedup
Before justifying more cores, ask whether the problem size grows with the hardware. If the workload is fixed, reason with Amdahl; if it scales, Gustafson applies.
§ 50 Kerckhoffs's Principle
obscurity may be one thin extra layer, never the foundation
Assume the attacker has your source and design. Put all of the secret in rotatable keys, and never rely on a hidden algorithm to protect anything.
§ 49 Principle of Least Privilege
over-restriction that users route around defeats itself
Default every process, service account, and token to deny, then add only the minimal scopes the job provably needs; re-audit the grants whenever the job changes.
§ 54 Law of Demeter
strict application breeds forwarding and wrapper bloat
Only call methods on your direct collaborators, your arguments, objects you create, and your own fields. If you are chaining getters, add a method to the object that owns the data.
§ 53 Ashby's Law of Requisite Variety
excess control variety is itself cost and complexity
When incidents keep escaping your alerts and runbooks, either add matching response capability or deliberately shrink the system's state space: fewer configurations, stricter inputs.
§ 52 The Tail at Scale
hedged and tied requests add load; don't chase the tail where the median is what users feel
Set SLOs on p99/p99.9, not the mean, and deploy tail-tolerance — hedged requests, micro-partitioning — instead of trying to make every node uniformly fast.
Making a resource cheaper to use can increase how much of it is used in total.
Make something cheaper and expect more of it to be used
In complex, tightly coupled systems, accidents are built into the structure.
Loosen the coupling before you add more safeguards
Visible disorder left unrepaired can signal that standards are optional, inviting more.
Fix the defect in front of you before it becomes the standard
Code built for imagined future needs costs time now and rarely fits the need that arrives.
Build for the case you have, not the one you imagine
A system has to be simple enough for an ordinary person to fix under bad conditions.
Simple means someone else can fix it at 3 AM
Knowledge kept in two places drifts apart, because nothing makes the copies change together.
Deduplicate knowledge, not text
A system's throughput is set by its single tightest bottleneck.
Improve the bottleneck first, because everything else is waiting on it
The explanation that needs the fewest unverified assumptions is usually the right one.
Test the explanation with the fewest assumptions first
A module serving two groups gets conflicting change requests from both.
Split code along the line of who asks for changes
§ 57 Broken Windows Theory
attention spent on paint is attention not spent on the foundation, and the criminological evidence for the original claim is contested
Repair the first visible defect in a file you are already touching, and give every tolerated exception an owner and a date. Do not open a refactor for a window you are not standing next to.
§ 56 Normal Accident Theory
organizations such as aircraft carriers and air-traffic control run tightly coupled, complex systems with very few accidents, through redundancy, deference to expertise and constant attention to small failures
Reduce coupling — add buffers, timeouts, bulkheads, and circuit breakers — and cut complexity before adding more safety interlocks, which themselves add interactions.
§ 55 Jevons Paradox
pair efficiency with a quota, cap, or price signal to actually capture the savings
When you make something cheaper — compute, storage, an internal API — expect demand to balloon; provision and budget for the rebound instead of assuming a net reduction.
§ 60 DRY Principle
two blocks that merely look alike today will fight each other the moment they need to diverge
Deduplicate knowledge, not text. Before merging two similar blocks, ask whether they change for the same reason and at the request of the same person; if not, leave them apart.
§ 59 KISS Principle
a system simpler than the problem it has to regulate cannot cope with it, and simplicity below that floor is displaced complexity rather than less of it
Judge a design by who can repair it at 3 AM, not by how it reads in review. If the on-call engineer needs the author on the call, it is not simple — it is familiar to one person.
§ 58 YAGNI
YAGNI licenses you not to build something; it never licenses you to delete something whose purpose you have not established
Implement the case you actually have. When you feel the pull to generalize, name the second concrete case first — if you cannot, you do not have a pattern, you have a guess.
§ 63 Single Responsibility Principle
splitting by imagined responsibilities produces a scatter of one-method classes and moves all the complexity into the wiring between them
Define responsibility by who asks for the change, not by what the code does. If two different people can each demand an edit to the same module, split it along that line and nowhere else.
§ 62 Occam's Razor
a system can carry several independent faults at once, and the simplest story that fits the symptoms is not automatically the true one
Rank your hypotheses by how many unverified assumptions each needs, and test the cheapest first. Ask "what changed?" before "what is broken?"
§ 61 Theory of Constraints
relieve one and another takes its place, so a process permanently optimized around yesterday's bottleneck starves at the new one
Find the constraint, exploit it fully before you buy capacity, and subordinate every other stage to it. Then measure again — you have just created a different bottleneck somewhere else.
Behavior that surprises users costs more than behavior that is slightly worse but expected.
When in doubt, do what users already expect
After a first success, designers tend to pack the ideas they deferred into the second system.
In a rewrite, carry over the constraints, not the wish list
The number of transistors on a chip at lowest cost per part doubles about every two years.
Don't count on next year's hardware to save the design
New technology is overrated in its first years and underrated over a decade.
Discount the two-year hype, but respect the ten-year shift
In AI, general methods that scale with compute have, in the long run, beaten hand-coded human knowledge.
Bet on what gets better on its own when the budget doubles
Each new node adds value to every existing one, so a network's value outgrows its size.
Add connections in a product, cut them in a team
Each person contributes less as a group grows, most of all when no one can see who did what.
Make each contribution visible and owned
Institutions tend to keep alive the problem they exist to solve.
Ask every fixer what "fixed" would look like
An SLO below 100% leaves a measurable allowance of failure, and that allowance can be spent.
Spend the allowed failure on shipping, and stop when it runs out
§ 66 Moore's Law
the gains get spent rather than banked, and clock speed stopped rising long before transistor counts did
Do not budget for the hardware bailing out a design. If the workload is single-threaded and latency-bound, next year's machine will not save it — you have to parallelize it or do less work.
§ 65 Second-System Effect
some first systems cannot be grown: a data model, a platform or a security boundary that blocks the next step outright, and there a deliberate, scoped second system is the right call
When rewriting, carry forward the constraints and not just the wish list. Cut the deferred features to the few that actually blocked users, and replace the original one piece at a time.
§ 64 Principle of Least Astonishment
designing only for today's expectations freezes bad conventions in place; sometimes the right move is to surprise everyone once, loudly, with a migration path
When two designs are close, take the one that matches the convention your users already know — the flag name, the exit code, the sort order. Spend deliberate surprise only where you can afford to announce it.
§ 69 Metcalfe's Law
connections are an asset between users and a liability between colleagues; Brooks' Law is Metcalfe's Law with the sign flipped
For a product whose value comes from other users, spend early effort on the smallest network that is already useful to its own members, not on features. For a team, do the opposite and cut connections.
§ 68 The Bitter Lesson
inside a fixed budget domain knowledge is often the only lever you have, and the lesson describes the trajectory of a field rather than the right move this quarter
When choosing between encoding what you know and building something that learns from more data or more compute, ask which one improves on its own when the budget doubles. Bet on that one for anything with a multi-year horizon.
§ 67 Amara's Law
survivorship makes the law look inevitable, because the technologies that never got a long run are not the ones quoted back at us
Discount two-year forecasts about a new technology and take ten-year ones seriously — but plan around the version that actually ships, not the one in the demo.
§ 72 Error Budget
a standing allowance for failure teaches a team that each failure is routine; the outage that should have alarmed people gets logged against the budget and never investigated
Agree on the SLO and the policy before the incident, not during it: while budget remains, ship; when it is spent, freeze feature releases and put the time into reliability until it recovers. Keep data loss and security outside the budget entirely.
§ 71 Shirky Principle
treating every long-lived team as self-serving destroys the ones doing necessary maintenance, which is invisible precisely when it is working
For any team or tool created to fix something, write down what "fixed" looks like and when you will check. A platform team that cannot describe its own obsolescence is optimizing for its own survival.
§ 70 Ringelmann Effect
the effect is a property of how the work is measured rather than of the people; make the individual contribution legible and most of it disappears
Give every workstream one named owner and a visible output. If you cannot say who produced which part of a result, expect the group to produce less than the sum of its members.
Manual, repetitive operational work grows with the service and, left unchecked, crowds out engineering.
Treat repeated manual work as a defect, not a duty
Punishing the person nearest a failure teaches people to hide what they did.
Fix what made the mistake easy, not the person who made it
Teams that start from a solution often build things no customer needed; starting from the announcement exposes that early.
If you cannot say what the customer gets, you are not ready to build
Waiting for everyone to agree is often slower than committing and correcting course if the call turns out wrong.
Disagree once and fully, then commit, unless it cannot be undone
When the team that writes a service also operates it, the cost of every operational weakness lands on the people who can fix it.
Whoever can fix it should be the one it wakes up
A system that has to take new action to survive a failure depends on that action succeeding at the moment things are going wrong.
Don't make recovery depend on acting during the failure
A fallback path runs only after something has already failed, so the least-tested code in the system runs under the worst conditions.
Distrust code that runs only when things are already broken
A system whose work grows with the number of changes or failures does the most work exactly when it has the least headroom.
In control loops, do the same work whether or not anything changed
Asking people to try harder after a failure changes little, because the failure happened to people who were already trying.
Replace "be careful" with something that works without anyone remembering
§ 75 Working Backwards
when customers cannot judge an idea on paper (a new platform, an infrastructure change, something with no precedent) a cheap prototype tells you more than a polished press release
Before a project starts, write a one-page press release and an FAQ for the customer, and review them as a team. If you cannot name the customer and their problem in the first paragraph, do not start building.
§ 74 Blameless Postmortem
when nobody is answerable, the action items have no owner and quietly expire; some teams name a person accountable for the fix precisely because blamelessness leaves no one holding it
Write the postmortem as a timeline of what people saw and why each action made sense then, and end with changes to the system, not to a person, each with one named owner and a date. Ban "human error" as a root cause; ask what made the error easy to make.
§ 73 Toil
automating a task removes the practice people needed to handle it when the automation fails, and some automation costs more to build and keep alive than the toil it replaces
Measure the share of each person's time spent on toil and set a ceiling (Google uses 50%). When a task comes back a third time (a rule of thumb, not the book's), file it as engineering work; when it scales with users, treat it as a defect rather than a chore.
§ 78 Static Stability
capacity held for a failure that rarely happens is paid for every day, and scaling to demand is cheaper wherever a slow recovery is acceptable; the source itself concedes that building services zone by zone rather than regionally adds complexity
List what your service must do to recover from losing a zone or a dependency. For every step that calls a control plane or launches something, decide whether to have it in place beforehand instead: spare capacity in every zone, the last good configuration cached locally, serving that continues while the control plane is down. Reserve this for paths whose failure you cannot afford; elsewhere, scale on demand.
§ 77 You Build It, You Run It
owning the whole cycle widens what each developer must know and the priorities they juggle every week; without shared tooling and an on-call rotation it ends in burnout, and Netflix, which runs the model, says it supports people who want depth over breadth in finding other roles
Put the team that ships a service on its pager, and give it the authority and the deploy rights to fix what pages it. Pair that with a paved road (shared deploy, observability and alerting tooling) and a rotation, so no one person is on call for everything. Do not apply it to a team that cannot change the thing it is woken up for; that hands over the pager, not the ownership.
§ 76 Disagree and Commit
a culture that prizes commitment teaches people to stop objecting early, and silent compliance hides the dissent that would have caught the error
State your disagreement once, in full, with your reasons. Then say "I disagree and commit" and execute as if it were your idea. If you are the senior person, do it too: back the team's call instead of making them convince you. For an irreversible decision, or one with a safety or ethical risk, do not commit quietly: escalate.
§ 81 Mechanisms, Not Good Intentions
a mechanism can harden into the goal; once following the process is what gets judged, people defend a bad outcome by saying they followed it, and nobody asks whether the process still serves the result
When a postmortem action item says "be more careful", "remind the team" or "double-check", replace it with a change that works without anyone remembering: a CI check, a safe default, a field that cannot be skipped. Give each one an owner and a date to inspect whether it is used and whether it worked. Retire mechanisms that no longer change outcomes.
§ 80 Constant Work
doing the full work every cycle wastes resources when little has changed; for configuration and health status the cost is negligible, but for a web fleet the savings from scaling with load usually win over running peak capacity all day
For control loops that propagate configuration or health, send the whole state on a fixed schedule instead of deltas on change, and size the payload for the maximum, not the typical case. Keep the amount of work independent of how many things changed. Use it where the work is small; for request-serving capacity, scale with load and design the overload case explicitly.
§ 79 Avoid Fallback
returning a reduced answer beats returning an error when the reduced path runs all the time, as when a recommendations panel falls back to a static list it serves anyway; the danger is the path that never runs, not degradation itself
Before adding a fallback, ask whether the same effort would make the primary path more available: push data to the caller ahead of time instead of pulling it at request time, add redundancy. If you keep a fallback, run it in production continuously, not only on failure, and treat its output as an equally valid source. Delete fallback paths nobody has exercised.
Letting anyone who sees an abnormality stop the line keeps a defect from traveling downstream, where it costs more to find and fix.
Let anyone stop the line, and never punish a stop
The first answer to "why did this fail" is usually a symptom, and fixing a symptom leaves the cause in place to fail again.
Keep asking why until you reach something you can change
Resilience that has never been exercised is a hypothesis, and production will test it whether or not you schedule the test.
Break it on purpose before production does it for you
As an organization grows, rules and approvals tend to scale worse than shared understanding; Netflix's argument is that people given the reasons behind a goal make better local decisions than people given a procedure.
Fix the missing context before you write a rule
Holding every change to a standard of perfection makes review slow, and slow review leaves the codebase worse, not better.
Approve better, not perfect
In a shared codebase, the behavior no test checks is the behavior that changes without warning.
If you depend on it, put a test on it
When the team that changes shared infrastructure can push the migration onto its users, the cost of the change multiplies by the number of users.
Whoever changes shared code pays for the migration
When scope is fixed and time is not, the date slips and the scope stays; fixing the time instead forces a choice about what matters.
Decide what the work is worth before you ask how long it takes
Replacing a live system piece by piece around its edges is usually safer than replacing it all at once.
Make every step of a migration shippable, and plan the deletion up front
§ 84 Chaos Engineering
deliberately degrading a system real customers depend on spends their trust, and much of the same knowledge comes cheaper from fault-injection tests, game days and design review; on a system already known to be fragile an experiment only confirms what you knew, so fix it first
Pick one dependency, write down what steady state should look like while it is down, and take it away in production during working hours with an abort switch and someone watching. Start with a small slice of traffic, widen only after the system holds, and do not experiment on a service you already expect to fall over.
§ 83 Five Whys
a single chain of whys picks one path through an accident that had several, the analyst's choice at each step decides which root cause comes out, and in complex systems there is often no single root to find
In the postmortem, keep asking why of each answer until you reach something the team can change that would have stopped the chain, and give that change an owner. Branch whenever an answer has more than one cause, and never stop at a person: "the engineer made a mistake" is a cue to ask why the mistake was easy to make.
§ 82 Andon (Stop the Line)
every stop costs output, and where a team is judged on throughput, pulling the cord becomes a cost someone has to justify, so a cord that fires often or falsely teaches people to route around it
Make a red main-branch build, a failed canary or a breached SLO halt further merges or deploys for everyone, and let anyone pull that cord without asking permission. Keep the trigger narrow enough that it rarely fires falsely, and treat a stop that nobody investigates as a defect in the response, not in the person who pulled it.
§ 87 Beyoncé Rule
a test-shaped contract tells the changer what it broke, not that breaking it was free; the team making the change still owes its users the migration
Write a test for every behavior your product relies on in a shared library or dependency, and make sure it runs in the CI that gates other people's changes. When something breaks and no test caught it, add that test before closing the incident. If you own the shared code, say up front that tests are the contract, and do not invoke the rule unless your changes actually run consumers' tests.
§ 86 Approve What Improves Code Health
a reviewer who waves each small flaw through because the change is a net improvement can still leave a codebase full of tolerated flaws, each one making the next easier to accept
Approve a change once it definitely leaves the code healthier than before, even if you would have written it differently. Prefix polish with "Nit:" so the author can skip it, and block only on what makes the code worse: outside an emergency, do not approve a change that definitely worsens overall code health.
§ 85 Context, Not Control
some failures (a leaked credential, a compliance breach, an irreversible deletion) cost too much to leave to judgment, and context does nothing for a newcomer who has not absorbed it yet
When a team makes a call you would have made differently, ask what context they were missing before you write a rule, and fix the context first. Keep hard controls (approval gates, enforced policy) for decisions that are irreversible, unethical or a material risk, and record why each one exists so it can be removed when the reason goes away.
§ 90 Strangler Fig
when the old system cannot be intercepted cleanly, or the transitional layer would cost more than the rewrite, a single planned switch avoids the common end state of incremental migration: the easy routes move, the tangled core never does, and the organization runs and pays for two systems indefinitely
Put an interception point (a proxy, router or facade) in front of the legacy system and move one slice of behavior behind it at a time, starting with one that delivers value on its own. Define "done" at the start, track the share of traffic still on the old path, and budget deleting the old code and the transitional layer as part of the project, not as cleanup for later.
§ 89 Fixed Time, Variable Scope
under a fixed date a team that cannot or will not cut scope cuts tests, review and error handling instead, and some work (a protocol, a compliance requirement) has a floor below which no slice is worth shipping
Before the work starts, decide how much time it is worth, not how long it will take, and shape the scope to fit. When the time runs out, stop by default: ship what is done if it stands on its own, otherwise reshape it and decide afresh whether to bet on it again; do not quietly extend. Cut features before tests or review, and do not fix the time on work that cannot be sliced below a coherent minimum.
§ 88 Churn Rule
people who change a codebase they do not live in miss its local reasons, so a central migration still needs the owning team's review, and some changes only its owners can make safely
If you own a library, service or platform, budget the migration as part of the change: move the callers yourself, or change in place in a backward-compatible way. Do not ship a deprecation notice and a deadline as the migration plan. Invest in the tooling that makes cross-codebase changes cheap, and send each change to the owning team for review instead of landing it unseen.
Every unfamiliar technology a team adopts brings unknown failure modes and a permanent operating cost, and a team can afford only a few of them.
Spend new technology only where it sets you apart
Code shipped before the team fully understands the problem charges extra on later changes to that code until someone rewrites it.
Record shortcuts as loans, and repay them where you change code most
A program in real use must keep changing or grow less useful, and each change makes it more complex unless work is spent to simplify it.
Budget for simplifying, not just for changing
The fewer people who can keep a system running, the more its future depends on each of them staying.
Anything only one person can do is a risk to fix now
Every way of finding bugs leaves behind the bugs it cannot find, so a test suite that never changes finds fewer and fewer.
Keep changing how you look for bugs
An argument cut down to slides and bullets loses the links between its points, so the gaps and warnings that prose would have exposed pass through the review unnoticed.
For decisions that matter, write prose, not bullets
When consumers may choose which version of a shared dependency to use, each choice becomes a conflict for someone who never made it.
Treat every second version as a debt with an owner and an end date
Decisions made from reports drift away from what is actually happening, because each layer of summary drops the detail that did not fit its form.
See the real thing yourself before you trust the summary
When a group counts every opinion the same, or defers to rank, the people who have actually done the thing before are outvoted by those who have not.
Weigh views by track record, not by rank or headcount
§ 93 Lehman's Laws of Software Evolution
every change makes users relearn something and breaks someone who relied on the old behavior, so for a protocol, file format or tool that others build on, freezing the design can be worth more than keeping up with the world
Budget ongoing change as the normal cost of a program in use, not as an exception after launch. Reserve part of every cycle for work that reduces complexity, such as deleting dead paths and merging special cases, and track a complexity measure across releases so you see the trend before it stalls you. Freeze only what other people build on, and say so when you do.
§ 92 Technical Debt
paying down debt early spends time on code whose design may still change or that may be deleted before anyone touches it again, so cleaning up ahead of the next change can cost more than the interest it saves
Treat code written before the team fully understood the problem as a loan: write down where it is and what repaying it would take, and schedule the rewrite while the code is still fresh in someone's head. Repay first where the team changes code most often, not where the code merely looks worst. Do not let debt pile up unrecorded.
§ 91 Choose Boring Technology
boring is not the same as never new; when the existing stack genuinely cannot do the job, forcing it costs more than a token, and a stack that never moves becomes the legacy nobody wants to work on
Before adding a language, datastore or framework, write down what it would take to do the job with what you already run and why that falls short, and make the decision with everyone who will operate it, not inside one team. Spend new technology only where it sets the product apart. When you do adopt something, plan to retire what it replaces.
§ 96 Narratives, Not Slides
when running code would settle a design question faster than prose, a document written first spends a week recording guesses, and a design doc that is really an implementation manual should not be written at all
For a decision that is expensive to reverse, or that people outside the team must approve, write the proposal as a few pages of prose: the problem, the options considered, the trade-offs and the recommendation. Open the review with everyone reading it in silence, then discuss. Do not write one for a reversible change or for a question a quick prototype will answer; build the prototype instead.
§ 95 Pesticide Paradox
a test that has not failed in years still keeps a fixed bug from coming back and pins behavior others rely on, so retiring old tests to chase new bugs gives up protection they still provide
Keep the regression suite, but do not count on it to find new bugs. Add tests aimed at what the suite does not exercise: new inputs, fuzzing, property-based tests, exploratory sessions. When a bug escapes to production, ask which kind of test would have caught it and add that kind, not only that one case. Review the suite on a schedule and remove tests that duplicate each other.
§ 94 Bus Factor
a specialist who owns an area works far faster and notices more than a rotation of people who each know a little, and a small team that copies everything into a second head spends time it does not have
List the parts of your system that only one person can change or operate. For each, pair a second person on the next real change instead of writing a handover document nobody reads. Rotate on-call and code review so knowledge moves as a side effect of normal work. Treat a planned absence as a drill: if a week away stalls a system, fix that before someone leaves for good.
§ 99 Believability-Weighted Decisions
when judgments are made independently, a plain equal-weight aggregate is hard to beat (the median guess of Galton's fairground crowd was within 1 percent of the ox's weight), and picking experts in advance bets on a track record that may not carry over to the new question
Before a contested technical call, ask who has built or run this kind of thing before and whether it worked, and give their view more weight than headcount or title. Collect views in writing before the discussion so they stay independent, and look at both the plain tally and the weighted one; where they disagree, dig in rather than letting the weighted side win by default. Base believability on outcomes you can check, such as systems shipped and postmortems, and drop the weighting for questions nobody on the team has faced before.
§ 98 Genchi Genbutsu (Go and See)
a visit shows one shift, one user or one trace, and people judge from a small sample as if it stood for the whole (the belief in the law of small numbers), so for a question about the whole fleet the dashboard that covers every case is the better witness
Before you decide on a fix, a priority or a postmortem conclusion, look at the primary evidence yourself: reproduce the bug, read the raw logs and the trace of one failing request, watch a real user hit the problem, or sit on the support queue for an hour. Use what you saw to question the dashboard, not to replace it.
§ 97 One-Version Rule
where no one owns every caller, as across an open-source ecosystem, nobody can make the single change that moves everyone, so letting incompatible major versions live side by side under different import paths lets each caller upgrade on its own schedule and accepts the duplicate copies as the price, which is the approach Go modules take
Keep one version of every shared dependency, internal or third-party, and do each upgrade as one change that moves every caller. When an upgrade cannot land in one step, allow a second version only under a different name, with an owner and an end date, and delete it when the date comes. Do not let a team fork or pin a shared library on its own. Where projects have genuinely different security, legal or release requirements, split them into separate repositories, but hold each one to a single version per dependency.
Feedback from people who can overrule the owner gets defended against rather than used; peers with no power to impose a fix can be candid, and the owner can afford to hear them.
Give candid notes, and leave the fix to the owner
Refuting a false claim takes far more effort than making it, so a stream of cheap claims can swamp the people who have to check them.
Make a claim carry its own evidence before you spend yours on it
People working with an automated aid tend to let it stand in for their own checking: they miss what it fails to flag and follow it when it is wrong.
Answer for the outcome, not for having followed the tool
The larger a change sent for review, the less closely each line is read: defects slip through and the change waits longer for a first look.
Send a change small enough to read in one sitting
A program's design lives in the heads of the people who built it, and the code and documents carry only part of it, so once those people are gone, changes tend to erode the design even with full documentation in hand.
Code stays maintainable only while someone can say why it is the way it is
A test can only catch a wrong answer if something independent of the code knows the right one, and for many programs nothing does.
Before trusting a passing test, ask what it was checked against
An AI agent that can read private data, takes in content from outside and can send data out can be steered into leaking that data by whoever wrote the content.
Treat any text an agent reads as instructions from whoever wrote it
Work gets ordered by size, by gut feel or by whoever asks loudest, while what each item loses every week it waits goes uncounted, so the most valuable work often waits behind the merely visible.
Ask what a week of waiting costs before asking what it costs to build
Commit too early and a guess hardens into the design; wait too long and an option quietly expires, so the decision gets made by default without anyone making it.
Know when each decision expires, and decide before it does
§ 102 Automation Bias
the opposite error is common too: Dietvorst, Simmons and Massey found that "people more quickly lose confidence in algorithmic than human forecasters after seeing them make the same mistake", and so drop an aid that still beats them
Wherever an automated aid feeds a decision (generated code, scanner results, an alert that says all clear), name a person who answers for the outcome, not for having followed the tool. On high-stakes paths such as security, data migrations and production changes, have the reviewer check against the requirement, not against the tool's own output, and keep a record of what the aid missed. Do not re-derive by hand what the tool has shown it does better; spot-check low-stakes output instead.
§ 101 Brandolini's Law
in front of people who know the subject, a wrong claim often draws its correction quickly and for free, so posting your best guess and letting others fix it can beat holding back until every claim is checked
Where claims arrive faster than you can check them (bug reports, review comments, security disclosures), ask the claimant for the evidence up front: steps to reproduce, a failing test, the log. Timebox the first look, and watch what a reward attracts: even one paid only for confirmed results can draw more claims than you can check, and then it is better dropped. Do not use this to wave away a short report from someone with nothing to gain; a terse report that reproduces deserves full attention.
§ 100 Braintrust (Notes Without Authority)
where a blind spot's cost lands on someone other than the owner (a security hole, lost data, another team's pager), advice that can be ignored is not enough, and a reviewer has to be able to block
In a design or RFC review, let reviewers name problems and their suspected causes but not dictate the fix, and leave the decision with the author, who answers each point in writing. Fill the room with peers who have built something similar, not the manager who rates the author. Where a mistake would land on others (security, data loss, an irreversible migration), keep a blocking approval, but run it as a separate step from the advisory review.
§ 105 Test Oracle Problem
for a cheap, reversible change, a partial and time-limited deployment judged against real traffic and SLOs catches problems no test author thought to write down
For every test that guards something important, be able to say where its expected value came from: a spec, a hand calculation, an independent implementation, a domain expert. Treat snapshot tests and generated tests whose expectations were copied from the current output as change detectors, not as evidence the code is right. Where no oracle exists, test what must hold anyway: invariants, round trips, and relations between the outputs of related inputs. For a reversible change behind good monitoring, a canary can be the check; keep hand-built oracles for changes that are expensive to undo.
§ 104 Programming as Theory Building
Parnas and Clements argue for writing the design down as if it had been derived rationally and keeping that record current with every change, so new programmers do not have to depend completely on the old staff; where people move on often, a maintained record is a safer bet than counting on who stays
When a system changes hands, plan an overlap: the new owners make real changes while the old team reviews them, and the handover ends when the old team stops catching patches that fight the design. Before merging code from a generator or a contractor, have the person who will own it explain why it is shaped the way it is; if nobody can, treat it as unowned. When a program's team is gone, Naur's advice is to discard the old text and let the new team solve the problem afresh, which he expects to cost no more than reviving it; where a rewrite is out of reach, rebuild the theory by pairing on real changes before restructuring anything.
§ 103 Small Changes
every change pays a fixed cost whatever its size (a review round trip, a CI run, the reviewer switching context), so splitting work multiplies those costs and the waits between them; when reviews are slow, a chain of tiny dependent changes can take far longer to land than one coherent change
Make each change one self-contained thing: about 100 lines is usually reasonable and 1000 lines usually too large, though the reviewer has the final say. Send refactoring separately from behaviour changes, and stack dependent changes instead of piling them into one. Do not split a purely mechanical change (a rename, generated code) just to hit a number, and do not cut a design so finely that the reviewer can no longer see what it does.
§ 108 The Last Responsible Moment
Wirfs-Brock finds she cannot tell when the last responsible moment is, and that aiming for it lulls her into thinking there will always be time to change her mind; she prefers to decide as soon as a decision has a positive impact, which often comes earlier
For each open design decision, write down the event that would remove an alternative (a contract date, a release that freezes an interface, another team starting to build on it) and put its date on the calendar. Decide before that date, not on it. Do not use this to postpone decisions that unblock other work or that shape everything after them, such as layering.
§ 107 Cost of Delay
instead of making engineering work win its place item by item, fix its share of capacity by rule; Google caps operational work for SREs at 50% of their time and says "Their remaining time should be spent using their coding skills on project work."; the SRE book does not discuss cost of delay, but by this entry's reading a fixed share protects work such as paying down debt, whose loss in any one week looks small and so rarely tops a ranking
For the items at the top of the backlog, estimate what each one loses per week of waiting, in money, and write the assumptions next to the number. Divide by the expected duration and schedule in that order. A rough range is enough: the point is to expose how far apart people's guesses are, not to be precise. Keep a fixed share of capacity outside the ranking for work whose value is long-term.
§ 106 The Lethal Trifecta
an assistant worth having often needs all three; a design like Google DeepMind's CaMeL keeps them by planning the steps from the user's trusted request alone and tagging data with capabilities, so within the control and data flow it tracks, untrusted content cannot change which steps run or send private data where policy forbids; when you build the agent yourself, that can serve better than taking a capability away, but it finishes fewer tasks: on the AgentDojo benchmark the paper reports 77% with CaMeL against 84% for an undefended agent
Before connecting a tool to an agent, write down which of the three it adds: private data, untrusted content, or a way to send data out (including links, image loads, pull requests and email). When a session ends up with all three, take one away: browse in a sandbox with no credentials, cut the outbound channel, or make a human approve each outbound action. Do not count a prompt-injection filter as the control. An agent that reads only trusted data, or whose output never leaves the machine, does not need this.
People who doubt a plan the team has already committed to tend to keep quiet; asking them to explain a failure that has already happened draws the doubts out.
Assume the plan already failed, and make finding out why the clever move
For some problems, working out what the problem is and choosing a solution are the same act, so the requirements cannot be settled before the design starts and there is no point at which the problem is done.
When solving changes the problem, treat its statement as a draft, not a gate
In online controlled experiments at large web companies, most ideas that survived the team's own pruning do nothing or make things worse once they are measured, and experts tend to be poor at telling in advance which ones.
Treat your favourite idea as a hypothesis that will probably fail
As a server's utilization approaches 100%, the time work spends waiting for it climbs steeply, and variability in arrivals and service multiplies the climb.
Keep headroom wherever someone is waiting on the answer
People who make things need long unbroken blocks of time, and a calendar run in one-hour slots breaks those blocks into pieces too small to use.
Count a meeting's cost as the block it breaks, not the hour it takes
Decisions drift toward whatever can be counted, until what cannot be counted is treated as if it did not exist.
Name what you cannot count, and keep it beside the number
When real effects that large are rare, a metric that moves surprisingly far is more often a bug in the measurement or the analysis than a real effect.
Treat a surprising number as a bug report until it survives checking
A team learns when its members admit mistakes, ask for help and disagree, and they do that far more readily when they believe it is safe to.
Make "I was wrong" and "I don't know" cheap to say
§ 111 Most Ideas Fail
some decisions cannot be put through a controlled experiment at all; the same paper agrees with Davenport that experiments suit strategy execution, not strategy formulation, and are "not suited for assessing a major change in business models, a large merger or acquisition", and grants that measuring is sometimes "non-economical"; by this entry's reading, there someone has to commit on judgement
Before building, write down the metric the idea is meant to move and by how much, then ship it behind a flag to a randomised share of users. Drop or rework what does not move the metric, however sure the team was. Where you cannot randomise (too little traffic, a long-term bet, a change you cannot roll back), say so and decide on judgement without claiming it was measured.
§ 110 Wicked Problems
Pólya's method opens with "You have to understand the problem." and asks "What is the unknown?" before any plan is made; for much engineering work, such as a bug, a migration or a latency target, writing down the unknown, the data and the condition first is what makes it solvable, and calling such work "wicked" excuses skipping that step
Before writing requirements, ask two questions: does the problem statement change every time someone proposes a solution, and is there no test that would say it is solved? If both are yes, stop trying to freeze the requirements first: put the people who disagree in the same review, show small versions early, and decide in advance when you will stop, since the problem will not tell you. If either is no, treat it as tame and write the problem statement.
§ 109 Pre-Mortem
hunting for failure on every plan breeds caution; Klein himself notes that pre-mortems "tend to encourage risk aversion", and for a cheap, reversible step, trying it teaches more than imagining how it goes wrong
At the kickoff of any project that would hurt if it failed, after the plan is presented, tell the team the project has failed. Give everyone two minutes to write down the reasons alone, then go round the room one reason per person until the lists are empty, and give the top few an owner and a change to the plan. Skip it for small, reversible changes, where shipping and watching is cheaper.
§ 114 McNamara Fallacy
much of what looks unmeasurable can be measured roughly, and a rough number tells you more than an unexamined hunch; Hubbard argues that the belief something cannot be measured rests on misconceptions (How to Measure Anything, 2007)
When a decision rests on a dashboard, write down what matters that the dashboard does not show, such as user trust, on-call load or code health, and put at least one direct look or survey beside the numbers. The SPACE authors make the same point about developer productivity: no single metric or dimension can capture it. For a narrow, well-instrumented question such as one endpoint's latency, the number is enough.
§ 113 Maker's Schedule, Manager's Schedule
Toyota lets any operator stop the line so a problem is dealt with where it appears instead of piling up downstream; a team that guards every maker's block the same way can leave a blocked teammate, or a defect, waiting behind it
Put meetings at the edges of the day or cluster them on fixed days, and keep blocks of at least half a day free of them for the people who build. Before booking a maker, count the block you would break, not the hour you take. Incidents get answered now; a teammate waiting on a review gets an answer at your next break point, within a day.
§ 112 Kingman's Formula
spare capacity is paid for whether or not anyone uses it, so whoever owns the budget pushes utilization up, and often rightly; the Google SRE book says "Efficient use of resources is important any time a service cares about money." and treats provisioning as a large lever on a service's total cost, so where a slower answer costs little, running hotter frees money for work that matters more
For anything latency-sensitive (a service, a shared build runner, the on-call engineer), set a utilization ceiling below saturation (well below for a single server or a single person; a pool of interchangeable workers can run closer to full) and add capacity or shed load when you cross it, not after latency has already spiked. Cut variability too: smaller, more uniform jobs wait less at the same load. Set the ceiling by weighing what a slower answer costs against what the idle capacity costs, and raise it where waiting is cheap.
§ 116 Psychological Safety
in a three-year study of 545 New York City public schools, Higgins and colleagues found the best performance where psychological safety was relatively low and felt accountability relatively high, not where both were high as Edmondson's model predicts; they liken safety to "a pinch of yeast", so when results lag, raise accountability for shared goals before adding comfort (Academy of Management Discoveries, 2022)
Leaders go first: say your own mistakes and unknowns out loud, ask for dissent before you decide, and answer bad news by thanking the messenger and fixing the system. Keep standards and deadlines where they are; safety is about speaking up, not about lowering the bar. Edmondson herself warns that "if you are ONLY creating psychological safety, then you are creating a comfort zone."
§ 115 Twyman's Law
the same paper's Rule #1: trivial changes sometimes move key metrics a lot, like a Bing font-colour change worth over $10M a year; a team that treats every big win as a bug stops running the cheap long-shot experiments that find them
When a result is far better or worse than past experiments, hold the announcement and check the plumbing first: how the metric is logged, whether the treatment changed what gets recorded, and whether the analysis compares like with like. Then replicate on a fresh sample. Ordinary, expected moves do not need this treatment.