The Complexity Fetish: Why Are We Overengineering the Simple?

4 months ago 20

Junior Rodrigues

Why the hell do we need a bunch of plugins, abstractions, dependencies, frameworks, and configuration just to build and scale a super simple feature?

Nowadays, writing a line of code feels like the final step in a sacred ritual: before that, you have to choose the framework, configure the environment, understand the latest architectural pattern, follow three best-practice checklists, and of course, install half a dozen libraries no one remembers why we use.

Most developers start out being bombarded with design patterns, engineering principles, fancy acronyms, and a mountain of concepts promising “clean” and “scalable” code. But are we really writing better software — or just making the simple more complex?

At big companies, architecture has become an end in itself. What should be a solution often turns into the problem: layers upon layers of abstraction that increase maintenance costs and learning curves. I’ve seen microservices being used just to return a simple “OK”. And then we ask ourselves: are we solving real problems or just stacking tech to look smart?

The Cult of Complexity

There’s a certain fetish for complexity in our field. The harder the code is to understand, the more “mature” it feels. I’ve even heard people say “if it’s too simple, something’s wrong.” The problem is: complexity has a cost — and it’s usually paid by whoever has to maintain it.

Architecture becomes a goal in itself instead of a means to an end. Need to add logging? Let’s create a middleware that calls a library, which emits an event, that goes through a broker, reaches a handler, and finally logs the message. All that to do what a `console.log` could have done in one line.

When Abstraction Becomes a Trap

Abstractions are important, of course. They help us hide unnecessary details and enable code reuse. But abstraction for the sake of it — built in advance without real need — is a trap.

You add more and more layers because “you might need it someday.” You create interfaces, adapters, wrappers… all before knowing if the code will even change. The result: no one knows where the logic actually is. And when something breaks, you dig through five files just to find the real error.

I’ve seen classes named `FactoryManagerAdapterService` that did nothing but call another class with a similar name. It’s almost as if the goal was to confuse.

The Dependency Addiction

Sometimes it feels like developers forgot how to write plain code. Anything becomes an excuse to install a library: need to format a date? Install one. Make a simple request? Wrap Axios with another lib. Sort an array? There’s a package for that too.

Every new dependency is another opportunity for something to break — and you don’t even control it. And when that lib vanishes from NPM? Or releases a new version full of breaking changes? Then comes the chaos: obscure errors, version conflicts, and hours wasted “upgrading” something that never needed to exist in the first place.

Not All Complexity Is Bad

This isn’t a manifesto against architecture, patterns, or good practices — and definitely not against modern tools. The truth is: complexity happens in big systems, and it must be handled carefully.

But complexity should come *from the problem*, not *from the solution*. It should be a response, not a requirement. Scaling a well-written monolith is often easier (and cheaper) than maintaining a poorly thought-out mesh of microservices.

If your system is growing, you’ll need structure — just don’t start with layered architecture, full DDD, CQRS, and Kafka just to handle a basic CRUD.

How to Avoid Overengineering?

A few simple attitudes go a long way:

- Start simple. Always.
- Solve today’s problem. Worry about tomorrow’s when it arrives.
- Write code you’ll understand three months from now.
- Avoid unnecessary dependencies. If you can solve it in 10 lines, do it yourself.
- Architecture matters — but only when the context demands it.

Less Ego, More Solutions

Software engineering isn’t about showing off how much you know. It’s about solving real problems in the best, most sustainable way possible. And more often than not, the best solution is the simplest one.

If you can solve it with less, why make it more?

Read Entire Article