These come from computer science, organizational theory, psychology, and systems thinking. They're commonly lumped together as "software engineering laws," but they aren't all the same kind of thing. Some are provable constraints you can't work around. Some are patterns measured in labs and observed across decades of projects. Some are practical rules of thumb. And a few are quips from the early internet that turned out to be uncomfortably accurate.
The Ideas
- 1. CAP Theorem - When the network splits, you choose consistency or availability
- 2. Amdahl's Law - Widen the bottleneck before adding parallel capacity
- 3. Ringelmann Effect - Small teams outperform because there's nowhere to hide
- 4. Price's Law - A few people carry most of the output; plan around it
- 5. Bus Factor - Concentrated knowledge is invisible risk; one departure can stall a project
- 6. Pareto Principle - A small number of causes produce most of the impact; find them
Organizational and Evolutionary Patterns
- 7. Conway's Law - Architecture follows org structure whether you plan for it or not
- 8. Brooks's Law - New hires consume experienced people's time before they produce
- 9. Gall's Law - Start simple, evolve; rewrites fail because they skip the learning
- 10. Lehman's Laws - Untouched software decays; entropy is the default
- 11. Hyrum's Law - Your real API is everything observable, not just what's documented
- 12. Goodhart's Law - Metrics as diagnostics: good. Metrics as targets: dangerous
- 13. Hofstadter's Paradox - Uncertainty is irreducible; plan for it instead of against it
- 14. Parkinson's Law - Generous timelines produce extras, not quality
- 15. Leaky Abstractions - The layer below waits until you need it most to become the problem
- 16. Linus's Law - More eyes help, but diverse expertise matters more than volume
- 17. KISS - Complexity feels productive but creates puzzles for future readers
- 18. Kernighan's Principle - Write below your max ability so you can still debug it
- 19. Postel's Law - Strict output, tolerant input, but not at the cost of security
- 20. Knuth's Principle - Optimize what the profiler says, not what your intuition says
- 21. Chesterton's Fence - Understand why something exists before you remove it
- 22. Gilb's Principle - Imperfect measurement beats no measurement
- 23. Dunning-Kruger Effect - High confidence + low experience = slow down and investigate
- 24. Technical Debt - Shortcuts are loans; the interest compounds if you don't repay
- 25. Reversibility - Two-way doors need speed; one-way doors need deliberation
- 26. Murphy's Law - Make failures survivable, not impossible
- 27. Sturgeon's Law - Most output is mediocre; the skill is knowing where to invest
- 28. Zawinski's Law - Successful software absorbs adjacent problems until it collapses
- 29. Cunningham's Law - Wrong answers provoke better conversations than questions do
Tensions
- Knuth vs Amdahl - When to optimize? Always know the bottleneck; only act on the profiler
- KISS vs Murphy - Simplicity or safety? Defend at boundaries; trust well-tested internals
- Gall vs Chesterton - Simplify or preserve? Gall for new work; Chesterton when modifying what exists
- Linus vs Ringelmann - More or fewer reviewers? Two thorough reviewers beat twenty casual ones
- Parkinson vs Hofstadter - Tight or generous deadlines? Short iterations with firm boundaries
- Goodhart vs Gilb - Measure or don't? Measure as diagnostic, rarely as incentive
- Postel vs Hyrum - Tolerant or strict input? Strict for new APIs; liberal + logged for mature ones
- Brooks vs Reversibility - When is adding someone right? Specialists for gaps; not generalists on late projects
- Brooks vs Bus Factor - Share knowledge or protect focus? Pay the small continuous cost, not the crisis cost
- Technical Debt vs KISS - When are shortcuts OK? Bounded debt with a repayment plan; otherwise just mess
- Pareto vs Murphy - Focus or defend broadly? Pareto for features; Murphy for failure modes
- Conway vs Gall - Org is already complex - now what? Conway as constraint; Gall as aspiration
- Technical Debt vs Chesterton - Pay the debt down? Investigate first - not all "debt" is actually debt
- Sturgeon vs Gilb - If 90% is mediocre, why measure? Measure cheaply; iterate; discard most
A distributed system can guarantee only two of: Consistency (every read gets the most recent write), Availability (every request gets a response), and Partition tolerance (the system keeps working when network messages between nodes are lost or delayed).
Source. Eric Brewer, keynote at ACM PODC, 2000. Formally proven by Seth Gilbert and Nancy Lynch, 2002. Formal proof (Gilbert & Lynch, 2002); universally accepted.
Further reading. Kleppmann, Designing Data-Intensive Applications (2017). Extended critique of CAP.
CAP is often misread as a menu: pick your favorite two. It isn't. Any system with more than one node will eventually see partitions, so partition tolerance isn't optional. The real choice is between consistency and availability when a partition happens. Techniques like bounded staleness, session guarantees, and quorum reads don't escape that trade-off; they change how it feels when it bites.
When the network splits, a system either refuses to serve stale data (some users get errors) or keeps serving it (some users get outdated data). A ride-sharing app can show drivers who might already be taken, or show nothing until it's sure. An e-commerce flash sale can oversell the last item, or lock out buyers while stock is confirmed. Reasonable people disagree on the right call.
Caveats. Kleppmann (Designing Data-Intensive Applications, 2017) argues CAP is misleading: partition tolerance isn't optional, so the real choice is always C vs A. Abadi's PACELC model adds the latency-consistency trade-off during normal operation. Most developers never make this choice directly; their database makes it for them. Irrelevant for single-node systems and for most CRUD apps where the database's default is fine.
The speedup from parallelism is limited by the sequential part.
Source. Gene Amdahl, 1967, "Validity of the Single Processor Approach to Achieving Large Scale Computing Capabilities," AFIPS Conference Proceedings. Mathematical result; standard in systems textbooks.
If 5% of your pipeline is sequential, you'll never get more than a 20x speedup no matter how many parallel workers you add. The sequential part is a hard ceiling. A single processor can't be made infinitely faster, so eventually you add machines; that horizontal scaling is exactly where the sequential fraction starts to matter.
The same dynamic plays out beyond CPUs. Inside an organization the sequential bottleneck is rarely labeled as one. It might be the one person who understands the deployment pipeline, or the consensus culture that needs five meetings before any decision ships. Adding more engineers doesn't help when they're all waiting in the same queue.
Caveats. Gustafson (1988) argued that in practice, you tend to solve larger problems with more processors, not the same problem faster. The sequential fraction often isn't fixed; redesign can shrink it. Amdahl assumes a fixed workload, Gustafson a fixed time budget. If your real constraint is I/O rather than CPU, the whole framing is wrong.
Individual output drops as team size goes up.
Source. Maximilien Ringelmann, experiments conducted in the 1880s, published 1913. Replicated by Ingham et al. (1974) and many subsequent studies. One of the oldest findings in social psychology, with strong replication.
Two forces are at work. Coordination: aligning ten people takes more effort per person than aligning three. Diffusion of responsibility: when many people share a task, each assumes someone else will handle the hard parts. You see this in code review, where large teams rubber-stamp, and on large on-call rotations, where ownership gets diluted until incidents start falling through the gaps.
Caveats. The original experiments measured physical tasks. Knowledge work behaves differently; larger teams can outperform smaller ones when the task rewards diverse expertise. The effect varies with culture, cohesion, and how cleanly the work can be partitioned. A team of ten specialists on genuinely separable modules is a different animal from ten generalists on one codebase.
Half the work is done by the square root of the people.
Source. Derek J. de Solla Price, 1963, Little Science, Big Science. Based on bibliometric data (scientific publications), not directly studied in software teams.
In a team of 9, roughly 3 people do half the work. In a team of 100, roughly 10 do. The ratio gets worse as the group grows. Losing a top contributor doesn't remove 1/N of capacity; it removes much more. The majority isn't dead weight, though. They do the other half plus the operational and support work that lets top contributors focus. Statistical reality, not a performance problem to fix.
Caveats. "Output" in software is notoriously hard to define (see Goodhart). Force-multiplier work like mentoring, architecture, or tooling is invisible to most output measures but can matter more than direct production. Strong pair or mob programming practices flatten the curve; so does small scale (under six people or so).
How many people need to disappear before the project is in serious trouble?
Source. Community-coined; no single attributable author. The term circulated on the c2 wiki and agile/XP mailing lists in the early 2000s and entered mainstream use from there. Sometimes called the "truck factor" or "lottery factor" (for those who prefer optimistic framing). Informal industry term; no formal research.
Price's Law tells you output is concentrated. The Bus Factor tells you knowledge is concentrated, and that's the risk. A bus factor of one means one resignation or illness can stall a project, and the bad part is that you don't notice until it happens.
I once inherited a deploy script with an unexplained sleep 45 in the middle of it and burned half an afternoon tracing why. The person who knew had left eight months earlier. That kind of knowledge doesn't show up in sprint metrics or org charts; you only find it when it's gone.
Raising the bus factor isn't really about writing documentation, though documentation helps. It's about making sure more than one person has recently done the hard parts: deployed to production, debugged a critical failure, made a non-trivial change to the core path. Knowledge that hasn't been exercised by a second person isn't really shared. It's just written down.
Caveats. In early-stage projects, a bus factor of one is sometimes the right call. Speed matters more than redundancy when you're still proving the idea should exist. Pairing, rotation, and documentation all take time away from delivery, so the cost isn't zero. If the whole company is two people, knowledge concentration is the least of your problems.
80% of effects come from 20% of causes.
Source. Vilfredo Pareto, 1896. Applied to quality management by Joseph Juran in the 1940s. The underlying power-law distribution is well-documented in statistics.
In software: 80% of bugs cluster in 20% of modules. 80% of users use 20% of features. 80% of incidents trace back to 20% of services. The heuristic is useful for prioritization. When twenty things need attention, roughly four account for most of the impact, and finding those four beats spreading effort evenly.
See also: Price's Law (uneven output among people). Together they suggest that a small number of people working on a small number of problems produce most of the value.
Caveats. The 80/20 split is an approximation; the actual ratio varies wildly. The principle is routinely misused to justify ignoring the "unimportant" 80% outright, when the long tail can matter a great deal. A single overlooked vulnerability in the tail is all an attacker needs, and compliance doesn't care about frequency. In any safety-critical domain the frequency framing is the wrong one.
Organizations design systems that mirror their communication structure.
Source. Melvin Conway, 1968, "How Do Committees Invent?" (Datamation). Named "Conway's Law" by Fred Brooks (1975). Empirically validated by MacCormack, Rusnak, and Baldwin at Harvard Business School (2012).
If your frontend team and backend team sync once a week, your system will have a hard boundary between frontend and backend with a formally negotiated API in between. Not because anyone designed it that way; that's just the path of least resistance for how those humans communicate. Architectural decisions are organizational decisions in disguise. You can't adopt microservices without autonomous teams, and a coherent monolith won't survive ownership fragmented across six groups.
This is also why local vs global optimization is so persistent: each team optimizes for its own structure and metrics (see Goodhart), producing a system that's locally rational but globally incoherent.
Caveats. The Inverse Conway Maneuver (deliberately structuring teams to produce the architecture you want) shows the effect isn't deterministic. Open-source projects with fluid structures don't always follow the pattern, and in small teams of two or three the law is too weak to notice. The effect is strongest in large organizations with rigid hierarchies.
Adding people to a late software project makes it later.
Source. Frederick P. Brooks, Jr., 1975, The Mythical Man-Month. Based on the IBM OS/360 project. One of the most cited books in software engineering. Still the best book on software project management.
Communication paths grow quadratically: n(n-1)/2. A team of 5 has 10 paths; a team of 20 has 190. The deeper issue is knowledge transfer. Software projects accumulate context that lives in people's heads, and when you add someone new, experienced people stop producing and start teaching. On a late project, you're burning your scarcest resource (experienced people's time) to create your most abundant one (inexperienced capacity). The usual correct response to lateness is to cut scope, not add headcount.
See also: Reversibility. Adding a specialist to fill a specific gap is a two-way door; adding generalists to a late project is a one-way door into Brooks's trap.
Caveats. Brooks himself noted that the observation is strongest for highly interconnected work. Adding a specialist (a DBA, a security reviewer) can help without the overhead penalty. Ramp-up cost varies enormously with documentation quality and codebase clarity. A project that's behind because it's been genuinely understaffed from day one is a different case from a late-stage, complex one.
A complex system that works is always built from a simple system that worked first.
Source. John Gall, 1975, Systemantics (later The Systems Bible). Based on general systems theory, not a specific study. Semi-satirical; no controlled study. Short, funny, devastating.
You're always wrong about the destination until you've shipped something and watched it collide with reality. Teams that get into trouble spend six months building infrastructure for a product that hasn't proven it should exist. The ones that succeed ship something embarrassingly small, learn what actually matters, and build from there.
Rewrites are the same pattern. The original system is ugly because it absorbed years of edge cases. A rewrite starts clean but ignorant, and usually runs out of patience before it re-learns every lesson the original did.
This entry, along with KISS and Kernighan's Principle, argues for simplicity from different angles: evolutionary reality (Gall), design goal (KISS), and debugging constraint (Kernighan).
Caveats. The original book is semi-satirical. Some complex systems have been designed successfully from scratch when the problem domain was well-understood enough to specify. If requirements are stable and already documented through years of operation, or the domain is safety-critical and iterating in production isn't an option, this isn't advice you want to follow.
Software that is being used must be continually adapted or it becomes progressively less satisfactory.
Source. Manny Lehman, 1974-1996, culminating in "Laws of Software Evolution Revisited" (1996). Based on empirical study of IBM's OS/360. Strong empirical foundation for E-type (real-world-embedded) systems.
Lehman formulated eight laws over two decades. The quote above is the first (Continuing Change), but three others hit just as hard:
- Increasing Complexity (1974): as a system evolves, its complexity increases unless work is done to reduce it. Entropy is the default; simplicity requires effort.
- Conservation of Organizational Stability (1980): the rate of development is roughly constant regardless of resources allocated. Echoes Brooks; throwing more people at it doesn't change the rate.
- Conservation of Familiarity (1980): the system can't grow faster than the team's ability to understand it. Connects to Bus Factor; concentrated knowledge becomes the constraint on how fast the system can safely evolve.
The common thread: a system that nobody touches doesn't stay the same. It decays, not because the bits rot but because everything around it moves. Dependencies release security patches, operating systems drop old APIs, user expectations shift, regulations change. Software that ages well isn't software that stops being touched; it's software where change is small, continuous, and routine.
This is the software version of the Tragedy of the Commons: shared systems decay when no one owns them. Conway's Law explains why. Ownership follows org structure, and the gaps between teams are where maintenance falls through.
Caveats. Lehman distinguished between S-type (specification-driven), P-type (problem-driven), and E-type (real-world-embedded) programs. His observations primarily apply to E-type. A sorting algorithm doesn't "decay," and firmware on hardware that isn't going anywhere doesn't feel the same pressure. The more external dependencies a system has, the more the law bites.
With enough users, every observable behavior of your API becomes someone's dependency.
Source. Hyrum Wright, Google engineer. Documented at hyrums.law. Single-practitioner observation; consistent with broad industry experience.
Your documentation says the response field order doesn't matter. Somewhere, a consumer is parsing your JSON with a regex that assumes "id" comes first. I once broke a client by alphabetizing a field order nobody was supposed to depend on, and reverted within a day. The contract isn't what you documented; it's what you shipped. Every observable behavior (response times, error formats, header casing, sort order) becomes load-bearing somewhere. If you need freedom to change something, don't expose it.
See also: Robustness Principle. What you tolerate becomes depended upon.
Caveats. Scale-dependent. With a handful of consumers, undocumented behavior is unlikely to be depended upon, and strong API versioning mitigates the effect. For internal tools with a small, known user base, or when you own both sides of the interface, you can usually change things without drama.
When a measure becomes a target, it stops being a good measure.
Source. Charles Goodhart, 1975 (British monetary policy). Generalized by Marilyn Strathern (1997). Well-documented across economics, education, healthcare, and software.
Further reading. Kim, Humble, Forsgren, Accelerate (2018). The DORA metrics work, and the Goodhart/Gilb tension navigated carefully.
The moment you tie incentives to a metric, people optimize for the metric instead of the outcome it represents. Set a target for test coverage and you get tests that exercise code paths without asserting anything meaningful. Measure velocity and story-point estimates inflate. Track deploys and people split one logical change into five. The metric isn't the problem; incentivizing it is. Diagnostically, metrics can be useful. As targets, they corrode.
See also: Gilb's Measurement Principle, the essential counterpoint.
Caveats. Some metrics are robust as targets, especially composite ones. Pairing metrics (velocity plus defect rate, for instance) can mitigate gaming. A metric used purely as a diagnostic with no incentive attached doesn't trigger the law, and a metric that closely corresponds to the actual goal and is hard to game can sometimes survive being a target.
It always takes longer than you expect, even when you account for this.
Source. Douglas Hofstadter, 1979, Gödel, Escher, Bach. A self-referential observation, not a formal result. Self-referential aphorism; no formal study.
The recursive phrasing is the point. You can't outsmart this by adding a buffer, because you'll add the wrong buffer. The work itself is unpredictable: the straightforward task uncovers a hidden dependency, or the library doesn't handle your edge case, or the requirement turns out to be ambiguous once you poke it. Every estimation technique is an attempt to manage that uncertainty; none of them eliminate it. The best you can do is plan for uncertainty explicitly, with small deliverables, course corrections, and estimates treated as probability distributions instead of commitments.
Caveats. Reference class forecasting (Kahneman and Tversky) demonstrably improves accuracy, and teams with stable velocity do get better at estimating the kind of work they keep doing. The paradox is strongest for novel work. Routine tasks with historical data, or bounded scope with no external dependencies, are where estimates tend to come closest to reality.
Work expands to fill the time available.
Source. C. Northcote Parkinson, 1955, The Economist. Originally satirical. Not based on controlled research, but widely confirmed anecdotally.
Further reading. Parkinson, Parkinson's Law (1958). More insightful about organizational behavior than most management textbooks.
A two-week sprint assigned one task will produce a gold-plated, over-engineered version of that task. Not from laziness; humans fill available time with refinement. Generous timelines don't produce proportionally better work. They produce the same work plus unnecessary extras. Timeboxing forces the question of what actually matters.
Caveats. Satire, not research. Generous timelines can produce better outcomes when the work benefits from exploration, and tight deadlines produce burnout and technical debt of their own. What looks like gold-plating is sometimes just getting the edge cases right.
All non-trivial abstractions, to some degree, are leaky.
Source. Joel Spolsky, 2002, blog post "The Law of Leaky Abstractions." Single-author observation; consistent with universal industry experience. A blog post that became permanent vocabulary.
Every abstraction eventually leaks. Your ORM hides SQL until it generates a query that locks the table for thirty seconds. Your HTTP client hides TCP until connection pool exhaustion turns every request into a timeout. Your cloud provider hides servers until an availability zone goes down and you discover your "distributed" system was on three racks in the same building.
The one that sticks with me was an ORM happily issuing an N+1 inside a loop over a thousand-entity list. Everything worked fine in staging with ten entities. Production fell over in minutes. That's the pattern. You don't need to know the layer below daily, but on the day the abstraction betrays you, nothing else will help.
Caveats. Not all leaks matter in practice. Many developers use ORMs and cloud services for years without hitting meaningful ones, and some abstractions (garbage collection is the obvious example) are so well-implemented that leaks are vanishingly rare. A simple wrapper around a well-behaved library, used well within its design parameters, is one of the cases where you can just trust the layer.
Given enough eyeballs, all bugs are shallow.
Source. Eric S. Raymond, 1997, The Cathedral and the Bazaar. Named after Linus Torvalds. Partial support from code review research (Rigby and Bird, 2013); diminishing returns demonstrated after 2-3 reviewers.
When many people look at code, someone spots the defect everyone else missed. This is the strongest argument for genuine code review: second-pair-of-eyes examination, not rubber-stamp approval. Two thorough reviewers with different expertise catch most of what matters. Twenty casual reviewers mostly produce noise. Optimize for review quality, not count.
Caveats. Heartbleed (CVE-2014-0160) lived in OpenSSL's open-source code for over two years. The assumption that people actually read the code is often wrong, and reviewer count is a poor substitute for reviewer quality. Bugs that hinge on deep knowledge of system invariants, or on specialized domains the reviewers don't know, slip through plenty of eyeballs.
Keep it simple. Anything beyond that is overhead.
Source. Attributed to Kelly Johnson, Lockheed Skunk Works, 1960s. The principle predates software; it comes from aircraft design, where unnecessary complexity killed pilots. Engineering aphorism; no formal study.
Simplicity isn't about writing less code. It's about making fewer decisions that future readers have to reverse-engineer. Every abstraction, every indirection, every configurable option is a question someone will eventually have to answer: "why is this here?" The hard part is that complexity feels productive. Extracting a base class or adding a strategy pattern feels like engineering, but if the problem doesn't demand the flexibility, you've just added a puzzle. Before adding an abstraction, ask whether you need it, not whether it's possible.
This is the same instinct behind YAGNI (You Aren't Gonna Need It) and Occam's Razor: all of them push toward not adding what you can't yet justify.
Caveats. "Simple" is subjective. Sometimes the simple solution just shifts complexity elsewhere, and premature simplification can be as harmful as premature optimization. Cryptography and distributed consensus aren't going to be simple; pretending otherwise produces worse code, not better. If requirements genuinely demand flexibility you already know you need, adding it up front isn't over-engineering.
Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.
Source. Brian Kernighan and P.J. Plauger, 1974, The Elements of Programming Style. The "twice as hard" claim is rhetorical, but the argument about cognitive headroom is sound. Rhetorical framing; cognitive-load argument widely accepted. Concise, opinionated, still relevant.
If you spent all your brainpower writing something as clever as you could manage, you have nothing left when it breaks. The clever bitwise trick, the deeply nested ternary, the regex that handles twelve cases in a single expression: these are all write-once constructs. The design constraint this implies is to write code at a level below your maximum ability, so you can still reason about it under pressure, at 2am, six months from now.
Caveats. Performance-critical code sometimes requires cleverness that earns its keep. Some algorithms are inherently hard; the complexity lives in the problem, not the solution. A well-tested hot-path optimization with measurable value gets a pass, and so does any algorithm where the simpler version would be wrong.
Be conservative in what you send, liberal in what you accept.
Source. Jon Postel, RFC 761, 1980, describing TCP. Also known as the Robustness Principle. RFC convention; contested in newer protocols.
A public API that rejects requests over a trivial formatting issue creates a terrible developer experience. An integration that chokes on a slightly malformed date string will cost you operational hours. The dark side is real, though. If everyone accepts garbage, nobody has incentive to stop producing it. The web is built on a mountain of malformed markup because browsers were too lenient, and no browser can ever become strict again without breaking half the internet. In security contexts, lenient parsing is actively dangerous.
See also: Hyrum's Law. If you accept garbage, someone will depend on your garbage-handling.
Caveats. RFC 9413 (Thomson, 2023) argues the Robustness Principle has caused more harm than good, and the IETF has moved toward stricter parsing in newer protocols. Anywhere input handling is security-sensitive, leniency is the wrong default. For internal APIs where you own both sides, or new protocols where you can enforce strictness from day one, the principle doesn't really apply.
Premature optimization is the root of all evil.
Source. Donald Knuth, 1974, "Structured Programming with go to Statements," Computing Surveys. Widely cited; foundational to performance engineering practice.
Further reading. Knuth, The Art of Computer Programming (1968--) for the broader work.
The full quote matters: "We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%." Most performance intuitions are wrong. Profilers exist because human intuition about performance is unreliable.
This applies to architecture too. Don't shard your database before you've outgrown a single instance. Don't add a cache before you've confirmed the database is the bottleneck. Solve the performance problem you actually have, not the one you imagine having someday.
This is why Jeff Dean's "Latency Numbers Every Programmer Should Know" endures. Intuition says "memory is fast, network is slow," but the actual magnitudes surprise almost everyone. Measure, don't guess.
Caveats. Some optimization is structural and must be done upfront. Choosing O(n^2) when O(n log n) exists isn't premature optimization; it's a design mistake. Schema design and protocol choices are expensive to change later, and systems with hard performance requirements can't be patched after the fact.
Before you remove a fence, understand why it was put there.
Source. G.K. Chesterton, 1929, The Thing. Originally about reform, not software. Philosophical aphorism; no formal study.
That weird conditional you want to delete, the seemingly redundant null check, the method that appears to do nothing: these exist because someone hit a problem you haven't hit yet. Maybe a race condition under load. Maybe a vendor API that returns garbage in edge cases. The discipline isn't "never remove anything," it's "understand before you change." Read the git blame. Check for linked issues. If you can't find the reason, that's an argument for more caution, not less; context has been lost, which makes removal riskier rather than safer.
Second-order effects live here. Every fix changes the system, and changed systems produce new behavior you didn't predict. Lehman says entropy is the default; Chesterton says the fence you removed might have been holding it back.
Caveats. Sometimes the fence was put there by someone who was wrong. Legacy code contains bugs, cargo-cult patterns, and workarounds for problems that no longer exist. The principle should encourage investigation, not prevent all change. If git history confirms the reason no longer applies, or the original author can tell you it's safe to remove, there's no mystery left to respect.
Anything you need to quantify can be measured in some way that beats not measuring it.
Source. Tom Gilb, 1988, Principles of Software Engineering Management. Based on decades of consulting experience. Practitioner observation; no controlled research. Broader than the single quote: a full framework for quantifying software quality.
Further reading. Kim, Humble, Forsgren, Accelerate (2018). The DORA metrics work, and the Goodhart/Gilb tension navigated carefully.
The necessary counterpoint to Goodhart. Metrics can be gamed, yes, but flying blind is worse. You can't measure "developer productivity" directly, but you can measure deployment frequency, review lead time, incident rate, recovery time. None of those is productivity, but together they sketch a blurry outline, and a blurry picture beats no picture. Use metrics to ask questions, not to answer them.
Caveats. Some things are genuinely hard to measure without distortion. Bad proxy metrics can be worse than no metrics if they drive wrong behavior, and measurement has a cost that can exceed its value. In domains where measurement changes the behavior being measured (any Hawthorne-ish feedback loop), the act of tracking corrupts what you're trying to track.
The less you know about something, the more confident you tend to be.
Source. David Dunning and Justin Kruger, 1999. Widely cited as empirical research but with significant replication concerns (Nuhfer et al., 2016, 2017, argue the effect is partly a statistical artifact). The "Mount Stupid" curve popular online is not from the original paper. Included here as a useful heuristic for calibrating confidence, not as settled science.
Whether or not the specific cognitive effect holds up, the pattern is observable in software, most clearly in technology selection. The team member who just read a blog post about event sourcing is the most confident it will solve everything, and the person who has actually operated an event-sourced system at scale is full of caveats. I've been on both sides of this. The first time I picked up a "just add a frontend" task I didn't realize "just" was doing a week's worth of work, between browser quirks, accessibility, and a performance budget I hadn't known existed. When someone is very certain about something they haven't done before, that certainty is a signal to slow down.
Caveats. The core insight (self-assessment is unreliable for beginners) is better supported than the specific curve shape, and the effect may be smaller than popularly presented. Domains with fast, clear feedback (the compiler that tells you immediately) dampen it, and so does the habit of actively seeking external feedback before committing. Experienced practitioners estimating inside their own domain rarely show it.
Shipping first-time code is like going into debt. A little debt speeds development so long as it is paid back promptly with a rewrite.
Source. Ward Cunningham, 1992, experience report at OOPSLA ("The WyCash Portfolio Management System"). The metaphor was deliberately financial. Metaphor, not formal theory; widely adopted in industry.
What's often missed: Cunningham's original metaphor was about the gap between your understanding and the code, not about sloppy work. As you learn more about the domain, the code you wrote with less understanding becomes "debt" even if it was well-written at the time. The interest comes from the growing distance between what you know now and what the code reflects.
The metaphor's power is that it gives engineers and managers a shared vocabulary. "This will take an extra week" is hard to justify. "We're carrying six months of accumulated debt in the payment module and the interest is slowing every feature" is a conversation both sides can reason about.
See also: Lehman's Laws. Software decays even without shortcuts, and debt and decay compound together.
Caveats. Financial debt is quantifiable; technical debt is not. Teams use "technical debt" to justify any rewrite they want. Not all accumulated code problems are debt; some are just maintenance. Throwaway prototypes and short-lived code aren't "in debt." Neither is code you'd write differently today that works correctly and isn't causing problems.
Some decisions are one-way doors. Most decisions aren't like that. They're two-way doors.
Source. Jeff Bezos, 2015 Amazon shareholder letter. Management heuristic; no empirical research.
Most engineering decisions are two-way doors: choosing a library, structuring a module, picking an internal API shape. If you get it wrong, you can change it, and for those, speed matters more than thoroughness. One-way doors are the ones that are expensive or impossible to reverse: choosing a database engine for a billion rows, publishing a public API that external consumers will depend on, shipping a data format that gets persisted to disk. Those deserve deliberation.
Caveats. The distinction isn't always clear. Some decisions look reversible but have hidden lock-in (a framework that ends up permeating the codebase, or a proprietary cloud service). Some one-way doors disguise themselves as two-way ones until you try to walk back through them. When you can't tell which kind of door you're at, the safe default is to slow down.
Anything that can go wrong will go wrong.
Source. Widely attributed to Captain Edward Murphy, Edwards Air Force Base, ~1949. The exact origin is disputed. Folk aphorism; exact origin disputed.
In a system with enough users and enough time, every failure mode will eventually occur. The network will partition. The disk will fill up. The dependency will return garbage. The certificate will expire on a holiday. The response isn't to prevent all failures; it's to make them survivable. Circuit breakers, retries with backoff, health checks, automated rollbacks, runbooks. Systems that stay up aren't the ones that never fail. They're the ones that recover fast.
The cultural version matters too. Blameless post-mortems, incident reviews, and chaos engineering all stem from accepting this as a given.
Caveats. Over-application leads to excessive defensive coding: wrapping every line in try-catch, guarding against impossible scenarios. Defensive design has a complexity cost, and unnecessary defenses introduce their own bugs. For well-tested code paths, or simple systems with few real failure modes, adding defense-in-depth can do more harm than the threat it was meant to counter.
90% of everything is crap.
Source. Theodore Sturgeon, ~1957. Sturgeon himself called it a "revelation," not a law, after critics dismissed science fiction as mostly bad. His point: 90% of everything is bad, so singling out one field is meaningless. Aphorism; no formal study.
Most features won't be used. Most abstractions won't pay off. Most technical initiatives won't deliver their promised value. This is the base rate of creative work, not a sign of failure. Triage is where the skill lives; saying no to the 90% creates space to make the 10% excellent. The risk is reading the law as cynicism. It doesn't mean effort is pointless, it means you should be selective about where you direct it.
Caveats. The 90% figure is arbitrary. In mature domains with strong quality gates (aviation, medical devices), the rate is much lower. Using this as justification for low standards is the opposite of its intent. In regulated industries with mandatory quality enforcement, or anywhere strong quality gates keep the 90% from ever shipping, the law describes something that never happens.
Every program expands until it can read mail. The ones that cannot are replaced by ones that can.
Source. Jamie Zawinski, ~1995, during his time at Netscape. Industry observation; no formal study.
Successful software attracts adjacent use cases like a planet attracts debris. Users don't want to switch contexts, product managers don't want to lose engagement, engineers enjoy building new things more than maintaining old ones. So the tool grows. Your project management tool adds chat. Your chat tool adds a project board. Your CI adds deployment, your deployment tool adds monitoring, and everyone converges toward the same bloated middle. I've watched a lightweight internal tool turn into a clone of the product it was built alongside within two years, because every absorbed feature looked like a small win at the time. The defense isn't resisting all growth; it's being intentional about which problems you absorb and which you integrate with.
Caveats. Plenty of products stay focused indefinitely. The Unix ecosystem is the long-running counterexample, even though the individual tools (bash, vim, git) all bloated considerably over time. The ecosystem stayed composable; the tools did not. Strong opinionated leadership is what usually keeps the bloat out.
The fastest way to get the right answer online is to post the wrong one.
Source. Attributed to Ward Cunningham, but likely coined by Steven McGeady describing Cunningham's behavior. Internet folklore; attribution uncertain.
People are more motivated to correct errors than to answer questions. A question can be scrolled past; a wrong answer demands correction. In engineering, this shows up in design reviews and RFCs. A polished proposal gets rubber-stamped. A deliberately rough draft draws out critiques, alternatives, edge cases. It also works in debugging. Instead of "does anyone know why this fails?", state your theory ("I think this fails because X") and people who know the system will correct you.
Caveats. Only works in communities with sufficient expertise. Among the uninformed, the wrong answer gets accepted and amplified, and overuse erodes trust. In professional contexts where credibility is on the line, or regulated domains where the wrong answer can cause harm, the cost of the wrong answer swamps the benefit of the correction.
These ideas don't exist in isolation. Several directly contradict each other, and the skill isn't picking a side; it's knowing which one applies now.
Knuth vs Amdahl: when to optimize. Knuth says don't optimize prematurely. Amdahl says find the bottleneck. The resolution: Knuth is about micro-optimizations and speculative architecture. Amdahl is about structural constraints that cap your system. Always know where your bottleneck is (Amdahl). Don't optimize code that isn't the bottleneck (Knuth). Profile first, then act on the profiler.
KISS vs Murphy: simplicity vs safety. Every circuit breaker, retry loop, and fallback path adds complexity. The resolution: defense at system boundaries is worth the complexity (network calls fail, disks fill up, dependencies go down). Defense inside well-tested internal code paths usually isn't. Put your defenses where the failures actually happen.
Gall vs Chesterton's Fence: when to simplify vs when to preserve. One pushes toward simplification, the other toward caution. The resolution is temporal: Gall applies when you're building something new. Chesterton applies when you're modifying something that exists. Build simple. Refactor carefully.
Linus vs Ringelmann: more reviewers or fewer? Both are true. The resolution is in the type of contribution: diverse, expert reviewers add value; warm bodies don't. Two thorough reviewers with different expertise catch most of what matters. Twenty casual reviewers mostly produce noise.
Parkinson vs Hofstadter: tight deadlines or generous buffers? Tight deadlines produce focused but late work. Generous ones produce gold-plated but on-time work. The resolution: short iterations with firm boundaries. Instead of one six-month deadline, ship something every two weeks. Parkinson focuses each sprint. Hofstadter can only surprise you by two weeks.
Goodhart vs Gilb: measure or don't? The resolution is in how you use the number. Metrics as diagnostics (signals that prompt investigation) are Gilb's territory. Metrics as incentives (tied to performance reviews or bonuses) are Goodhart's. Measure everything. Incentivize almost nothing.
Postel vs Hyrum: tolerate messy input or enforce strictness? Accept malformed dates today, and tomorrow a consumer's pipeline assumes you always will. The resolution depends on lifecycle stage: for a new API, be strict from the start. For a mature API with unknown consumers, be liberal but log what you're tolerating.
Brooks vs Reversibility: when is adding someone the right call? Adding a specialist to fill a specific, separable gap is a two-way door: low coordination cost, high leverage. Adding generalists to a tightly-coupled late project is a one-way door into Brooks's trap.
Brooks vs Bus Factor: spread knowledge or protect focus? Brooks says knowledge transfer is expensive: experienced people stop producing to teach. Bus Factor says concentrated knowledge is a ticking time bomb. The resolution is in the timing: proactive sharing (pairing, rotation, having a second person deploy) is cheap. Reactive knowledge transfer under pressure (onboarding someone after the only expert left) is Brooks's trap. Pay the small cost continuously or pay the large cost in a crisis.
Technical Debt vs KISS: when are shortcuts acceptable? KISS says avoid unnecessary complexity. Debt says borrow against the future to ship faster. The resolution: deliberate, bounded debt with a repayment plan is a tool. Debt that violates simplicity without a plan is just mess. If you can't articulate when you'll pay it back, you're not taking on debt; you're creating it.
Pareto vs Murphy: focus or defend broadly? Pareto says the vital 20% produces most of the value. Murphy says the 80% you ignore will bite you. The resolution: apply Pareto to feature development and optimization (build few things, build them well). Apply Murphy to failure modes (defend broadly, because the failure you didn't plan for is the one that pages you at 3am).
Conway vs Gall: what if the org is already complex? Conway says architecture mirrors the org. Gall says start simple. Small teams naturally produce simple systems, so the two align. The conflict appears when the org is already large and rigid. Conway wins as a constraint (the architecture will match the org); Gall becomes the aspiration (fight for the simplest system the org can support).
Technical Debt vs Chesterton's Fence: should you pay this debt down? You want to clean up old code, but Chesterton says understand before you change. Not all "debt" is actually debt. Some is fence: decisions that look wrong but serve a purpose. The resolution: investigate before "repaying." If you can't explain why the code is the way it is, you haven't earned the right to change it.
Sturgeon vs Gilb: if 90% is mediocre, why measure? Gilb's metrics are how you find the 10% that matters. Sturgeon tells you most of your measurements will also be mediocre. The answer is to measure cheaply, iterate on what you measure, and accept that most metrics will be discarded. The ones that survive are how you find the signal.