Complexity in software often feels like a technical problem.
But most of the time, it’s emotional.
Fear of change.
Fear of missing out.
Fear of not being “right”.
These fears create complexity that has nothing to do with the actual requirements.
The architecture of anxiety
I’ve seen systems that look like this:
- Microservices for every CRUD operation
- Three layers of abstraction before you hit the database
- Event buses for internal team communication
- Feature flags for features that will never be used
- Multiple authentication systems “just in case”
Each piece made sense in isolation.
Together, they created a system that was impossible to reason about.
The minimalist baseline
I’m not saying “never use microservices” or “never abstract”.
I’m saying: start with the simplest thing that could possibly work.
For most applications, that looks like:
- Monolith (at least initially)
- Clear separation of concerns, not layers of indirection
- Direct database access (or simple ORM)
- Events only when there’s actual distributed work
- One authentication system
This isn’t “old school”.
It’s just honest.
When complexity creeps in
Complexity usually appears in two ways:
1. You add things too early
- “We might need microservices later” → build microservices now
- “What if we have multiple databases?” → add abstraction layers
- “This might scale to millions” → over-engineer for scale that doesn’t exist
2. You avoid difficult decisions
- “I don’t want to choose between framework A and B” → use both
- “This logic is messy” → wrap it in another layer instead of cleaning it
- “I’m not sure about this trade-off” → keep both options open indefinitely
Both patterns create complexity that slows you down.
The emotional root
Most of these decisions come from fear:
- Fear of being wrong
- Fear of making the wrong trade-off
- Fear of not being prepared for the future
- Fear of looking incompetent
These fears don’t make you a better developer.
They make your systems harder to maintain.
How to stay minimalist
1. Ask: “What is true right now?”
Not what might be true in six months.
Not what could be true if things scale.
What is true today?
2. Make decisions with incomplete information
You’ll never have all the information.
That’s not a reason to stop.
It’s a reason to choose the simplest path and iterate.
3. Embrace “good enough”
“Perfect” is the enemy of “shippable”.
“Simple” is the enemy of “over-engineered”.
4. Default to integration, not abstraction
Connect things directly first.
Add abstractions only when there’s a clear need.
5. Be okay with changing your mind
If you made the wrong decision, change it.
That’s not failure.
That’s how you maintain a simple system over time.
The gentle architecture
I’m not looking for the “perfect” architecture.
I’m looking for the gentlest one.
The one that:
- Lets me understand the system in an afternoon
- Lets me change things without rewriting half the codebase
- Lets me sleep at night
- Lets me focus on building features, not managing complexity
That’s not minimalism for its own sake.
That’s minimalism as a strategy for sustainable development.
A more honest baseline
Most projects don’t need complex architecture.
They need:
- Clear boundaries
- Simple decisions
- Courage to say “no” to unnecessary complexity
- Permission to change your mind later
When you build with those principles, your systems become easier to maintain.
And you become a calmer developer.