Microservices or monolith: how do you choose?
The most reliable signal is team size and structure: small single teams with a monolith, multiple teams with independent release needs with microservices. The second signal is the real difference in scalability requirements between components: if everything scales together, there's no need to decompose.
The most underrated solution is the Modular Monolith: the benefits of code separation without the operational cost of microservices. It works for the vast majority of systems that are not Amazon or Netflix.

Luca has seven years of experience in C#. Four ASP.NET Core systems running in production.
Last week he proposed a microservices architecture for a new client project.
The client said yes. Luca was thrilled.
Eighteen months later, the project is behind schedule. Cloud costs are running at four times the original budget.
A six-person team is managing Kubernetes, a service mesh, and four separate CI/CD pipelines for a system with 300 active users.
Luca did not fail through incompetence. He failed because the technology industry has a structural problem that nobody had ever explained to him.
The problem is called conference bias: the tendency to copy the architectures of Netflix, Amazon and Spotify without sharing their problems or their resources.
The talks circulating online present solutions built by organisations with tens of thousands of engineers who could no longer coordinate on the same codebase.
They never show the real operational bill, the months of reduced productivity spent learning Kubernetes, or the dozens of companies that consolidated everything back into a monolith after years of struggle.
Conference bias works because the people who failed with microservices do not give talks.
Here is the uncomfortable truth: the right answer for your project is probably not microservices, and it is probably not a monolith either.
It lies in the structure of your team and the workloads you have today, not the ones you imagine having in three years.
In 25 years working on enterprise systems for Il Sole 24 Ore, NATO, Fiat and GSK, I have watched this story repeat itself dozens of times.
A team adopts microservices for the wrong reasons, accumulates complexity it cannot manage, and 18 months later consolidates everything into a Modular Monolith it should have built from the start.
This article gives you the five concrete signals that distinguish the cases where microservices save a project from the cases where they sink it, and explains why the Modular Monolith is the answer most development teams are looking for without realising it.
Monolithic architecture vs microservices: the Netflix myth nobody challenges at conferences

