Code is cheap. Decisions aren't.
Code used to be the expensive part. It isn’t anymore - I produce more code in a day than I used to in a week. Decisions are - what to add, what to leave out, when to stop, when the thing is done instead of just bigger.
Most of this I learned by getting it wrong first.
What changed
When code was expensive, every line had to justify itself. The friction of producing it was doing a lot of design work for free.
That friction is gone. An LLM will scaffold the abstraction in two seconds. It will add the wrapper, suggest a generic where you had a concrete, add a config option for the case you mentioned offhand. None of these moves cost anything anymore. So none of them get the design pause they used to.
It’s easier to add than to think. The cost of typing the thing is gone. The cost of deciding whether it should exist didn’t go anywhere - it just stopped getting paid.
Small wrong decisions don’t stay small
You add a thin wrapper around a library. Just one - to make testing easier, or to swap implementations later, or because the API is slightly awkward. A month later there’s a wrapper around the wrapper. Six wrappers in, the bottom of the stack is unreachable. Nobody calls the library directly. The original reason for the first wrapper is gone, and nobody knows it.
You add a nullable column for one edge case. Just that one case - fine. Now every read site handles null. Months pass. New code assumes the field can be null. To make it required, you write a migration to narrow down the nulls - and you can’t write it until you’ve decided what to fill them with and found everything still putting nulls in.
Each of these, on its own, is easy to live with. That’s the problem. They’re everywhere - like needles on a Christmas tree, none of them weighing anything, but the tree is full of them, and at some point you can’t move it without losing half on the floor. Speed degrades. Dev speed degrades. Robustness degrades. Not because of any one decision. Because of the texture of all of them.
The new kind of legacy
Now imagine you’re new to a project. You open the codebase and everything is clean. Layers separated. Tests at every level. Logging structured. You can’t find anything to fault.
The old advice - when you inherit a project, look for the bad code and fix it - doesn’t help here. There is no bad code. Every individual file is a textbook example. The thing you have to learn to see is harder: the fit between the code and the problem it’s supposed to be solving. And here, there isn’t one. Most of this code doesn’t need to exist. The whole architecture is solving problems the system doesn’t have.
You used to need to recognize bad code. Now you also need to recognize too good code - every piece correct in isolation, the whole thing wildly oversized for what it does. The right move isn’t a refactor toward better practices. It’s a refactor toward a worse, simpler solution that actually fits. That’s a much harder reflex to develop, and it cuts directly against everything a “good engineer” gets praised for.
What’s actually expensive
The work is holding the whole requirement in your head while you build. Not the part you’re touching this hour - all of it. What does the system actually need to do? What does it not need to do? Where does 0.99 matter and where is 0.7 fine? What’s the smallest thing that could answer the actual question?
Most of the discipline is not adding. Saying no to the wrapper. Saying no to the service. Saying no to the optional field, the flag, the hook, the abstraction “for later.” Asking, every time something wants to be added: does this pay rent? If not, leave it out.
The cost
This is slower. It’s lonelier. There are fewer screenshots. Your peers will write more impressive PRs. The agent will keep suggesting the bigger move and you’ll keep declining. The reward, when you get it, is a system that’s small and fast, that does what it was supposed to do, and that you can still understand a year from now.
Code is cheap. Decisions aren’t. The expensive part now may be in the things you don’t build.