Every few years, the industry consensus swings. Monoliths are bad. Microservices are good. Then the pendulum reverses. Amazon writes a blog post about consolidating to fewer services. Suddenly monoliths are back.
The honest answer is that neither is universally better. The question is: what is right for your team, your scale, and your pace of change?
What the words mean
A monolith is one application, deployed as a single unit, usually with one database. Microservices split the system into small services that are developed, deployed and scaled separately and talk to each other over the network.
Start with a monolith when
Start with a monolith if your team is small, your domain is not fully understood, and you are still finding product-market fit. A well-structured monolith is fast to build, easy to reason about, and far simpler to debug. You can always extract services later.
A monolith also lets you change your mind cheaply. Moving a boundary inside one codebase is a refactor. Moving it between two services is a migration.
Move toward services when
Move toward services when you have clear bounded contexts, different scaling requirements across subsystems, multiple teams that need to deploy independently, and the operational maturity to manage distributed systems.
Notice that most of those reasons are about people, not technology. Microservices mainly solve an organisational problem: many teams stepping on each other in one codebase.
What microservices really cost
The mistake is jumping to microservices prematurely because they feel more serious. Distributed systems add complexity — network partitions, distributed transactions, service discovery, and observability across multiple deployment targets. That complexity has to be justified by real organisational or scaling requirements.
- Every call can fail. A function call inside a monolith works or throws. A network call can also time out, arrive twice or arrive out of order.
- Data is harder. A change that touched three tables in one transaction now spans three services and needs careful handling when one step fails.
- Debugging takes tooling. Following one request across ten services requires tracing, central logging and monitoring before you need them, not after.
- You need a platform. Automated deployment, service discovery and configuration for many services is real work that somebody has to own.
The middle path: a modular monolith
Most teams do best with one deployable application divided into strict internal modules, each with its own code, its own data and a defined interface to the rest. You get clear boundaries and simple operations. If one module later needs to become a separate service, the boundary is already there.
Signs you have outgrown a monolith
- Teams regularly block each other’s releases.
- One part of the system needs far more capacity than the rest, and scaling everything together is wasteful.
- A deployment takes so long, or is so risky, that people avoid doing it.
- One area needs a different technology for a good reason.
If none of those is true, splitting the system will add cost without removing a problem.
How to extract a service safely
Do it one piece at a time. Pick the module with the clearest boundary, put a stable interface in front of it, move it out, and run it in production before touching the next. A rewrite of everything at once is the most common way these projects fail.
The best architecture is the simplest one that solves your current problem without blocking your next one.
Need a second opinion on your architecture? See our software development services or hire senior engineers who have done this before.