Most serious developers learned software design by watching conference talks.
The most-viewed talks of the past decade explain how Netflix, Amazon and Spotify solved their scaling problems with microservices.
That is precisely why the majority of development teams have adopted architectures that did not fit their situation, and are now paying a price they never budgeted for.
Most developers believe microservices are the natural evolution of the monolith: the mature choice for anyone who wants to do things properly.
In reality, Netflix did not choose microservices because they are better.
They chose them because of a specific problem: dozens of independent teams blocking one another, hundreds of millions of users, and availability requirements the monolith could no longer sustain.
The vast majority of software companies do not have that problem.
Applying Netflix's architecture to those contexts is not doing things properly. It is pure over-engineering that adds complexity with no real benefit.
The mechanism behind conference bias — the tendency to make technical decisions based on what is fashionable rather than on what the project actually needs — is straightforward: the talks you hear at conferences almost always showcase successes.
The person who wasted 18 months on the wrong microservices implementation rarely gives a talk about it.
This creates a systematic distortion: you only hear about the architectures that worked, in the context where they worked, for the problems those teams had.
You never hear about the failures.
The result is a distorted picture of the real benefits relative to the real costs.
In 2023, Amazon itself consolidated a distributed Prime Video system into a single monolithic application, cutting costs by 90%.
This is not an isolated case: it is a symptom of a systemic problem.
Software architectural patterns are chosen based on marketing and conference talks, not on the real requirements of the project.
Martin Fowler, one of the theorists who helped formalise microservices, has written explicitly that the default recommendation should be not to use them.
Sam Newman, author of the definitive book on microservices, has stated on multiple occasions that many teams adopt them without the organisational or technical foundations to manage them.
The result is what he calls a distributed monolith: all the problems of microservices with none of the benefits.
This pattern is particularly common among smaller consultancies and product teams that adopt enterprise-scale architectures without evaluating whether they make sense given their traffic volume, team size and available expertise.
The outcome is unnecessarily complex systems that are hard to maintain and expensive to run.
Monolithic architecture: what it is, the three variants and which one to avoid
Monolith does not mean badly written code.
In 2026 there are three types of monolith with profoundly different characteristics, and confusing them is the mistake that leads teams to migrate towards microservices for the wrong reasons:
| Traditional monolith | Modular Monolith | Distributed monolith | |
|---|---|---|---|
| Structure | Single artefact, logic not separated | Single artefact, modules with explicit boundaries | Multiple physical services, tightly coupled |
| Deployment | Single | Single | Multiple, but coordinated |
| Internal boundaries | None — everything calls everything | Explicit, public API per module | Weak — shared database, synchronous cascade |
| Network overhead | None | None | High |
| Verdict | Acceptable if disciplined | Recommended — best practice | Avoid — worse than either alternative |
The distributed monolith is not a poorly implemented microservices system.
It is a distinct architecture that is genuinely worse than a traditional monolith for any purpose. And unfortunately it is the most common outcome when teams adopt microservices without the right signals.
Stack Overflow, one of the world's most visited developer sites, handled billions of requests per month on a monolith for years.
Operational simplicity is not a weakness: it is a competitive advantage for any team that wants to move quickly.
What are microservices: definition, bounded context and the three criteria that matter
A microservice is an autonomous service responsible for a bounded context, which can be deployed, scaled and developed independently of the other services in the system.
But what is a bounded context?
Imagine you work at a company that sells shoes. The word "product" means different things depending on who is using it:
- To the warehouse team, it is a physical pair of shoes with a location on a shelf.
- To the marketing team, it is something with a name, a photo and a description.
- To the billing team, it is a line item with a price and a tax rate.
A bounded context is simply the department. Each one uses the same word with its own specific meaning, without creating confusion with the others.
The key word is not "micro". Not in the sense of small. Here it means independent.
A service qualifies as a true microservice only if it meets three criteria:
- Independent deployment: it can be released to production without coordinating with other teams or services. If you need to notify three other teams and wait for everyone to be ready, you do not have microservices — you have a disguised distributed monolith.
- Independent scalability: it can be scaled horizontally without having to scale the rest of the system.
- Independent development: a separate team can work on it without depending on the others.
The boundary of a microservice should correspond to a domain bounded context following the principles of Domain-Driven Design — an approach to software design in which the code structure mirrors the business domain.
The goal is not to split the system by technical function, but by domain concept: orders, inventory, payments, notifications.
Splitting by technical function instead of by domain produces nanoservice architecture: services so small that the volume of network calls between them cancels out any benefit from independence.
Understanding where to draw bounded context boundaries requires Domain-Driven Design skills that go well beyond technical knowledge.
It is the difference between someone who designs systems and someone who implements features.
That distinction in competence is precisely what separates a senior developer from a Software Architect, and it is not something you acquire by watching tutorials on YouTube.
I am not saying your system already has an architectural problem.
I am saying that every sprint spent managing complexity that produces no value for the client is time you will not get back.
And the difference between those who know where they stand and those who find out the hard way is always visible — but usually visible too late.
When to use microservices: 5 concrete signals that the monolith is no longer enough

You do not choose microservices for philosophical reasons, or because they are what modern technology companies use.
You choose them when concrete signals in your project indicate a real problem that only microservices can solve better than a monolith.
If the signals are not there, microservices are not the answer — regardless of what Netflix does.
1: multiple teams constantly blocking one another
If you have four teams working on the same codebase and continuously getting in each other's way — daily merge conflicts, deployments blocked because one team is not ready, endless meetings to coordinate releases — you are paying the organisational cost of a monolith without getting the benefit of its simplicity.
Conway's Law states that the architecture of a software system tends to mirror the communication structure of the organisation that builds it.
The question to ask is: are the teams blocking one another?
If the answer is yes, the organisational cost of the monolith is exceeding its benefits and it is time to consider microservices.
If the answer is no, the monolith is working and there is no reason to complicate the architecture.
2: radically different scalability requirements across components
If the search component receives 500 requests per second while the admin panel receives 2, and these differences are stable and confirmed by production data, extracting the search engine as a separate service makes economic sense.
A word of caution: this signal is only valid when the scalability requirements are genuinely and radically different, confirmed by real data — not hypothetical projections about the future.
3: incompatible technologies required for different components
If you need Python with TensorFlow for a machine learning component, .NET for the main backend, and possibly Go for a high-concurrency component, microservices are the natural answer.
A .NET monolith cannot natively integrate a Python module.
4: regulatory or compliance isolation
In sectors such as finance, healthcare or telecommunications, certain functions must be physically isolated for compliance reasons.
A payment system must be PCI-DSS certified separately from the rest of the application.
In these cases, microservices are not an optional architectural choice — they are a concrete regulatory requirement.
5: differentiated resilience with fault isolation
If one component must continue operating even when others are down, microservices allow you to contain failures.
In a monolith, if the process crashes due to a bug in one module, the entire system goes offline.
With microservices, a crashing service does not bring down the others.
Monolithic architecture: 5 conditions in which it outperforms microservices
There are equally concrete signals that indicate a monolith is not just the right choice today, but will remain the right choice for the foreseeable future of your project.
Recognising them saves you years of unnecessary operational complexity.
1: a small team or a single team
Below 10 to 15 developers working on the same system, microservices add complexity without any organisational benefit.
A single team with a well-structured monolith can move much faster than a team that must manage separate pipelines, multiple API versions and a service discovery mechanism — all of this for every individual module.
2: a domain that is still evolving and not yet stable
If you are building a new product and the domain is not yet clear, splitting into microservices early is dangerous.
Bounded contexts will shift as your understanding of the domain deepens.
Renegotiating boundaries between microservices in production is painful and expensive.
3: a team without experience in distributed systems
Running a microservices system requires specific skills: managing containers, enabling inter-service communication, tracing what happens as a request passes through dozens of services, and handling partial failures before they cascade.
If your team lacks this experience, the cost of acquiring it in the context of a live production system is enormous.
4: a limited operational budget
Operating microservices costs more.
More CI/CD pipelines, more staging environments, more compute resources for containers, more network costs between services.
For a startup or a mid-sized software consultancy, these costs are not trivial.
5: a system with strong transactional requirements
If the domain requires frequent distributed transactions — as in ERP systems, accounting platforms or multi-step approval workflows — a monolith greatly simplifies consistency management.
In a distributed system, transactions spanning multiple services are far more complex to handle and require specific approaches to keep data coherent.
Reading the signals is necessary, but it is not enough.
The Software Architect AI Course works on the code and architecture of your actual project — not on abstract demos.
The move from senior developer to architect is worth significantly more per month in most markets.
You are not paying for a course. You are accelerating a salary differential that pays for itself within weeks.
Some people reach this point in an article and say "I need to think about it."
Others say "I need to understand exactly where I stand before this becomes a real problem."
Only one of those two has already resolved the question.
Modular Monolith: what it is and why it sits between monolith and microservices

