Your architecture choice shouldn't be driven by what Netflix or Uber is doing. It should be driven by where you are right now — your team size, your traffic, your deployment maturity, and your runway. The monolith vs microservices debate has a real answer for your situation. It's just not the one most blog posts give you.
Here's the framework we use when helping startups and growth-stage companies make this call.
Why Most Teams Get This Wrong From the Start
The mistake I see most often: founders read about how Airbnb or Grab migrated from a monolith to microservices, and they decide to build microservices from day one because that's what scale looks like.
It isn't. That's what post-scale looks like. There's a difference.
When those companies broke apart their monoliths, they had hundreds of engineers, mature CI/CD pipelines, dedicated platform teams, and years of operational experience with their own domain boundaries. They weren't starting fresh. They were solving a problem that emerged from growth, not anticipating one that might never arrive.
Starting with microservices before you have product-market fit is one of the fastest ways to burn engineering resources on infrastructure instead of product. We've seen it happen. It's painful to watch.
The Monolith: Unfairly Maligned
A monolith isn't a bad architecture. It's a starting point. And for most teams — honestly, for teams up to 10–15 engineers with a single product — it's the right one.
In a traditional monolith, all your application code lives in one deployable unit. One codebase, one database, one deployment pipeline. The benefits are real and often underappreciated.
Development velocity is genuinely faster early on. There's no network latency between services, no distributed transaction complexity, no service discovery overhead. You can refactor across the entire codebase in one shot. Debugging is straightforward because everything runs in one process.
The problems come later. As your team grows, the codebase becomes harder to navigate. Different teams start stepping on each other's work. Deployments get slow and risky because every change ships everything. That's when the architecture starts to fight you, not help you.
The real signal you've outgrown a monolith isn't traffic. It's team friction and deployment pain.
[→ Read: How to build a backend that scales from 100 to 10 million users]The Modular Monolith: The Option Nobody Talks About Enough
Here's the counter-intuitive point: for most startups that think they need microservices, a modular monolith is actually the better answer.
A modular monolith is still a single deployable unit, but the internals are deliberately structured into isolated modules — each with clear boundaries, their own data ownership, and strict rules about how modules interact. Think of it as microservices discipline inside a monolith's deployment model.
The practical result: you get much of the architectural clarity of microservices without the operational overhead. You can enforce team ownership of modules. You can move faster without breaking unrelated parts of the system. And when you eventually decide to extract a service, the module boundary makes it a surgical operation instead of a painful untangling.
Shopify ran a monolith for years, and the work they did to make it modular — what they called "componentisation" — is one of the more honest engineering stories out there. It wasn't glamorous. It was just effective.
A modular monolith is the architecture that earns microservices. You build the discipline first, then you extract services when the operational case is clear.
Microservices: When They Actually Make Sense
Microservices are the right answer for a specific set of conditions. All of them need to be true, not just one.
Your team is large enough that different groups genuinely need independent deployment cycles. You have parts of your system with radically different scaling characteristics — say, a real-time notification service that spikes to millions of events per second while your invoicing service handles hundreds of requests per day. You have the platform engineering capacity to run container orchestration, service meshes, distributed tracing, and on-call rotations for multiple services. Your domain boundaries are well understood because you've built and operated the system long enough to know where they should be.
If you're missing any of those, microservices will slow you down.
The operational surface area is real. In a distributed system, you're now debugging network partitions, handling partial failures, managing schema migrations across service boundaries, and coordinating deployments across multiple repositories. Each of those is a solvable problem. Collectively, they require a team that has the headspace to solve them.
One of SpectreDev's clients — a Series A fintech — came to us after attempting a microservices migration with a team of six engineers. Eighteen months in, they had eight services, three of which couldn't be deployed independently because of undocumented shared state. The team was spending more time on infrastructure incidents than feature work. We spent three months collapsing it back to a modular monolith before rebuilding the extraction incrementally. The irony isn't lost on anyone.
[→ Read: What is database sharding — and when does your startup actually need it]The Decision Framework
Use this as a starting point. It's opinionated and it's supposed to be.
Build a monolith if: you're pre-product-market fit, your team is under 8 engineers, and your primary constraint is development speed.
Refactor toward a modular monolith if: you've found product-market fit, your team is growing, and you're starting to feel the organisational friction of a shared codebase — but you don't yet have the platform maturity for distributed systems.
Extract services from that modular monolith if: a specific module has a genuinely different deployment cadence, a clearly different scaling profile, or a different team ownership model that justifies the operational overhead. Extract one service, operate it well, then decide on the next.
Notice what's not on that list: "because we expect to have 10 million users someday." That's not an architecture decision. That's wishful thinking. Architect for where you are and the next logical growth phase, not for a ceiling you may never approach.
For Indonesian companies specifically, there's an additional layer to consider: talent availability. Engineers comfortable with distributed systems operations — Kubernetes, service mesh, distributed tracing — are a thinner slice of the market in Jakarta than in San Francisco. A modular monolith your current team can operate confidently is worth more than a microservices setup that creates a hiring dependency you can't fill.
Practical Example: How a Regional E-Commerce Startup Should Think About This
Consider a regional e-commerce platform — think something operating across Indonesia, Malaysia, and the Philippines — in the 50,000–200,000 active users range and growing.
At that scale, the right architecture is almost certainly a modular monolith. You'd want clearly isolated modules for the product catalogue, order management, payments (especially given regional payment methods like GoPay, OVO, and GrabPay that each have their own integration logic), and logistics tracking.
None of those need independent deployments yet. But structuring them as modules means when you hit 2 million users and the payments module is getting hammered during 11.11 flash sales, you can extract it as a standalone service with a clear API contract already in place. The groundwork is done.
The alternative — building microservices for each of those domains at 50,000 users — would add months of infrastructure work before you've even proven the product works in all three markets.
[→ Read: How to build a backend that scales from 100 to 10 million users]FAQ
Q: Can I start with a monolith and migrate to microservices later without rewriting everything?
A: Yes — and this is actually the intended migration path. The key is maintaining clean module boundaries inside your monolith from early on. If you've built a well-structured modular monolith, extracting a service means defining the API boundary (it probably already exists as a module interface), setting up the deployment infrastructure for that service, and gradually moving traffic. It's still significant work, but it's not a rewrite. A "big bang" monolith with tangled dependencies is the one that requires a painful rewrite.
Q: At what team size should I seriously consider moving to microservices?
A: Team size isn't the only variable, but a rough heuristic: when you have more than 15–20 engineers working on the same codebase and deployment friction is measurably slowing you down, it's worth having the conversation. The more useful indicator is whether you can deploy changes to one part of the system without risking unrelated parts — and whether the answer is "no" consistently enough to hurt you.
Q: Are microservices harder to secure than a monolith?
A: Differently hard, not necessarily harder. In a monolith, your attack surface is more contained but a compromise can affect the whole system. In microservices, you have more network attack surface and need to secure service-to-service communication (mTLS, service accounts, network policies). The security posture depends entirely on your implementation. Neither architecture is inherently more secure.
Q: What about serverless — is that a fourth option?
A: Serverless functions can be a useful pattern within any of these architectures, but they're not a replacement architecture. You can have serverless functions inside a modular monolith (for async event processing, for example), and you can have them inside a microservices system. Serverless introduces its own complexity around cold starts, stateless design, and vendor lock-in that most teams underestimate. For most startups, it's a tool, not a strategy.
Q: We're a non-technical founder. How do we evaluate whether our current tech team is recommending the right architecture?
A: Ask them to explain the trade-offs, not just the choice. A strong engineer can tell you what you're giving up with their recommended approach, not just what you're gaining. If the pitch for microservices doesn't include an honest discussion of operational overhead, distributed system complexity, and your team's current capability to manage it — that's a flag. The best architecture recommendation for your stage should feel slightly boring. Exciting architecture choices are usually expensive ones. [→ Read: How to run a technical debt audit]
The right architecture is the one that lets your team ship product, maintain reliability, and adapt as your business changes. That's not microservices for most of you reading this. It's probably a well-structured monolith or modular monolith that gives you the discipline to grow into something more distributed when the evidence actually demands it.
If you're at the stage where these decisions are becoming real — whether you're building 0 to 1 or hitting the walls of a system you've outgrown — this is exactly what we work through with clients at SpectreDev.
External Documentation: