Simplicity is beauty
Simplicity is beauty
“Simplicity is the ultimate sophistication.” — Leonardo da Vinci
In software engineering, people default to complexity. Not because it solves the problem better, but because it looks like it does. The culture rewards the appearance of sophistication. A simple solution feels like you didn’t try hard enough. So you spin up a microfrontend. You build a pipeline. You add a layer of AI on top. And somewhere in that stack, the actual problem quietly stays unsolved.
We don’t have a tooling problem
Most complexity I have seen in teams isn’t a technical failure. It’s a communication failure wearing a technical costume.
Simple miscommunication? Add more Slack channels. People not aligned on a decision? Create a process around it. A task that takes minutes? Delegate it to a massive automation pipeline because it’s “scalable.” We keep building systems to route around the discomfort of just… talking to each other.
We put another layer of AI to hide the fact that we don’t communicate. And then that AI creates more confusion, because the person it’s supposed to inform has no context. It just stacks another layer on top of the original problem, which is still there, untouched. We are not solving anything. We are just making the mess harder to see.
The guilt is real. We know we’re not addressing the root. So we stay busy adding tools that make it look like we are.
The performance of engineering
There is a culture problem underneath this. Sophisticated processes get rewarded. A developer who introduces a new framework gets noticed. The one who deletes code, simplifies the flow, or just writes better documentation? Quiet. Unspectacular. Nobody’s going to talk about that in the standup.
So engineers optimise for visibility. Complexity becomes currency. And teams end up with systems that serve their architects’ careers more than their actual users.
The irony is that restraint is harder. Writing code that a junior can read six months from now is harder than being clever. Saying “we don’t need this” when everyone expects you to build something takes more confidence than building it.
Think in steps, cut aggressively
Here’s a mental model I keep coming back to, loosely inspired by how Elon Musk thinks about manufacturing: treat any system as a sequence of steps. Before you automate, before you optimise, before you add anything — lay out every step in the process and ask what you can remove.
Not trim. Remove. Kill the requirement entirely if it doesn’t justify its existence.
Most of the time, steps survive because nobody questioned them. A microfrontend doesn’t earn its place because it sounds architectural. It earns its place if and only if it makes delivery genuinely better for the team doing the work. If it doesn’t, it’s just theatre.
The same logic applies to communication tools, automation pipelines, observability layers, and everything else we reach for by default. Every addition is a bet that the cost of maintaining it is worth what it gives back. Most of the time, that bet loses.
It’s okay to be boring
It’s okay to write a terminal script instead of spinning up a cloud workflow. It’s okay to re-read the documentation instead of building an abstraction over it. It’s okay if the code is longer when it brings clarity. It’s okay to write documentation if it saves people from jumping into chat every time. It’s okay to ask the question again.
The old ways gave us clarity. Whole businesses run on boring mechanisms that have been quietly serving their purpose for decades, and those are the building blocks of everything we rely on today.
Simplicity is not a lack of ambition. It is the discipline to focus on what actually matters. In a world of abundance, that focus is expensive. It requires resisting the pull toward sophistication, resisting the culture that rewards the performance of complexity, and resisting your own instinct to look like you’re doing more than you are.
Practice removing. Add back only when you feel real pain. Most of the time, you won’t.