Between the traditional monolith and microservices there is a middle ground that solves most real-world problems with a fraction of the complexity.
It is called the Modular Monolith, and it is the solution most development teams should choose — but one that is often overlooked because it never makes the headlines at conferences.
Nobody gives a talk about the Modular Monolith, and that is precisely why it is the right choice for most contexts.
Conferences promote complexity because complexity is interesting to present. Functional simplicity is dull to talk about but invaluable to operate.
A Modular Monolith is a single deployable artefact divided internally into modules with explicit boundaries.
Each module has its own area of the database (a separate schema, not a separate database), its own public API towards other modules — typically defined as C# interfaces or internal events — and boundaries that prevent direct access to the internal entities of other modules.
The practical difference between the three approaches, in one line each:
| Traditional monolith | Modular Monolith | Microservices | |
|---|---|---|---|
| Deployable artefact | One, unstructured | One, separate modules | One per service |
| Internal boundaries | None (big ball of mud) | Explicit, via contracts | Physical, via network |
| Database | Shared, no separation | Separate schema per module | Separate database per service |
| Ideal team size | 1–5 developers | 5–15 developers | 3+ independent teams |
| Operational cost | Low | Low | High (3–5×) |
| Future migration | Difficult (full refactoring) | Surgical (extract one module) | N/A |
I worked with a tech lead with eight years of .NET experience who was managing a SaaS platform for the manufacturing sector.
He had started migrating to microservices based on advice from a consultant who had looked at the system for just three days.
Within four months, the five-person team had a Kubernetes cluster, three separate services and an Azure operational cost of €2,200 per month instead of €400.
No new clients. No new features.
Just more complexity.
Consolidating back into a Modular Monolith brought costs down to €500 per month and freed up two sprints per month of development time that had previously gone into infrastructure management.
The Modular Monolith is not a temporary solution while you wait for "real" microservices.
It is a fully legitimate architecture that can sustain complex systems for years, and it is the default choice recommended by many of the most respected software architects in the field.
If one day a module grows enough to justify extraction as a microservice, the boundaries are already defined.
The migration is surgical rather than a rewrite.
You are building a system that can evolve towards microservices only where necessary, without having to tackle everything at once.
Microservices: the hidden costs that push operational spending to 2–3 times the monolith
The cost of microservices is almost always underestimated. The conversation typically focuses only on benefits: scalability, team independence, resilience.
The real operational bill never appears on the conference slide.
Before choosing microservices, these costs need to be budgeted explicitly, line by line.
Infrastructure and management
Microservices require Kubernetes — powerful, but complex. For a five-person team, having at least one person dedicated to cluster management is a fixed overhead cost.
A minimal production-ready cluster costs €300–800 per month, comprising two main components:
- Control plane: the "brain" of the cluster. Free on the basic tier (with no uptime guarantees) or around €70 per month on the standard tier (with contractual SLA).
- Worker nodes: the machines that actually run your applications. This is the largest cost component and the one that drives the total.
Observability and distributed tracing
In a monolith, a log file and a debugger are usually enough.
In a microservices system, following a single request as it passes through five different services requires dedicated tooling, the ability to correlate logs across separate services and service-specific metrics for each one.
Service mesh and secure communication
Many teams end up adopting an additional infrastructure layer that automatically manages secure inter-service communication, traffic distribution and failure handling.
These tools are powerful, but they carry a significant learning curve and make deployments more complex.
Integration testing and contract testing
You need to verify that services continue to communicate correctly after every change.
This is a testing discipline that simply does not exist in a monolith.
Partial failure management
In a distributed system, a service can slow down or stop responding without the rest of the system immediately noticing.
Managing these partial failures requires specific strategies to prevent problems from cascading — complexity that simply does not exist in a monolith.
Empirical evidence suggests that the operational cost of a microservices system is typically two to three times that of an equivalent monolith.
If your project does not have the signals that justify this additional cost, you are paying a high price for complexity you do not need.
You have been led to believe that complexity is a sign of technical maturity. It is the opposite.
How to migrate from monolith to microservices: the Strangler Fig pattern step by step
If you have an existing monolith and the concrete signals that justify extracting microservices, the Strangler Fig pattern is the safest way to do it without rewriting the system from scratch and without stopping the business.
The name comes from a tropical fig tree that grows by wrapping itself around a host tree, slowly replacing its structure until the original tree dies and only the fig remains.
The software pattern works in the same way: new services grow around the monolith, intercepting traffic, until the original monolith has been gradually replaced in the areas where that makes sense.
How the Strangler Fig pattern works
- Identify the bounded context to extract: the one with the strongest signals — different scalability requirements, merge conflicts, compliance needs.
- Build the new service in parallel with the monolith, with its own database, infrastructure and CI/CD pipeline.
- Insert a proxy in front of the system to route traffic. In the .NET ecosystem, YARP (Yet Another Reverse Proxy), developed by Microsoft, is the natural choice.
- Migrate traffic progressively: start with 1–5%, monitor, increase gradually.
Remove code from the monolith only after the new service has handled 100% of traffic for at least four weeks.
This pattern works well only if the monolith has sufficiently clear boundaries to identify what to extract.
If it is a "big ball of mud" — software that has grown without a clear structure, where everything depends on everything — migration is nearly impossible without a preliminary internal refactoring phase.
Investing in a Modular Monolith from the start has a strategic value that only becomes fully apparent years later.
API gateway, service discovery and service mesh: what they are and when you need them in microservices
One of the most underestimated aspects of microservices is the infrastructure required to make them work correctly in production.
Every component solves real problems, but each requires specific expertise that many teams simply do not have.
API Gateway
The API Gateway is the single entry point for the system: it receives all external requests and handles routing, authentication, rate limiting and data transformation as required.
In the .NET and Azure ecosystem, the most common options are Azure API Management, Ocelot (open-source .NET) and YARP.
Service Discovery
Service Discovery is the mechanism by which services find one another automatically.
When a service starts, it registers itself in a central registry so that other services know where to find it without manual configuration.
When another service needs to communicate with it, it resolves the current address through that central registry.
Service Mesh
A Service Mesh manages all communication between services: it encrypts it automatically, distributes traffic across instances, handles failures and tracks what is happening across the system.
It adds complexity, but moves the responsibility for resilience from the application layer to the infrastructure layer.
Here is a comparison of the three components on what matters most before adopting them:
| API Gateway | Service Discovery | Service Mesh | |
|---|---|---|---|
| Function | Single entry point for external clients | Dynamic location of internal services | Full management of inter-service communication |
| .NET/Azure tooling | Azure API Management, Ocelot, YARP | Consul, Kubernetes-native DNS | Istio, Linkerd |
| What it handles | Authentication, rate limiting, routing, transformation | Address registration and resolution | mTLS, circuit breaking, retry, observability |
| Learning curve | Medium | Low (if Kubernetes-native) | High |
| When required | Always, with multiple exposed services | Always, in dynamic environments | Optional — justified beyond 10+ services |
The question to ask is: does your team have the expertise to manage all of this?
And do you genuinely need all of this for your traffic volume and system complexity?
In many cases the honest answer is no.
The cost of managing this infrastructure before it is truly necessary is real, constant, and produces no value for the client.
Microservices in practice: when they saved the project and when they sank it

