The Cost of Complexity
The hardest thing in software is knowing what to leave out.
Every system starts simple. Then requirements arrive, edge cases appear, stakeholders ask for features, and before long you have something that technically works but that no one fully understands - including the people who built it.
Complexity accumulates silently
The insidious thing about complexity is that it rarely arrives all at once. It accrues in small decisions: an extra parameter here, a conditional branch there, a configuration flag that “might be useful someday”. Each addition seems harmless in isolation. The sum is what kills you.
This is even more dangerous in the age of generative AI. Vibe-coding - letting an LLM generate code while you steer from the passenger seat - is intoxicating. You move fast. Features appear. But if you don’t understand what’s under the hood, you’re not building. You’re accumulating. And the moment something breaks, you’re lost in a codebase you never actually wrote.
Speed without understanding is just debt with a delayed invoice.
A rule I use
Before adding anything - a function, a config option, a UI element - I ask: what breaks if this doesn’t exist? If the answer is “nothing right now”, I don’t add it.
This sounds obvious. It’s surprisingly hard to practice when you’re in the middle of building something and your brain is generating ideas faster than your hands can type. It’s even harder when an AI is generating those ideas for you.
The minimalist tooling aesthetic
I find this same principle in the tools I admire. The ones that last are the ones that have the courage to be incomplete - that would rather do one thing well than five things adequately.
That’s what I’m trying to build. Piece by piece.
— Adrian