For the past few years, a lot of developers have been building their applications as if they were going to become the next Netflix.
Separate frontend, REST API, microservices, message queues, websockets, Kubernetes… sometimes right from the MVP stage.
Yet, after talking with other engineers and watching projects unfold, I keep noticing that we often adopt certain architectures way too early.
AI makes implementation so much easier, so we desperately want to set up complex architecture.
Multi-tier typically means separating frontend, backend, and database.
Microservices take this even further by splitting the backend itself into independent services.
Originally, these architectures were designed to solve real problems :
| Monolithic Architecture | Multi-tier Architecture |
|---|---|
| Single application | Multiple separate layers |
| Simple deployment | Independent deployments |
| Low operational complexity | More flexible |
| Rapid development | Better suited for large teams |
| Minimal internal network communication | Communication via API |
| Great DX for small teams | Good separation of concerns |
Multi-tier architectures really shine when:
- multiple clients consume the same data (web, mobile, desktop...)
- multiple teams work in parallel
- you need independent scalability
- you're exposing public APIs
- you're integrating with other services
And in those cases, they're excellent.
But more often than not, our applications don't have these problems yet.
For me, developer experience (DX) is incredibly important.
I like architectures that are simple, readable, quick to maintain, and let me ship fast without turning every feature into a headache.
That's why I believe today that many projects would benefit from staying monolithic longer (or forever).
😇 : a well-designed monolith lets you move fast with minimal complexity
😈 : without strict frontend/backend separation, your project won't scale
By definition, an API lets multiple systems communicate with each other.
But let's be honest: how many personal projects or early-stage SaaS actually have multiple consumers?
More often than not:
- there's only a web frontend
- no mobile app
- no external partners
- no public API need
Yet we immediately add:
- API versioning
- CORS handling
- Distributed authentication
- Duplicated types and validations
- Swagger documentation
- Frontend/backend synchronization
Basically, a lot of complexity for problems that don't exist yet.
And this complexity isn't free.
A network call will always be more complex than a simple function call within a monolith.
With a distributed architecture comes:
- latency
- timeouts
- retries
- synchronization issues
- network errors
When everything is in a single application, a ton of problems simply vanish.
There's also another point we don't talk about much: the attack surface.
Multiplying services, endpoints, gateways, and authentication mechanisms mechanically increases the chances of errors and vulnerabilities.
Sometimes we overcomplicate the security of an application that could have stayed very simple.
My glory stack right now is:
Laravel + Inertia + Vue.
Honestly, I love this trade-off.
With this approach:
- I keep the comfort of a modern JS framework
- validations stay centralized
- CSRF tokens are handled naturally
- routes are protected simply
- I maintain excellent development speed
I don't need to maintain:
- a frontend application
- a backend application
- sometimes a gateway
- multiple CI/CD pipelines
- multiple logging systems
When you're an indie hacker or in a small team, this matters.
The cognitive cost of an architecture is often underestimated.
In a monolith:
- one repo
- one deploy
- one debug session
- one codebase
- one monitoring system
And often... just one person to handle all of it.
I also think we overestimate scalability way too much.
Most projects don't die from a scaling problem.
They die because they couldn't find their users.
Before thinking about Kubernetes, service discovery, and distributed orchestration, you need a product people actually use.
And yet… part of me thinks the exact opposite.
Because in reality, many problems appear precisely when you wait too long before decoupling your system.
A monolith that grows without discipline can become extremely hard to maintain: tight coupling between modules, endless build times, mounting technical debt… Eventually, every change becomes risky.
A separated architecture can then bring clarity. Even when you don't yet need a mobile app or public API, preparing for that possibility early can avoid painful migrations later.
With my glory stack mentioned above, I can easily create an API alongside the monolith in the same codebase.
There's also the human aspect: in a growing team, having separate frontend and backend lets everyone move more independently.
Some backend developers actually prefer working completely decoupled from the frontend to keep their technological freedom and workflows (and saying "it works in Postman" 😂).
Let's not forget that nowadays tons of cloud tools simplify part of this complexity: managed CI/CD, observability, containers, serverless… what was once reserved for large enterprises is becoming progressively accessible to smaller teams.
So ultimately, the problem might not be the architecture itself, but our ability to honestly anticipate the future needs of the project.
Basically: multi-tier architectures are great.
But I think we turn them into default choices too often.
As if a monolith was necessarily bad practice or a "junior" architecture.
When a monolith can be:
- clean
- modular
- maintainable
- highly scalable (Facebook was monolithic at some point💀)
- extremely performant
Monolith doesn't mean spaghetti.
To reconcile my two brain hemispheres, I think we mainly need to analyze the actual project needs before choosing an architecture.
Multi-tier architecture isn't an automatic choice.
Sometimes strong decoupling is totally justified.
But sometimes... you want to kill a mosquito with a M16.