Concrete case studies are more informative than any abstract principle.
These two scenarios reflect patterns that recur across markets. Names and details have been changed to preserve confidentiality.
Case 1: the e-commerce platform that genuinely needed microservices
A mid-sized e-commerce platform reached a critical point: the development team had grown to 25 people, divided into four functional teams.
The monolith had become an organisational bottleneck: every release required coordination across all teams, merge conflicts were frequent, and the checkout component had to handle 50 times normal traffic during peak periods.
The decision to extract the checkout service first, then the catalogue search engine, allowed those two components to scale independently.
The rest of the system remained a Modular Monolith.
That is the correct approach.
Case 2: the consultancy that lost 18 months on the wrong architecture
A software consultancy persuaded a client to rewrite a legacy ERP system as a microservices architecture.
The team was six developers, none of whom had previous Kubernetes experience.
After 18 months, the system was in production but with serious problems: high latency, data consistency failures, and an operational cost on Azure running at four times the planned budget.
The resolution was a partial consolidation into a Modular Monolith.
A Modular Monolith from the start would have solved the same problems without the costs that nearly sank the project.
Eighteen months of a six-person team earning €40,000 each annually, spent on an architecture that had to be rebuilt: that is €360,000 of gross labour that did not produce what it should have.
Someone paid that bill. Usually the client, for as long as they could absorb it.
Then the margin, for as long as there was any.
Then the project.
Microservices or monolith: three concrete questions to make the right choice
A practical decision framework rests on three key questions to be answered honestly based on the current state of the project — not on hypothetical future scenarios. "We might need to scale later" is not a valid answer to any of them.
Question 1: how many teams need to deploy independently?
This is the most important question.
If you have a single team or teams that work in a coordinated way, a monolith or Modular Monolith is almost always the right choice.
If you have three or more teams that need to release independently without waiting for one another, microservices begin to make organisational sense.
Question 2: do components have genuinely different scalability requirements today?
The valid signal is: component X requires ten times the resources of the others, and this is causing measurable economic waste or performance problems.
In that case it makes sense to extract it as a standalone service.
That component only — not the entire system.
Question 3: does the team have the expertise to manage distributed systems?
This question must be answered honestly.
Running Kubernetes in production, implementing distributed tracing, designing for partial failure, managing eventual consistency: these are specific, demanding skills.
If the team does not have them, the cost of acquiring them in the context of a live production system is high and risky.
If you answer no to the first two questions, start with the Modular Monolith.
If you answer no to the third, start with the Modular Monolith regardless of how you answered the first two.
In most markets, the majority of development teams work on projects where the team does not exceed ten developers and the domains are relatively transactional.
In that context, the Modular Monolith is almost always the right choice.
Modular Monolith in .NET: implementation with ASP.NET Core, Clean Architecture and explicit boundaries
The Modular Monolith is often presented as a concept, rarely as a concrete implementation.
In a .NET solution, the structure uses separate projects for each module, following the principles of Clean Architecture.
Each module has three projects: the core containing domain entities and interfaces, the infrastructure containing concrete implementations (EF Core, repositories, HTTP clients), and the public contracts exposing only the interfaces accessible to other modules.
Each module exposes only its Contracts project to the outside world. Other modules may depend on that, but not on its internal implementations.
This boundary is the difference between a Modular Monolith and a traditional monolith where everything depends on everything else.
When this boundary is maintained with discipline, the structure becomes the exact map for a future migration to microservices.
Migrating from monolith to microservices: database split, realistic timeline and hidden costs

