Software developmentComparison
daLæs på danskMonolith vs Microservices: Why Most Projects Should Start as a Monolith
Monolith vs microservices for small teams: what microservices really cost, why a modular monolith fits most projects, and the signals that justify a split.

Freelance full-stack developer
- Published
- Reading time
- 11 min
In this post9
In the monolith vs microservices debate, the honest answer for most small and mid-sized teams is a monolith: one application, one codebase, deployed as a single unit. Microservices split a system into many small services that run and deploy independently. That solves a real problem for organizations with many engineering teams and creates expensive new ones for almost everyone else.
If you're a European SME or an early-stage startup with a handful of developers, start with a well-structured monolith and split off a part only when you can name the problem it solves. My own default for new web apps is a single Laravel application, so weigh that bias, but I'll be just as specific about when splitting is the right call.
The short answer
| Monolith | Microservices | |
|---|---|---|
| What it is | One application and codebase, usually one database | Many small services, each with its own code, deployment and often its own database |
| Best fit | New products, small and mid-sized teams, most business web apps | Large organizations with many teams and parts with very different load |
| Time to first release | Short, you build features from week one | Longer, the platform and pipelines come first |
| Running it | One app to monitor, patch and back up | Many services, the network between them, queues and centralized logging |
| Debugging | One place to look, one log | A single request can cross several services |
| Scaling | Scale the whole app, which is usually enough | Scale each part independently |
| Cross-cutting changes | One change, one deployment | Coordinated releases and versioned APIs between services |
| Biggest risk | Turns into a tangle if nobody keeps it organized | High fixed costs and a distributed mess if the boundaries are wrong |
My rule of thumb: build a monolith, keep it modular inside, and pull a piece out only when you can name a concrete problem the split fixes that can't be fixed more cheaply inside the app. "It needs to scale" isn't a problem statement. "PDF generation slows down checkout every time we send monthly invoices" is.
To see where architecture fits in the bigger picture, I've written an overview of the software development process from idea to launch.
Monolith vs microservices in plain terms
A monolith is a single application. Accounts, orders, invoicing and reporting all live in the same codebase, usually share one database and go live together. When you ship a fix, you ship the whole app. The word sounds dated, but most web apps are built this way.
With microservices, the system is split into small, independent services. One handles accounts, another orders, a third payments. Each has its own code and release cycle and often its own database. They talk to each other through APIs (defined interfaces that programs use to exchange data) or through message queues.
Think of it as one office versus teams spread across several cities, where every question becomes an email: it takes longer, and occasionally it never arrives.
A function call inside a monolith practically always works. A call across the network can be slow, can fail, or can half succeed, and every service has to be written to cope with that. This is where the extra cost of microservices comes from.
Why I'd start almost every project as a monolith
The strongest reason is that nobody knows the right boundaries at the start. To split a system into services, you need to know which parts belong together, and you only learn that by watching people use the product. A wrong guess inside a monolith means moving some code. A wrong guess between services means changing APIs, migrating data between databases and coordinating releases.
Martin Fowler argued in 2015 that nearly every successful microservices story he knew of began as a monolith that grew too big and was then broken up. Systems built as microservices from scratch, in his experience, mostly ran into serious trouble.
The second reason is organizational. Conway's law, from 1968, says that a system's design ends up mirroring the communication structure of the organization that builds it. Microservices fit companies with many teams that each own a part and want to release without waiting for anyone else. If you have three, five or eight developers, you have one team. You get all the overhead of the split and none of the independence.
A simple test I use: if everyone who works on the product can join the same weekly call, one application is almost always enough.
The third reason is speed. Every week spent wiring up pipelines and service plumbing is a week you're not learning whether customers want the product.
The microservices tax: what it costs a small team
Microservices are often pitched as the modern default without the bill attached. Here's what you pay for, starting long before launch:
- Every service has to be built, tested, deployed, monitored and patched. Ten services means ten times that work, plus the glue between them.
- In a monolith, an order and its payment can be saved in one database transaction: either both succeed or neither does. Split across services, you have to handle the case where the payment went through and the order was never created.
- One customer complaint can trace through four services. Without centralized logging and request tracing, you're guessing.
- Each service with its own database is another place to secure, back up and cover in your GDPR documentation, and another chance for data to end up outside the EU.
- The more unusual the architecture, the fewer developers can maintain it after your original vendor moves on.
This isn't hypothetical. In 2018, Twilio Segment described running more than 140 small services for forwarding customer data to other tools, with operational work growing every time they added one. They eventually merged them back into a single service and found it much easier to work on. And Segment really did have heavy traffic.
For a smaller project, that means more hours for the same features and a bigger hosting bill every month.
The modular monolith: the middle ground most teams should pick
A monolith doesn't have to be one big ball of code where everything depends on everything. A modular monolith is split into clear modules by business area, such as customers, orders, billing and inventory, but still deploys as one unit.
The rules are easy to state but take discipline to follow:
- Each module owns its responsibilities and its own database tables.
- Modules talk to each other through a few explicit entry points, never by reaching into each other's data.
- Heavy work like PDF generation, image processing and calls to third-party systems runs as background jobs on a queue, so it never slows down the rest of the app.
Shopify took exactly this route. Rather than breaking its large Ruby on Rails application into microservices, it reorganized the codebase into components by business domain and built tooling to enforce the boundaries. If that approach holds up at Shopify's scale, it will hold up for your customer portal or internal tool.
You get most of the clarity people want from microservices without network calls or scattered data, and if a module ever needs to become its own service, the boundary is already drawn. Laravel ships with queues, caching and scheduled jobs, so much of what teams build separate services for can stay inside the app. That's one of the reasons Laravel is my default for web apps.
A monolith also scales further than most people assume. You can run several copies of the same app behind a load balancer (a server that spreads traffic), give the database more resources and cache what's read often. When an app is slow, the architecture is rarely the cause. It's usually slow database queries, missing caching or heavy work running while the user waits.
When each option is the wrong choice
When a monolith stops being the right fit
- Several teams work on the same product and keep blocking each other's releases. At that point the organization has outgrown a single codebase.
- One part has a completely different load profile from the rest, like video transcoding or heavy batch jobs, while the main app serves a modest number of users.
- A part has to be isolated for security or regulatory reasons, payment data being the classic example.
- A part needs a different language or runtime, such as a Python machine learning model next to a PHP web app.
None of these require turning the whole system into microservices. The usual answer is one or two separate services next to a monolith. And if you're designing a whole platform of services for many teams, you need an in-house architect or a platform team more than a freelancer like me.
One situation looks similar but isn't: a monolith that was never kept in order, where every change feels risky. Splitting it rarely helps, because a mess in one codebase becomes a mess in ten. Start by getting a clear picture of the technical debt and what it's costing you, and clean up before you carve anything out.
When microservices are the wrong fit
- The product is new and you're still learning what customers want.
- The team is small: a freelancer, a small agency or an in-house team of a few people.
- The case for them is "scalability" and nobody can say what needs to scale, or by how much.
- The budget doesn't cover ongoing operations: monitoring, logging and someone who understands the whole setup.
- Nobody on your side can evaluate the architecture, so you can't tell whether it was chosen for your product or for the people building it.
Splitting a monolith without a rewrite
When you do have a concrete problem that a split solves, pull out one part at a time while the rest keeps running as before. This is often called the strangler fig pattern, named after a fig that grows around its host tree and eventually replaces it.
- Pick the part with the clearest problem and the cleanest boundary. Usually something with its own load or data, like image processing or a third-party integration.
- Make the boundary explicit inside the monolith first, so the rest of the code only touches that part through one entry point.
- Move the part into a separate service behind that same entry point. The rest of the system doesn't notice.
- Set up monitoring and logging for the new service before it takes real traffic.
- Check that the original problem is actually solved before you consider the next split.
Most teams stop after one or two services, because that was the problem they had. That's a sign it worked, not a half-finished migration. If it's a SaaS product that's growing, I've also written about what scaling a SaaS application usually involves.
Next steps
If someone has proposed microservices for your next build, ask these questions before you sign off.
Questions to ask before approving a microservices architecture
- What specific problem does the split solve that a well-organized monolith can't?
- What will it cost to run each month, in hosting and in people, and who runs it after handover?
- How many developers could take it over if the current team or vendor stops?
- Where will personal data be stored, and does every service keep it inside the EU?
Vague answers usually mean the architecture was chosen because it's exciting, not because your product needs it. And if you're dealing with an existing system that's hard to change, the signs of a healthy codebase are a better starting point than an architecture debate.
My starting point for new web apps and platforms is a well-structured monolith with room to grow, and I'll say so plainly if your product needs something else. You can see how I approach these builds on my web apps and platforms service page.
Frequently asked questions
Are microservices faster than a monolith?
Not by themselves. A call over the network is slower than a function call inside one application, so a simple request can get slower when it passes through several services. The real advantage is that you can give one heavy part more resources without scaling everything else.
Is serverless the same as microservices?
No, but it shares many of the same trade-offs. Serverless means your code runs as small functions that the cloud provider starts on demand, and you pay per execution. It works well for isolated tasks, like processing uploaded images. If you build an entire product out of dozens of small functions, though, you inherit the same debugging, data consistency and coordination problems as microservices.
What is a distributed monolith?
A distributed monolith is a system split into services that depend on each other so tightly that they have to be changed and deployed together. You pay for the network, extra databases and complex operations without getting the independence that was the point. It typically happens when service boundaries are drawn before anyone understands the product well enough.
Is a monolith a problem for GDPR or EU data residency?
No, it's often the simpler option. A single application with one database hosted in an EU region gives you fewer places where personal data lives, which makes it easier to document, secure and keep inside the EU. Microservices that lean on many managed cloud services can spread data across more providers and regions. This isn't legal advice, so check your specific setup with a privacy professional.