Separate services, independent deployments, per-component scaling, queues, events, and observability make microservices look ready for growth. Sometimes they are. They can also turn one simple system into several systems that are hard to maintain before there is a problem worth solving that way. A more distributed architecture isn't automatically a better architecture.
Splitting things has a cost
When an application lives inside a single project, a lot of operations are direct. One function calls another. A transaction updates several pieces of data. An error can be traced within the same process.
Splitting services introduces new boundaries: network calls, inter-service authentication, contract versions, partial failures, retries, synchronization, and distributed logs.
Independent deploys. All of that can be necessary. But it isn't free.
The monolith isn't the enemy
"Monolith" is often used as shorthand for old, hard-to-maintain software, but a monolithic application can be well organized, with clear modules, separated responsibilities, good tests, well-defined internal interfaces, and a simple deployment. For many products, especially in their early stages, that structure lets the team move faster without closing the door on splitting components later. The problem isn't that everything lives in the same repository or process. The problem is that everything depends on everything.
There's a difference between modular and distributed
A lot of the time, what a project needs isn't microservices. It needs better boundaries. Billing can be a module. Inventory can be another.
Users can be a third module. Each can have clear responsibilities without immediately becoming a separate application with its own infrastructure. That keeps the architecture understandable and prepares the system for a future split if one part genuinely needs it: separate the concepts first.
Then, if needed, separate processes.
When does it start making sense?
There are cases where splitting a system solves real problems. A component needs to scale very differently from the rest. Different teams work on independent areas and need to deploy without blocking each other. Part of the system needs a different technology for a concrete reason.
A heavy process needs to run in isolation. There are availability or security requirements that justify a strong separation. That's where the added complexity can pay for itself. The difference is that there's a concrete problem being solved.
Not just an architecture we want to use.
Scaling users doesn't always mean scaling architecture
It's easy to think: "if this grows, we need microservices." But a well-built monolith can handle a huge amount of traffic. Before splitting it, it's worth checking much less exotic problems first.
More common bottlenecks include slow queries, missing indexes, unnecessary work on every request, poorly served files, jobs that should run in the background, missing caches, and undersized servers. A single application is often not the limiting factor.
It's what that application is doing.
The database tends to give away the fake split
There are systems presented as microservices where everything reads and writes directly to the same tables. That keeps most of the original coupling and adds network communication on top. If a service can't change without knowing another one's internal structure, the split is probably more visual than real.
Splitting code is easy. Splitting responsibilities and data is a lot harder.
Consistency changes too
Inside a single application and database, we can run several operations within one transaction. Either everything goes through, or nothing gets saved. In distributed systems, that guarantee can disappear. One service updates correctly.
Another fails. A third one hasn't received the event yet. Now the system can be temporarily in different states depending on where you look. That doesn't mean something's wrong.
It means the architecture has to be built to live with that reality. And that adds work.
Partial failures are normal
If an application depends on five services and one stops responding, what happens? Does everything stop working? Does only one feature get disabled? Do we save the operation to try again later?
Do we show incomplete information? In a distributed system, there isn't just "the application is working" or "the application is down." Some parts can be working and others not. Designing for those states is part of the architecture.
You also have to be able to operate the system
The more components there are, the more important it becomes to understand their state through centralized logs, metrics, traces, alerts, deployed versions, queue status, and health checks.
Without that level of observability, investigating an error can turn into jumping between servers trying to reconstruct a request's path. An architecture that scales technically but that nobody can diagnose isn't ready to grow.
Organization matters too
Sometimes microservices show up because they work well at companies with hundreds of developers. But a large company's architecture also reflects its human structure. Many teams need independence. A three-person team has a different problem.
If the same two people have to maintain twelve services, pipelines, repositories, and databases, that independence starts becoming fictional. The architecture should consider who's going to operate it, not just what it can technically do.
Starting simple doesn't mean improvising
Choosing a simpler architecture doesn't mean putting everything anywhere. From the start, the team can separate domains and avoid unnecessary dependencies.
Use queues where they actually add value. Design clear internal contracts. Prepare components so they can be extracted later. The difference is not paying today for complexity you might need in three years.
The architecture has to justify its pieces
Microservices are a tool. So is a monolith. So is serverless. So is a queue. So is a function that runs from cron. The important question isn't which one looks more modern. It's what problem each piece solves and what cost it adds. If we can't answer that, we're probably designing for a scale that doesn't exist yet.
The right architecture is the one that can justify every piece. The same criterion applies when deciding whether WordPress still fits the product: choose for the problem, not for the tool.