The Strangler Fig pattern describes the strategy at a high level.
But how does it translate in practice for a team of five to ten developers?
The honest answer is that migration takes far longer than conferences suggest, and the database split is by far the hardest part.
Why big-bang migration does not work
A big-bang migration is one in which you stop developing new features, rewrite the entire system from scratch as microservices, and perform a cutover — the moment when you switch definitively from the old system to the new one.
In practice, the old system keeps acquiring new features during the rewrite, requirements change, and by the time you reach the cutover, the rewritten version is already behind the original.
The database split: the hardest part
Extracting a module's code into a separate service is relatively straightforward. Extracting the database is where most migrations stall.
The process unfolds in four phases:
- Eliminate cross-module JOINs by replacing them with two separate queries joined in memory.
- Remove cross-module foreign keys.
- Duplicate reference data using local projections updated via events.
- Only then physically extract the module's database.
Realistic timeline for a team of 5–10 developers
Months 1–2: preparation — internal modularisation, elimination of cross-module JOINs, infrastructure setup.
Months 3–6: extraction of the first service with a gradual rollout.
Months 6–18: extraction of subsequent services at 2–3 months each.
Hidden costs: time to acquire Kubernetes skills (3–6 months of reduced productivity), cloud infrastructure (€300–800 per month for the Kubernetes control plane), additional CI/CD pipelines.
For a team of five to ten developers, a full migration requires 18–36 months and an investment in the order of hundreds of thousands of euros.
If the signals are there, the migration is worth the investment.
If the signals are not, the Modular Monolith is the right answer: it lets you defer the complexity without accumulating technical debt, and extract services in the future only where and when it truly becomes necessary.
Luca, from the opening example, changed his approach.
He did not dismantle the microservices the day after: that would have cost him another six months.
He progressively consolidated the least-justified services, implemented a Modular Monolith for new bounded contexts, and kept microservices only where all three signals were genuinely present.
Operational costs returned to a sustainable level. The team started shipping features instead of managing infrastructure.
Not because he learned more technologies.
Because he stopped choosing architectures based on trends and started choosing them based on the signals in his own system.
A wrong architectural decision is one you pay for over years: in accumulated complexity, in operational costs, in team turnover from people who cannot work efficiently.
Every sprint spent on an architecture that does not fit your context is operational debt that someone, sooner or later, will pay.
And that someone is usually you, at the worst possible moment.
The ability to read these signals and translate them into architectural decisions that hold over time is not something you acquire by watching tutorials.
It comes from working on real systems with someone who has already made those mistakes and knows where they lead.
The Software Architect AI Course is built precisely for this.
Luca sorted things out.
Not immediately, not without cost — but he sorted them out.
Those who do not sort things out are usually not unwilling. They believe the problem is small enough to handle on its own, or far enough away to wait for the next project.
There are two types of developers who reach the end of an article like this.
The first closes the tab.
They feel better informed, confirmed in what they already thought, and go back to work.
The architectural problem sits exactly where it was. Now it just has a precise name.
The second asks an uncomfortable question: if the signals I have just read describe my system, what am I waiting for before acting?
I am not saying your project is going badly.
I am saying that every wrong architectural decision is paid for twice: once when you make it, and once when you have to undo it.
The second payment always arrives at the worst possible moment — with the client waiting and the team already under pressure.
The move from senior developer to Software Architect is worth significantly more per month in most markets.
Every month spent managing complexity that should not exist is a month in which you are paying the price of an architecture you have not yet learned to design well.
If you are thinking "I need to think about it" — know that this is exactly what the person who closes the tab says.
The Software Architect AI Course does not work on abstract scenarios.
It works on the architecture of your actual project, with someone who has already made those mistakes on real enterprise systems and knows where they lead.
The kind of expertise that separates those who absorb architectural decisions from those who make them.
You could wait for the next project to teach you the lesson.
That is usually the most expensive method.
Frequently asked questions
Microservices make sense when different teams need to release parts of the system independently, when different components have radically different scalability requirements, or when the system is large enough to justify the additional operational complexity. Team size is the most reliable signal: with fewer than 15-20 developers, a monolith is almost always the right choice.
Not necessarily. A well-written monolith can scale horizontally across multiple instances and handle high loads. Microservices allow individual components to scale independently, but this granularity only makes sense when bottlenecks genuinely differ per component. In most systems, the database is the primary bottleneck, and microservices don't automatically solve that problem.
A Modular Monolith is a monolithic architecture where the code is divided into modules with explicit boundaries and controlled dependencies, but is deployed as a single artifact. It's an intelligent compromise that provides separation of concerns without the operational complexity of microservices. It allows services to be extracted in the future if needed, starting from already well-defined boundaries.
Yes, and it's the most common path. The Strangler Fig pattern allows you to gradually extract functionality from the monolith into new services without rewriting everything from scratch. The fundamental condition is that the monolith has clear enough boundaries to identify what to extract. A big ball of mud monolith is nearly impossible to migrate safely.
Hidden costs of microservices include: Kubernetes or equivalent infrastructure, service mesh for secure communication, distributed tracing and observability, partial failure management with circuit breakers, network latency between services, integration and contract testing complexity, and distributed deployment overhead. Empirical studies suggest the operational cost of a microservices system is 2-3x that of an equivalent monolith.
