In the early-morning hours of March 2016, tens of thousands of build pipelines around the world turned red at the same time. The cause: one man deleted one of his packages from npm. The package was called left-pad. Its entire source code is eleven lines; its function is “pad a string on the left with spaces.” His reasons had nothing to do with any of its users, yet thousands of projects–Babel and React included–instantly failed to build, because somewhere on a deep branch of their dependency trees sat this eleven-line package. Nobody had broken a single line of code. The world changed: a dependency you’d never heard of, buried a dozen layers down, vanished.
On December 31, 2020, Adobe ended Flash support, and two weeks later began actively blocking Flash content. Countless internal enterprise systems, government portals, and education sites became archaeology dig sites overnight. The developers of those systems had mostly left long ago. Not a single line of code changed, and the systems died anyway. What killed them wasn’t a bug. It was the calendar.
Every veteran programmer has also seen the third kind: that stretch of legacy code nobody dares to touch. “Don’t touch this function”–Dave said so. Dave left five years ago. It has no documentation, no tests, and call relationships like a bramble thicket; adding one line of logging requires a three-day risk-assessment meeting. It still runs, but nobody can explain why it runs, and nobody can make it better in any way. It isn’t a living system. It’s a specimen of one.
What these three stories share: from the code’s point of view, nothing happened. No new bug was written, no attack occurred, no hardware failed. The system got worse on its own. The industry files this phenomenon under “technical debt” and then reasons about it with financial logic: you incurred a debt, you calculate the interest, you find a chance to repay the principal.
This article argues that the “debt” metaphor is wrong at the root–and wrong systematically, in ways that matter. The physics that actually applies here isn’t finance. It’s thermodynamics. Technical debt isn’t debt; it’s entropy. And the engineer’s position in this framework snaps into focus: you are not a producer of code. You are a source of negentropy.
That sounds like mysticism, so let me put the disclaimer up front: like the Heisenbug article, this piece holds itself to one standard–the analogy must be mechanical, not decorative. Section X honestly covers where the analogy holds and where it breaks. Borrowing from physics here isn’t a bid to sound profound; it’s because thermodynamics happens to supply a mechanism for the three things the financial metaphor cannot explain: why untouched systems inevitably rot, why “we’ll clean it up later” never happens, and why engineers’ sustained effort is itself the system’s source of order.
I. Correcting the Metaphor: Technical Debt Is Not a Financial Problem
Let’s first give “technical debt” a fair hearing, because its popularity over three decades was earned. The metaphor performed one communication task superbly: explaining to management–people who don’t live in the code–why engineers need time to fix things with no visible output. Interest = slowed future development; principal = one-time repayment cost. When Ward Cunningham coined the term in 1992, this is exactly what he meant: to make a release, you knowingly write some code that isn’t clean, and in exchange you pay a little extra friction every future time you touch it.
But its success as a communication tool hides its failure as a mental model. Financial debt makes three implicit promises, and software degradation keeps none of them:
Promise one: the interest rate is calculable. A debt has a definite interest, so you can compute the cost of delay. Software degradation costs cannot be calculated, because they propagate through coupling. A careless abstraction’s cost doesn’t show up in the abstraction itself; it shows up in every future footstep that crosses it. You don’t know how many feet, or how many steps. After the log4j incident (December 2021), countless teams’ first question was “wait, are we even using log4j?” The answer: “yes–in your dependency’s dependency’s dependency.” When you can’t even measure the scope of the exposure, there is no interest rate to compute.
Promise two: the debt can be settled. A financial debt has an endpoint: paid off, account closed, page turned. Software degradation has no balance you can zero out. You can refactor a module away, but the refactoring itself introduces new comprehension cost and new risk. And more fundamentally, as the next section shows: even if you take on no new debt, the old balance keeps growing on its own. Financial debt does not do this. (Well, compound interest does–but compounding doesn’t conjure new creditors out of nothing just because you sat still.)
Promise three: paying it down is linear. You can pay a debt gradually, a little at a time, and your situation monotonically improves. Software degradation is nonlinear, with phase transitions: a system will “seem fine” for a long stretch, then past some point enter a different regime–every change spawns three new problems, and incremental improvement is no longer economically rational. A big ball of mud isn’t grown; it’s crystallized. Past the critical point, “pay 10% more per month” can no longer bring you back to the healthy zone. The financial model knows nothing of phase transitions.
Cunningham himself came forward decades later to explain what he’d meant: the metaphor was about the decision–consciously trading future friction for present speed–not a license for “write it badly now, fix it later.” But language, once it leaves its creator, grows on its own. In most organizations, “technical debt” in actual use is a thermodynamic problem booked as a muddled ledger: no interest rate, no ledger, no settlement date–just a feeling that keeps getting heavier.
So let’s switch metaphors. The physical system a codebase actually resembles is not a balance sheet; it’s a thermodynamic system. A codebase is an open system, continuously exchanging “energy” (engineering effort) and “matter” (dependencies, data, people) with its surroundings. Its spontaneous direction is degradation; maintaining order requires sustained input from outside. Let’s build that correspondence layer by layer.
II. Software Entropy: Disorder Is the Number of Ways to Deviate from Intent
In thermodynamics, Boltzmann’s definition of entropy is almost embarrassingly plain:
$$S = k \ln W$$
$W$ is the number of microstates the system can be in. Entropy isn’t the feeling of messiness; it’s something you can count: how many ways the system can exist that you cannot distinguish from each other but which behave differently. More possible states, more entropy; stronger constraints, fewer possible states, less entropy.
In information theory, the formula Shannon wrote down in 1948 for the uncertainty of an information source is, mathematically, the same object as Boltzmann’s entropy. There’s a well-worn anecdote here: Shannon was unsure what to call his quantity, and von Neumann suggested “entropy”–“no one really knows what entropy is, so in any debate you’ll always have the advantage.” Anecdote aside, the mathematics is serious: “how many states can this system be in” and “how much uncertainty do I have about this system” are two faces of one coin. Which lets us define software disorder without appealing to anyone’s feelings:
Software entropy = the number of behavioral states the system can actually be in, in excess of the states its design intent allows.
What your program should be is a small set of legal states, fenced in by the spec, the types, and the tests. What it can actually be is determined by everything you fail to constrain: every version of every package in your dependency tree, every shape the data might take, every combination of config flags, every interleaving of concurrent operations, every environment variable. The more corners you fail to constrain, the larger the actual state count $W$, and the more ways the system can deviate from intent–that’s entropy. Not having hit a bug doesn’t mean the system is in a legal state; it means this particular roll of the dice hasn’t landed on one of the illegal ones yet.
A real event puts flesh on this definition. After log4j, “what components do we actually run?” became the soul-searching question of engineering organizations worldwide. Most could not answer. A modern application’s dependency tree easily runs to hundreds or thousands of transitive dependencies–every layer can change, go unmaintained, or carry a vulnerability. The system’s actual state count long ago exceeded any individual’s comprehension. This isn’t a moral failing; it’s structural: you are using a linearly-shrinking mind to constrain an exponentially-expanding state space.
And here’s an example precise enough to interlock with the debugging series: undefined behavior (UB). When the C/C++ standard declares a class of behavior “undefined,” it is writing into the contract: “these states, the language does not constrain.” The set of legal states is deliberately enlarged by the standard, and the optimizer sails freely through that enlarged state space–it is entitled to assume “no UB” and transform code accordingly. This is why the same source can compile into two semantically different programs under -O0 and -O2. Restated in the language of entropy: UB moves the cost of the state space out of the specification and into the runtime environment; the states nobody constrains end up being dice rolled by whoever’s compiler, whoever’s heap layout.
This section established one definition. The next section uses the second law to answer the most unsettling question: why does the system rot even when nobody touches it?
III. The Second Law, Stated for Software: The Environment Is a Heat Bath, and Frozen Systems Rot Anyway
The second law of thermodynamics, in its simplest form: the entropy of an isolated system never decreases. The everyday version is blunter: things fall apart on their own. Coffee goes cold, rooms get messy, metal rusts. Nobody adds the mess to the room; mess is the default direction, and order is the thing that demands explanation.
Software people observed this long ago and even named it: bit rot. A program that ran fine, untouched, suddenly stops working years later. Folk explanations trend mystical (“bits flipped on the disk,” “cosmic rays”), but the real mechanisms are neither mysterious nor rare–they’re just rarely written down in one place. Written down, they turn out to be a concrete implementation of the second law:
The key is that software is never an isolated system. You can freeze the code. You cannot freeze the code’s world.
A “frozen” program is actually soaking in a heat bath that keeps changing:
| What the heat bath changes | Real cases |
| Chains of trust | May 2020: the AddTrust root certificate expired, and HTTPS broke en masse on older devices and apps. September 2021: Let’s Encrypt’s old cross-sign expired, and devices on Android below 7.1.1 threw certificate errors across the board |
| Protocols | From 2020, major browsers disabled TLS 1.0/1.1; a population of old-protocol-only clients and servers died silently |
| The dependency ecosystem | left-pad (2016): the heat bath deleted a state. npm rewrote its unpublish policy in response |
| Maintainers’ attention | event-stream (2018): the original author, no longer interested, handed the package to a stranger; malicious code reached the Copay bitcoin wallet. faker.js/colors.js (2022): the maintainer sabotaged his own packages–an infinite loop here, a deletion there–and thousands of pipelines went down with them |
| Time itself | Y2K; the 32-bit time_t overflow on January 19, 2038; timezone rules change every single year |
| Platform policy | 2014: YouTube API v2 shut down; old smart TVs bricked. August 2021: GitHub removed password authentication for git, and every CI script with a hardcoded password died on the spot. December 2020: Flash EOL (the second story in this article’s opening) |
| Runtime evolution | Python 2 reached end-of-life on January 1, 2020; the ecosystem spent a decade and still didn’t finish migrating |
Read down the list and a pattern emerges: not a single row requires your system to make a mistake. Your code stays perfect; the heat bath moves regardless; your position relative to the environment shifts. In physics terms: even if the system’s own entropy doesn’t change, a system coupled to its environment sees its entropy relative to the environment grow. Coffee in a room goes cold not because the coffee molecules went bad, but because the room keeps pumping away its warmth.
Software engineering, in fact, discovered the second law empirically decades ago. In the 1970s, Meir Lehman and Larry Belady tracked the evolution of IBM’s OS/360 over roughly ten years and distilled the “laws of software evolution.” One became known as the law of increasing complexity: unless active work is done to reduce it, the complexity of a system in real-world use will increase over time. Notice the phrasing: “unless active work is done.” That’s thermodynamic phrasing, not financial phrasing. Finance says “unless repayment”; Lehman says “unless work is done.” The difference: repayment has an end; work doesn’t. The second law has no concept of “paid off.” It only asks: was the work done today?
The Pragmatic Programmer borrowed “broken windows” from criminology to make the same point: one unrepaired broken window in a building, and soon every window is broken. That analogy is half right–it captures the contagiousness of disorder–but it never explains why “nobody repairs it” is the norm rather than the exception. Thermodynamics supplies the missing half: not repairing is the spontaneous direction; repairing is swimming upstream. Upstream takes energy, and energy is always scarce. Which brings us to the most important section of this article.
IV. Dissipative Structures: Order Is a Flow, Not a Stock
Up to here, the second law describes only the downhill direction. But the physicist Ilya Prigogine (Nobel Prize in Chemistry, 1977) studied a strange class of systems that live precisely far from equilibrium yet maintain a high degree of order for long periods. A vortex keeps its shape in a stream; a flame keeps its outline while burning; an organism spends decades resisting its own decomposition. What they share: not that they disobey the second law, but that they maintain local low entropy by continuously absorbing energy and continuously exporting entropy to the environment. Prigogine named them dissipative structures.
The crux of a dissipative structure: its order is not a stock; it’s a flow. A vortex is not a thing; it’s a process the water is doing. Cut off the current and the vortex is not “preserved”–it simply stops existing. Life is the same: an organism is not a durable good; it’s a river of ongoing metabolism.
Now look at a codebase. Every trait of a healthy codebase is a trait of a dissipative structure:
- CI runs every day (metabolism);
- dependencies upgrade every week (exchange of matter with the environment);
- refactoring happens continuously (exporting entropy outward);
- docs and tests update alongside the code (storing the “why” outside the system).
And a “frozen” codebase–no upgrades, no changes, just keep it “running”–is not a preserved order. It’s a vortex with its current shut off. It doesn’t hold still in its former state; it slides from “maintaining” into “decomposing.” The table in Section III is its decomposition schedule.
The most sobering real-world footnote is Heartbleed (2014). OpenSSL was then guarding the cryptographic handshakes of more than half the world’s websites, while its foundation received on the order of two thousand dollars a year in donations, with a core maintainer group you could count on one hand. The mismatch between the system’s size (how much of the world depended on it) and its metabolism (the energy flowing in) was three orders of magnitude. The vulnerability was not an accident; it was the predictable product of a dissipative structure in chronic energy starvation. Afterward, the Linux Foundation created the Core Infrastructure Initiative to fund it–which is, at bottom, the industry finally admitting: the energy flow this structure needs must actually exist. Prayers and gratitude are not substitutes.
Now take the knife of “order is a flow” and hold it to the most common lie in engineering: “Ship it like this now; we’ll refactor later.”
Under the financial metaphor, the sentence almost works: debt can be deferred. Under thermodynamics, it directly violates conservation of energy. Locally lowering entropy requires injected energy, and “later” is not a time when energy is more abundant. Every future sprint also has to fight the entropy the future produces (new requirements, new dependencies, new environmental shifts). Today’s energy budget has no surplus, and neither will later’s. Engineering hours cannot be banked. Every “later” is an IOU written against a future that will be exactly as broke as the present. This is not a discipline problem or an attitude problem. Conservation of energy does not extend credit.
So the right question was never “when do we pay the debt back” but “what is this system’s metabolic rate?” The maintenance budget is not a number you withdraw from savings; it’s a basal metabolic rate. Fall below it and the system enters decomposition. You can lose weight; you cannot stop breathing. Google’s internal practice is an extreme but real reference point: their monorepo executes hundreds of automated large-scale refactors per week (change an API signature, and robots update every call site). There, order is industrially and continuously produced. Don’t envy the scale; read the principle: they don’t owe less debt. They metabolize more steadily.
V. Maxwell’s Demon and Landauer’s Principle: Entropy Can Be Moved, Never Destroyed
Section IV left a door open: dissipative structures “export entropy to the environment.” This section works out where the entropy actually goes. It leads to a conclusion that surprises people: refactoring doesn’t destroy complexity; it only decides where the complexity lives. And along the way it answers what, exactly, an engineer is in this physical picture.
In 1867, Maxwell proposed one of the most famous thought experiments in the history of physics. Imagine a demon stationed at a little door between a hot gas and a cold one. It watches every approaching molecule: fast ones get waved through, slow ones get held back. Over time, hot and cold separate; order appears; and the demon, apparently, has done no work at all. This demon tormented physics for over a century: if it worked, the second law had a loophole.
The resolution took three steps, and each one maps precisely onto software:
- Szilard (1929): the demon’s magic is information. It knows each molecule’s speed; that knowledge is what lowers entropy.
- Landauer (1961): information is physical, and erasing information has a physical cost–wiping one bit dissipates at least $kT\ln 2$ of energy. Deletion is not free.
- Bennett (1982) closed the loop: the demon’s memory is finite. It must keep erasing old records to keep observing, and the cost of that erasure exactly cancels the order it creates. The demon isn’t free. The bill for lowering entropy is paid at the point of forgetting.
Now put the engineer in the demon’s position.
The engineer is Maxwell’s demon. Your capital for lowering entropy isn’t physical strength; it’s information: you know what the system should be, why each module exists, which approach was tried and failed. When you review code, you are doing the demon’s job–watching each incoming change, waving through the ones that reduce the state count, holding back the ones that expand it. The difference between a senior engineer and a junior one is, at bottom, the difference in “information about molecule speeds.”
But Landauer’s principle immediately issues a warning–and it’s the exact lesson the software industry spent thirty years of tuition slowly learning:
Deletion is not free. When you delete a piece of code, you delete more than code; you delete the entire context of why it existed. That act of erasure comes with a bill. Either you pay now–by transferring the “why” somewhere outside the system (tests, ADRs, commit messages written like a human wrote them)–or you pay later, when some future person (very often you, three months older) steps on the same rake and reinvents the same “why” from scratch. Tests and architecture decision records are not bureaucratic documentation requirements. They are the bill you pay to Landauer’s principle: storing “the system must behave like this” and “here’s why it was done this way” outside the system, making deletion cheap and forgetting survivable.
Apply “entropy can only be moved, never destroyed” to refactoring, and you get a list every architect should memorize. The complexity “removed” by a refactor has exactly three possible destinations:
- Transferred into clearer structure (modularization, layering, converged APIs): the state count gets locked into a smaller cage. Best outcome.
- Exported to external storage (tests, docs, git history, ADRs): the complexity continues to exist, as searchable explanation; the cost is maintaining that storage. Second-best, and necessary.
- Left in people’s heads: a few people “just know” how the whole thing works. This is the worst destination, because this storage medium evaporates–going home clears the cache; resigning is a reformat.
The third destination is the thermodynamic definition of bus factor: what fraction of the negentropy required to run the system is stored on a medium that evaporates? In the event-stream and faker.js incidents, what evaporated was the maintainers themselves. In many companies, what evaporates is the architect who “understood everything.” Once the medium is gone, whatever order never made it out into structure or documentation turns permanently back into entropy.
This section also deserves one real and deeply respectable counter-example–the highest recorded standard of “exporting entropy.” During the development of Windows 95, the team discovered that SimCity 2000 kept using memory after freeing it–a textbook use-after-free by today’s vocabulary, written in code that was obviously never going to be fixed. Raymond Chen’s team didn’t respond by demanding the world’s old software upgrade (pushing the energy cost onto the players least able to pay it). They had the operating system pick up the tab: if the process is SimCity, don’t actually free that memory. Over the following decades, the Windows application-compatibility layer (appcompat shims) accumulated thousands upon thousands of controlled rules like this. In thermodynamic language: Microsoft did not destroy the old software’s entropy. They exported the disorder scattered across millions of users into one centralized, managed, auditable structure. It is an underrated feat of negentropy engineering: acknowledge the entropy exists, and build it a reservoir.
VI. Free Energy and Phase Transitions: Between “Incremental Refactoring” and “Rewrite Only,” There Is a Critical Point
The first five sections described gradual processes. This one is about sudden change.
Thermodynamics has a concept called free energy: the part of a system’s total energy that is actually extractable and usable. A cup of boiling water and a barrel of lukewarm water can contain the same amount of heat, but only the cup can drive an engine–because what’s usable is not the total; it’s the part with a gradient against its environment. Codebases have an exact counterpart: a feature-complete system can already be “lukewarm water”–all capability present, and no new capability extractable. The system’s size is still there; the system’s free energy is gone: every unit of capability is locked into structure entangled with the rest, unextractable.
And the exhaustion of free energy isn’t linear; it comes with a phase transition. Water at 99 degrees is water; at 100 it abruptly becomes steam. The formation of a big ball of mud (Foote and Yoder’s famous 1997 paper) works the same way: the system “still accepts changes” for a long stretch, then past some point enters a different regime–change one thing, break three. No new bad code suddenly appeared; entanglement crossed a threshold, and the propagation cost of every change jumped from “local” to “global.”
How do you know a system is approaching criticality? These signals arrive before any metric does:
- The radius of change keeps growing: a one-line requirement now touches five “unrelated” modules.
- The test suite loses signal: permanently red, trusted by no one, read by no one.
- The oral map becomes load-bearing: “ask Dave first” knowledge is now a precondition for change (the third destination of Section V has won).
- Change failure rates climb; hotfix cycles stretch: the system is increasingly “surprised” by every touch.
- Onboarding takes years: externalized storage nears zero; the negentropy lives entirely in skulls.
Past the critical point, the options change. The negentropy injection rate of incremental refactoring can no longer catch the entropy production rate–and the “pay 10% more per month” financial logic fails completely. What’s needed is a one-time injection of energy above the threshold: an isolated rewrite, the strangler fig pattern (build the new system around the old, inch by inch; named by Martin Fowler), or a wholesale re-architecture. Thermodynamically: you must melt before you can re-crystallize.
But rewriting has a canonical cautionary tale that anyone tempted to start from scratch should reread. In the late 1990s, Netscape decided to abandon the old code and rewrite the browser engine from zero. Planned at two years, it stretched to nearly four–during which the old product stopped evolving and competitors took the entire market. Joel Spolsky’s famous broadside, “Things You Should Never Do” (2000), was written about exactly this. Its core claim, restated in this article’s language: a rewrite throws away the code, but it cannot throw away the tacit knowledge. Many of those “stupid-looking” branches in old code were extracted, over years, from real environments of real users–they are negentropy that has already been paid for. Stored in the worst possible form (undocumented code), but stored. Flattening the codebase hands that accumulated order back to entropy with interest, and then spends four years earning it back. This is why, on the road through a phase transition, the strangler pattern beats the scorched-earth rewrite: crystallize block by block instead of melting the whole ingot–each step preserves the knowledge already banked, and the system stays alive throughout the rewrite.
Remember also the hysteresis of phase transitions: once past the critical point, restoring the old level of energy input does not return you to the old state. Recovery requires a one-time injection above the threshold. This is why the story “we only cut two people from last year’s headcount–how did everything suddenly fall apart?” replays every year. Nothing happened suddenly. The line was crossed long ago.
VII. Heat Death: The Most Stable System Is the Deadest System
Thermodynamics has a famous hypothetical ending for the universe: heat death. All temperatures equalize, no gradients remain, entropy maxes out. Note what’s horrifying about heat death: it isn’t destruction; it’s the absence of anything left to do. No temperature difference means no work; no work means no change. The system still exists; the universe still exists; nothing meaningful can ever happen in it again.
What is software heat death? Not a crash. Quite the opposite–an extremely stable system:
- It runs stably in production, one incident-free year after another;
- nobody modifies it, so there are no changes, so there are no risks;
- its runtime has been end-of-life for years, pinned inside an image that will never be upgraded;
- not one person on the team–including the business paying for it–can say exactly what it does;
- the risk assessment of any change, including a security patch, comes out worse than doing nothing, so nothing is ever done.
The hundreds of billions of lines of COBOL still running the world’s banks are the classic portrait: not that nobody wants to replace them, but they are stable enough that the cost of touching them exceeds everything, and dead enough that they carry nobody’s understanding. That is not a living system. It’s a fossil in the shape of one.
Heat death hands down a counterintuitive verdict, worth setting in large type:
Stability and death coincide in the limit. A system that must never be touched and a dead system are the same system.
“If it works, don’t touch it” is human enough as one engineer’s gasp after a midnight hotfix. As an organizational strategy, it is a prescription for heat death. The heat bath of Section III doesn’t stop moving just because you’ve decided to hold still–choosing not to act is unilaterally starting your system’s countdown. And the countdown doesn’t end in a crash (a crash would at least force work); it ends in losing even the qualification to crash: for a system no one understands, “fix it” has no definition.
In 2017, Equifax paid this section’s tuition on behalf of the whole industry. When the critical Apache Struts vulnerability dropped, Equifax wasn’t refusing to patch–it spent months unable to locate which of its systems carried the component. In the end, the data of 147 million people leaked. The detail of the post-mortem that stung engineering most wasn’t “they lacked a patch”; it was “their inventory of assets and dependencies was incomplete.” The dependency inventory is the system’s catalog of states–and a system without its catalog is in the early stage of heat death: it needs archaeology even to answer “where am I?” Four years later, log4j replayed the same plot at tens of thousands of companies.
Set this against the criticality signals of Section VI and you’ll see they’re two graduations of the same instrument: the phase transition is the doorway you pass through on the way to heat death. A system past the doorway that keeps receiving energy becomes a fossil; a system still short of the doorway is merely lukewarm water. In between lies the window where engineering still works.
VIII. The Entropy Ledger in the Age of AI
At this point the framework owes an answer to a 2026 question: now that AI writes code at scale, has the entropy ledger changed?
It has–at the root. In the language of Section II, one sentence says it:
Generation expands $W$ (the state count). Verification compresses $W$. AI has made generation nearly free–which makes verification the only hard currency left.
Generating ten candidates in one pass, stacking up thousands of runnable lines in an afternoon–seen through the lens of entropy, this isn’t producing order. It’s mass-producing unconstrained states. Every line of unreviewed AI code is one more expansion of the system’s state count. It might be correct, and “might be correct” precisely means “still in superposition.” Who collapses the superposition into the one determined state? Verification energy: tests, review, types, runtime probes. Section V’s verdict applies unchanged: entropy can only be moved, never destroyed. AI did not eliminate the work of getting code right; it relocated that work from writing to proving.
The empirical data is already arriving. GitClear’s year-over-year analysis of more than two hundred million lines of code found that since AI adoption took off, code churn (the share of code rewritten within weeks) has risen markedly; copy-pasted duplicate blocks have multiplied severalfold in a few years; and “moved/refactored code” fell below “copy-pasted code” for the first time on record. In this article’s language: the industry’s average rate of entropy production has gone up. Another darkly comic neologism is slopsquatting: research found that a substantial share of generated code references packages that do not exist, and attackers have begun registering those hallucinated names, waiting for the copy-pasters. A hallucinated package is pure state count–it doesn’t even exist, and it’s already expanding your dependency tree.
But let’s be fair. Read the same physics in reverse and it becomes an opportunity:
- Cheap generation means the cost structure of trial and error has changed. Search-style development–generate ten, verify, keep one–is economically viable for the first time, provided the verification infrastructure keeps up. For teams with abundant verification energy, AI is a negentropy pump: test generation, dependency analysis, large-scale mechanical refactoring (Section IV’s Google-style automated refactoring is becoming generally available), and comprehension assistance for old code (partially migrating Section V’s third destination–the tacit knowledge in skulls–into documentation).
- For teams short on verification energy, AI is an entropy injector: the state count explodes, nobody collapses it, and churn and duplication do the bookkeeping.
So the thermodynamic criterion for the AI era is disarmingly simple: can the throughput of your tests, reviews, types, and CI keep up with the throughput of your code generation? If yes, you’re using AI to pump out entropy. If no, you’re using AI to accelerate heat death. The entropy ledger of generation and verification always balances.
IX. The Negentropy Engineering Checklist: Turning Physics into SOP
Physics done; now the checklist. Each item corresponds to a law from the sections above.
1. Define the maintenance budget as a basal metabolic rate, not as savings. A fixed share of engineering time each cycle–say 10–20%–goes to entropy-reducing work: dependency upgrades, refactoring, test debt, documentation. Its nature is breathing, not repayment. Below the basal rate, the system enters decomposition, and hysteresis (Section VI) delays the visible damage by months.
2. Module boundaries are entropy barriers. The function of a clean module/API boundary is to confine disorder where it started: when one module rots, the boundary keeps the rot from propagating globally. Run Section V’s Windows shim insight in reverse: rather than fantasize about a world without entropy, design isolation chambers and spillways for it. Microservices are not the only form; a well-bounded modular monolith is fully equivalent. What matters is ownership and contracts, not deployment topology.
3. Tests are entropy exported outside the system. Every test is one stored sentence of “the system must behave like this.” Tests are not a quality department’s ritual; they are the codebase’s external memory–collapsing the constraints in your head into executable assertions, making deletion cheap (Landauer’s bill, Section V). AI-generated code with poor test coverage is code that never intended to pay the bill at all.
4. ADRs and commit messages are bills paid to Landauer. Architecture decision records store “why it was like this back then”; good commit messages store “why it is like this now.” They save the you of three months from reinventing history. A change whose “why” cannot be written down is itself a warning sign.
5. CI is a metabolic system, not a bouncer. CI’s thermodynamic role is to keep the system continuously doing work: every commit verifies global state and exports entropy. It must be impossible to bypass–a commit that skips CI is a power cut to the dissipative structure.
6. Dependency governance is interface management with the heat bath. The SBOM (software bill of materials) is precisely the “catalog of states” missing in Sections III and VII–the thing Equifax lacked. Lockfiles, scheduled automated upgrades (Dependabot/Renovate), and checks on dependency age and maintainer health are the institutional answer to Section III’s table. Upgrading proactively is buying order at retail; rotting passively is borrowing at loan-shark rates.
7. Run a bus factor audit once a year (inventorying Section V’s third destination). For each critical subsystem, ask: how much of the necessary knowledge exists only inside skulls? More than one skull’s worth? Export it–into structure (refactoring) or storage (docs, tests).
8. Watch the long-term trend of entropy indicators, not their absolute values. Absolute values are meaningless (every complex system has entropy); the trend is the health check on your metabolism:
| Indicator | Approximate entropy meaning | How to watch it |
| Code churn rate | Short-term rewriting: direction unsettled / understanding incomplete | git log statistics |
| Duplicated-block trend | Structure abandoned; states copied wholesale | jscpd / SonarQube |
| Change failure rate, rollback rate | The system’s “surprise” at being changed | DORA metrics |
| Radius of change (modules touched per requirement) | Entanglement; a signal of Section VI’s critical point | code archaeology / review records |
| Onboarding indicators | A proxy for the externalized-storage gap | HR data |
| SBOM completeness | Self-knowledge of the system’s state count | syft and friends |
X. An Honest Disclosure: Where the Analogy Breaks
As promised at the start, this section exists to saw off the branch I’m sitting on. A physicist reading this far is probably frowning, and their objections are mostly valid:
1. Software has no temperature, and you cannot compute a Boltzmann constant. The $k$ in $S = k\ln W$ has an exact physical value; software “states” depend on the abstraction level you choose–from bits, from functions, from services, $W$ is three different numbers. That’s why this article has only ever reasoned qualitatively, never quantitatively (and it can’t). Anyone claiming to have computed “the entropy of a codebase” is selling pseudoscience.
2. “Energy” here isn’t conserved. Physical energy is strictly conserved; engineering “energy” is attention and hours–scarce, costly, and impossible to bank (Section IV’s argument is built precisely on that deviation, a convenient one, but a deviation is a deviation). It also gets tired, resigns, and gets crowded out by next quarter’s OKRs. Physical energy has none of these problems.
3. Not all complexity is entropy. Brooks’s distinction in “No Silver Bullet” must be inherited: essential complexity belongs to the problem domain (tax law is just complicated; that’s not your code’s fault), while accidental complexity is the disorder we manufacture ourselves. The Section IX checklist should ever only act on the latter. Treating essential complexity as entropy and “refactoring” it is the most common wrong turn in negentropy engineering.
4. Physical irreversibility is, in software, “recovery is expensive.” Molecules don’t get second chances; code can be rewritten–at the price of time and knowledge (Section VI’s Netscape). Calling software change “irreversible” strictly means “irreversible economically.” Because recovery does cost money, the analogy still works for decisions–just at a discount.
5. The biggest risk is the framework itself being abused. “Entropy” carries a built-in aroma of profundity and readily degrades into an all-purpose rhetorical device–rejecting any new requirement with “that would increase entropy,” explaining any failure with “insufficient metabolism.” A metaphor that explains everything explains nothing. This article spent ten thousand words building the framework in order to nail it to three checkable claims: state counting (the number of ways to deviate from intent is real and observable), irreversibility (some losses can’t be bought back, or only at prices that might as well be impossible), and open systems (you cannot freeze the world). Any use of “entropy” that doesn’t route through one of those three is rhetoric.
Conclusion: A Physical Definition of the Engineer
In 1944, in What Is Life?, Schrödinger wrote his famous verdict: life feeds on negative entropy. An organism maintains its internal order not by violating the second law, but by continuously soaking up order from the environment and discharging disorder–life is a small patch of the universe swimming upstream. (Honesty compels the footnote that Schrödinger later amended himself: the more careful phrasing is “life feeds on free energy.” The correction doesn’t affect this article; if anything it helps–even physicists patch their own analogies.)
Compress this long article into one sentence–a thermodynamic definition of the engineering profession:
An engineer is an information structure that continuously injects negentropy into a system to keep it far from thermodynamic equilibrium.
Every line of code you write will expire; every architecture you design will decay. This is not your failure; it is the second law, no more worth despairing over than cold coffee. The real dividing line runs elsewhere: do you pretend order is a stock (“once we finish this, it’s done forever”), or do you admit order is a flow (“what does this system breathe with?”)?
Software is not an artifact. It is a process. It resembles a flame, not a sculpture.
You are not building it; you are continuously lighting it. The day you let go is not the day it’s finished. It’s the day it starts going out.
One last word, for the individual. Section V said the engineer is Maxwell’s demon–but the demon is not a perpetual motion machine. The demon’s entropy-lowering runs on information, and information is forgotten; the demon’s work runs on energy, and energy runs out. So sustainable negentropy engineering must never be built on “some hero who never clocks out.” It must be built on the plain mechanisms of Section IX: let structure remember for you, let tests constrain for you, let process breathe for you. A good engineer does not write code that never rots–nothing does. A good engineer writes code that rots slowest, most predictably, and most repairably–together with a mechanism that metabolizes on its own.
This is not fatalism. It’s the opposite: the person who sees clearly that water runs downhill is the person who knows where to install the pump.
Appendix A: Bit Rot Trigger Quick Reference
| Trigger | Mechanism | Representative cases | Countermeasure |
| Certificates & chains of trust | Root expiry / re-signing breaks old endpoints | AddTrust expiry (2020), Let’s Encrypt cross-sign expiry (2021) | Certificate monitoring; test rotations in advance |
| Protocol deprecation | Platforms disable old protocols | TLS 1.0/1.1 disabled (2020) | Include protocol coverage in dependency scans |
| Dependency supply failure | Upstream package disappears / renames | left-pad (2016) | Lockfiles; private mirrors / proxy registries |
| Maintainer loss | The energy flow stops | event-stream (2018), faker.js (2022) | Dependency health checks (maintainer count, release cadence) |
| Time | Epoch and field overflows | Y2K; Y2038 (2038-01-19) | 64-bit time_t audits |
| Platform policy | API shutdowns; auth changes | YouTube API v2 (2014); GitHub password auth removal (2021); Flash EOL (2020) | Subscribe to upstream deprecation notices |
| Runtime evolution | Language / runtime EOL | Python 2 EOL (2020) | Upgrading is metabolism, not a project |
Appendix B: The System’s Entropy Checkup (30 Minutes, Twice a Year)
- Pull the trends (10 min): churn rate, duplicate blocks, change failure rate, radius of change–look for inflection points, not absolute values.
- Count the inventory (10 min): Is the SBOM complete? How many EOL dependencies? How many direct dependencies with no maintainers?
- Count the heads (5 min): What’s the bus factor of each critical subsystem? What knowledge lives in exactly one skull?
- Check the signals (5 min): Walk Section VI’s criticality list. Three or more hits means incremental refactoring is no longer sufficient–start evaluating a strangler-pattern program. Don’t wait for the sixth.
Appendix C: Three Iron Laws
- Entropy can be moved, never destroyed–before every “cleanup,” ask: where does the complexity go? Into structure, into storage, or into skulls?
- Order is a flow, not a stock–the maintenance budget is a basal metabolic rate; every dollar saved below it pre-pays for a phase transition.
- You cannot freeze the world–“just leave it alone for now” doesn’t preserve order; it hands the system’s fate to a heat bath that never stops moving.

Leave a Reply