Wirth's Law: Why Software Gets Slower as Hardware Gets Faster
Table of contents
You bought the faster machine. Twice the cores, four times the memory, a disk that reads a hundred times quicker than the one it replaced. And the thing you use every day, the editor or the chat app or the internal tool, opens in about the same time it did three years ago. Maybe slower. The hardware underneath it got dramatically better, and the experience on top of it stood still. You are not imagining it, and you did nothing wrong. You just watched a decades-old rule play out in real time: the speed the new hardware gave you was spent before you ever saw it, on software that grew to fill the room the hardware cleared.
That rule has a name, and naming it changes how you read every "we just need a bigger instance" conversation. Wirth's law is the observation that software gets slower more rapidly than hardware gets faster, so the net experience of using a computer barely improves no matter how much faster the chips get. It is not a law of physics. It is a law of incentives: adding is easy and rewarded, trimming is hard and invisible, so software expands to consume whatever headroom it is given. Here is what Wirth's law actually says, why the hardware gains keep disappearing, and the specific practices that let a team keep its software lean instead of quietly spending every upgrade its users pay for.
What is Wirth's law?
Wirth's law is an adage on computer performance which states that software is getting slower more rapidly than hardware is becoming faster. Named after the Swiss computer scientist Niklaus Wirth, who stated it in his 1995 article "A Plea for Lean Software", it is the pessimistic counterpart to Moore's law: hardware roughly doubles in capability every couple of years, and software finds a way to more than spend that gain.
The mechanism is not mysterious. Every generation of hardware hands developers a budget of extra cycles, memory, and bandwidth. That budget gets spent almost immediately, on higher-level abstractions, more layers of framework, richer graphics, more features running at once, and less pressure to optimize because "the machine is fast enough now." None of those choices is wrong on its own. Each buys something real: faster development, richer functionality, code that is easier to write. The sum is a piece of software that needs a machine three times faster than its predecessor to feel exactly the same. Wirth's law is what you get when a thousand reasonable trades of performance for convenience land on the same product, and nobody is measuring the total.
It helps to separate Wirth's law from the two things it is easily confused with. It is not the claim that hardware has stopped improving, which is a separate debate about the end of Moore's law. And it is not the claim that all software is badly written, which misses the point. Wirth's law describes an equilibrium, not a failure: given cheap performance and expensive discipline, software will always drift toward using all the performance available. The interesting question is never "why is this app slow," it is "what did we buy with the speed we spent, and did we mean to buy it."
Why the hardware gains keep disappearing
If faster hardware reliably produced a faster experience, Wirth's law would not hold. It holds because the pressure runs almost entirely one way. Every force in a normal software organization pushes toward using more resources, and very few push back. Naming the sources is the first step to resisting them.
| Where the slowdown comes from | Why nobody stops it |
|---|---|
| Layers of abstraction stacked for developer convenience | Each layer is individually justified; the tax is only visible when you count all of them together |
| Frameworks and dependencies pulled in for one feature | The whole library ships even when you use one function of it, and the cost is deferred to load time, not build time |
| Features that all run at once | Every feature has a champion; the aggregate startup cost has none |
| "The machine is fast enough" as a default | Optimization is invisible work with no demo, so it loses every prioritization meeting to a visible feature |
| Data structures and defaults chosen for the easy case | The slow path only shows up at scale, long after the choice was cheap to change |
| Performance treated as a late-stage fix | By the time anyone measures, the slowness is spread across a hundred decisions and nobody owns it |
Notice the shape every row shares. The reason to add is loud, immediate, and attached to a person who wants it. The reason to stay lean is quiet, deferred, and attached to nobody. That is the same asymmetry behind feature creep, and Wirth's law is in large part feature creep measured in milliseconds: a product bloats in scope and, at the same time, in the resources it demands, because the two grow from the same soil. It is also what makes the second-system effect so expensive, where a confident rewrite balloons in both features and footprint at once. Judge any single "let's add this" decision on its first-order effect and you will approve it every time; the cost lives in the second- and third-order effects that only the person watching the whole system can see.
Want the reasoning behind your performance decisions to still be there when the slowness finally shows up? Try Scribelet free and keep the "why we chose this" note attached to the choice.
Wirth's law examples
The law is easiest to recognize in software you already use. The pattern repeats across every category, and in each case the individual decisions were defensible.
| Situation | What Wirth's law produced |
|---|---|
| A text editor rewritten on a web runtime | Gigabytes of memory to edit a file that a native editor opened instantly in a fraction of the RAM |
| A chat app that loads a full browser engine per window | Startup and memory costs that dwarf the actual job of showing text messages |
| An operating system that adds effects and services each release | Boot times and idle resource use that climb even as the hardware underneath gets faster |
| A website that ships a megabyte of JavaScript to render an article | A page that is slower to read on a modern phone than a plain document was a decade ago |
| An internal tool that stacks one framework on another | A dashboard that needs a bigger cloud instance every year to do the same work for the same number of users |
The common thread is that no single team set out to build a slow product. Each reached for the abstraction, the runtime, or the dependency that made their own job easier, and every one of those choices was reasonable at the desk where it was made. The slowness is an emergent property of the sum, which is exactly why the person approving any one piece of it rarely sees it coming. Read one commit and it looks fine. Profile the whole thing and the hardware budget is gone.
Wirth's law and its neighbors
Wirth's law travels with a small family of adages about growth consuming its own headroom, and holding them side by side sharpens what each one actually claims. The definitional pages will tell you Wirth's law exists; what they rarely give you is the map of when to reach for which.
| Law | What it says | The angle it adds |
|---|---|---|
| Wirth's law | Software slows down faster than hardware speeds up | Performance is spent as fast as it is granted |
| Moore's law | Hardware capability roughly doubles every two years | The supply of performance Wirth's law spends |
| Andy and Bill's law | "What Andy giveth, Bill taketh away" | The industry version: new software consumes each hardware gain |
| Parkinson's law | Work expands to fill the time available | The general form: any resource is consumed to its limit |
| Gates's law | Software speed halves every 18 months | The blunt restatement of Wirth's law as a rate |
| Gall's law | Complex systems evolve from simple ones that worked | Why the lean version has to come first |
The row that matters most is the pairing of Wirth's law with Moore's law. Moore's law is the reason the budget exists; Wirth's law is the reason you never see it. Treating them as a single system, supply and spend, is what turns "the app is slow" from a complaint into a question you can act on: not "how do we get more performance," but "where did the performance we already have go, and did we mean to spend it there."
How to hold the line against Wirth's law
Wirth's law is not a sentence you have to serve. It is an equilibrium, and equilibria move when you change the forces. The goal is not to optimize everything, which is its own trap, but to make the cost of resources visible at the moment decisions are made, so that the quiet side of the trade finally has a voice. A few practices do most of the work.
- Set a performance budget and treat it like the feature budget. A hard number for startup time, memory footprint, or bundle size turns "the machine is fast enough" into a line you can point at. A budget breach becomes a bug, not a shrug.
- Measure the total, not the increment. Every feature looks cheap in isolation. Profile the whole product on the hardware your users actually have, on a schedule, so the aggregate cost shows up before it calcifies.
- Make adding a dependency a real decision. Write down what a framework or library buys and what it costs at load time. The point is not to refuse dependencies but to stop pulling in a megabyte for a one-line function without anyone noticing.
- Start with the thin version. A walking skeleton that runs end to end on modest hardware sets a baseline you can defend; it is far easier to keep a lean thing lean than to slim a bloated one.
- Write down the non-goals. A technical spec with an explicit "what this is not for" section is the single cheapest counterweight to bloat, because it lets you decline the reasonable-sounding addition without relitigating it every time.
- Record why a performance choice was made. The data structure that looks wasteful, the cache that looks redundant, the abstraction you deliberately did not add: each is a decision whose reason lives outside the code. Capture it the way good code documents the why rather than the what, so the next person does not "simplify" your speed away.
None of these is exotic. What they share is that they move the cost of a resource from invisible-and-deferred to visible-and-now, which is the only thing that ever changes the equilibrium Wirth's law describes.
The curve is the whole argument. The hardware line climbs the way Moore's law promises, and the line the user actually feels barely lifts off the floor, because the gap between them is filled in with abstraction, features, and dependencies that arrived one reasonable decision at a time. Closing that gap is never a single heroic optimization. It is a hundred small refusals, made possible by measuring the total and writing down what you chose not to add.
The reason the gap keeps reopening
Even a team that fights bloat well tends to lose the ground back, and the reason is worth naming because it is fixable. The judgment that keeps software lean, the knowledge of why a given abstraction was refused, why a dependency was kept out, why a data structure that looks wasteful is actually load-bearing, lives almost entirely in people's heads and in decisions nobody wrote down. When those people move on, the reasons go with them. The next engineer sees only a codebase that looks like it could be "cleaned up" or "modernized," reaches for the convenient framework the original team deliberately avoided, and the gap Wirth's law names quietly reopens.
This is knowledge decay hitting performance discipline at the worst possible moment. The countermeasures above only hold if the reasoning behind them stays attached to the code, and by default it does not: it rots in a Slack thread, a closed ticket, or a memory that has moved to another company. A performance budget with no record of why the numbers were chosen is a rule the next team will "temporarily" relax and never restore.
This is the problem Scribelet is built for. Its background agents re-check your notes and decision records against reality on a schedule and surface a diff when something no longer holds, so the reason a dependency was refused or a budget was set stays attached to the decision instead of evaporating the moment the person who made it leaves. Your keys, your model, your data: the agents run on the provider you choose, and you see exactly what changed and why. Keeping the why of a lean system alive is what stops the next well-meaning rewrite from spending, all over again, the performance the last team fought to save. Try Scribelet free and keep the reasoning behind your fast software from decaying into a codebase that just looks slow for no reason anyone remembers.
When Wirth's law is the wrong tool
Wirth's law is a lens, not a verdict, and it can be misused. It is not an argument that all abstraction is waste, that every framework is bloat, or that software should be written in assembly to honor the machine. Those abstractions bought real things: safety, portability, development speed, the ability to ship at all. A team that hears "Wirth's law" and responds by hand-optimizing everything has traded one failure for another, spending scarce engineering time chasing microseconds users will never feel while the actual product stalls.
The law also does not mean hardware upgrades are pointless. Sometimes the extra headroom genuinely unlocks something new, a capability that was impossible before, not just the same job done heavier. The discipline Wirth's law asks for is not asceticism. It is honesty: know what you are spending your performance on, make that cost visible at the moment you spend it, and decide on purpose rather than by default. The teams that keep their software fast are not the ones that refuse every abstraction. They are the ones that never let the price of one slip below the waterline where nobody has to answer for it.
Wirth's law is a reminder that performance is a resource like any other, consumed to its limit unless something holds the line. The line is not faster hardware. It is a team that measures the whole, writes down what it chose not to build, and keeps the reasons alive long enough to matter.
Share this article