What We're Actually Comparing
A monolith is a single deployable unit. All your code lives in one repository, runs in one process, and deploys as one artifact. Your user authentication, billing, notifications, and core business logic all share the same codebase and database.
Microservices split your application into independently deployable services, each responsible for a specific business capability. The user service handles authentication. The billing service handles payments. The notification service handles emails and push notifications. Each has its own codebase, database, and deployment pipeline. They communicate over HTTP, gRPC, or message queues.
The debate isn't about which is technically superior. Both architectures power billion-dollar companies. The question is which one matches your team's size, your product's maturity, and your operational capacity right now.
Why Startups Should Almost Always Start with a Monolith
This is our strong opinion based on building dozens of products: if your team has fewer than 20 engineers, start with a monolith. Here's why:
Speed of Development
In a monolith, adding a feature that touches users, orders, and notifications is one pull request, one code review, one deployment. In microservices, it's changes to three services, three pull requests, coordinated deployments, and integration testing across service boundaries. For a startup that needs to iterate weekly, the monolith lets you ship 2x to 3x faster.
Debugging Is Straightforward
When something breaks in a monolith, you have one set of logs, one stack trace, and one debugger. In microservices, a bug might span three services, and you need distributed tracing (Jaeger, Datadog) just to figure out where the failure occurred. That tooling costs money and engineering time to set up.
No Network Boundary Overhead
Function calls within a monolith are nanoseconds. Network calls between microservices are milliseconds, plus serialization, deserialization, retry logic, circuit breakers, and timeout handling. Every service boundary adds latency, failure modes, and complexity.
One Database, One Source of Truth
A monolith with a single PostgreSQL database gives you ACID transactions across your entire data model. Need to create an order and update inventory atomically? One transaction. In microservices with separate databases, you need distributed transactions (sagas), eventual consistency, and compensation logic. That's weeks of engineering for something the monolith gives you for free.
Hiring Is Easier
Any backend developer can contribute to a monolith from day one. Microservices require understanding of distributed systems, service discovery, API contracts, and async communication patterns. The talent pool for monolith developers is 10x larger than for engineers experienced with microservices.
When Microservices Actually Make Sense
Microservices aren't wrong. They're wrong for most startups at most stages. Here's when they become the right choice:
Team Size Exceeds 40 to 50 Engineers
Conway's Law states that system architecture mirrors organizational structure. When you have 50+ engineers split into 8 to 10 teams, a monolith becomes a coordination nightmare. Every team's changes risk breaking everyone else's code. Merge conflicts are constant. Deployment becomes a ceremony requiring multiple teams to coordinate. At this scale, independent services with independent deployment pipelines let teams move autonomously.
Different Scaling Requirements
Your video transcoding service needs GPU instances. Your API gateway needs high-throughput CPU instances. Your notification service spikes during marketing campaigns. When different parts of your application have fundamentally different resource requirements, microservices let you scale each component independently rather than scaling the entire monolith for one component's needs.
Different Technology Requirements
Your ML pipeline needs Python. Your API needs Node.js. Your real-time features need Go for performance. Microservices let each team choose the best technology for their specific problem. A monolith locks you into one language and runtime.
Fault Isolation
In a monolith, a memory leak in the notification module can take down your entire application. In microservices, the notification service crashes while checkout, search, and user management continue operating. For applications where partial availability is acceptable and total downtime isn't, service isolation provides resilience.
The Real Costs of Microservices
Advocates often undersell the operational cost of microservices. Here's what you're actually signing up for:
Infrastructure Complexity
- Service discovery: Services need to find each other. Consul, Eureka, or Kubernetes DNS. That's infrastructure to set up and maintain.
- Load balancing: Each service needs its own load balancer or you need a service mesh (Istio, Linkerd).
- Container orchestration: Kubernetes or ECS to manage service deployment, scaling, and health checks.
- CI/CD pipelines: Each service needs its own build and deploy pipeline. 10 services = 10 pipelines to maintain.
Observability Tax
You need distributed tracing, centralized logging, and per-service metrics dashboards. Tools like Datadog, New Relic, or the Grafana stack (Prometheus, Loki, Tempo) cost $1,000 to $10,000/month for a modest microservices setup. A monolith needs basic application monitoring at a fraction of that cost.
Developer Productivity Impact
Running 10 services locally for development is painful. Docker Compose helps but is slow. Tilt and Telepresence help more but add tooling complexity. Many teams resort to shared development environments, which introduces its own problems (conflicts, stale services, environment drift).
Personnel Requirements
A microservices architecture requires at least one dedicated DevOps/platform engineer. More realistically, you need a platform team of 2 to 4 people managing the infrastructure, CI/CD, and developer tooling. That's $300,000 to $800,000/year in salaries alone.
The Modular Monolith: Best of Both Worlds
There's a middle path that most architecture discussions ignore: the modular monolith.
A modular monolith is a single deployable application with well-defined internal boundaries. Each module has its own directory, its own database schema (or even separate database), and communicates with other modules through explicit interfaces rather than reaching directly into each other's internals.
Think of it as microservices boundaries without the network. You get the organizational clarity of separated domains without the operational complexity of distributed systems.
How to Structure a Modular Monolith
- Enforce module boundaries. Each module exposes a public API (TypeScript interfaces, Python abstract classes). Other modules can only interact through this API. No reaching into another module's database tables or internal functions.
- Separate database schemas. Each module owns its tables. Cross-module queries go through the module's API, not direct SQL joins. This makes future extraction into a service straightforward.
- Use async communication internally. For cross-module side effects (order created, user signed up), use an internal event bus. This decouples modules and mirrors the eventual consistency pattern you'd need in microservices.
Shopify ran on a modular monolith (Ruby on Rails) for years while growing to billions in GMV. They extracted services selectively where the scaling or team autonomy benefits justified the complexity. This is the pattern we recommend for most startups.
Migration Strategy: Monolith to Microservices
If you've outgrown your monolith, here's how to migrate without rewriting everything:
The Strangler Fig Pattern
Named after a vine that gradually envelops a tree, this pattern extracts one service at a time from the monolith. Route specific requests to the new service while the monolith handles everything else. Over months or years, the monolith shrinks as services take over more functionality.
Which Services to Extract First
- Services with different scaling needs. If your image processing feature needs GPUs while everything else runs on standard instances, extract it first.
- Services owned by a specific team. If one team owns notifications and another owns billing, and they keep stepping on each other in the monolith, separate them.
- Services with independent data. If a module doesn't share database tables with other modules, it's the easiest to extract. Minimal data synchronization needed.
What NOT to Extract
Don't extract core domain logic that's tightly coupled with multiple other modules. Don't extract services just because they feel like they "should" be separate. And definitely don't extract more than one service at a time. Each extraction is a significant effort (2 to 6 weeks per service including testing and migration), and you need time to stabilize before moving to the next one.
Our Recommendation and Getting Started
Here's our decision framework:
- 1 to 20 engineers: Monolith. No question. Focus your engineering time on product, not infrastructure. Use a modular structure so you can extract services later if needed.
- 20 to 50 engineers: Modular monolith with selective service extraction. Extract only the services where the benefits clearly justify the operational cost. Most companies at this stage need 2 to 5 services, not 50.
- 50+ engineers: Microservices make sense when team autonomy becomes a bottleneck. Even then, aim for 10 to 20 well-defined services rather than hundreds of nano-services.
The biggest mistake we see: startups with 5 engineers building a microservices architecture because Netflix does it. Netflix has thousands of engineers and a dedicated platform team. You don't. Build a clean, modular monolith. Ship features fast. Grow your team and your product. When your monolith starts slowing you down (and you'll know when it does), extract services surgically.
The best architecture is the one that lets your team ship quality software quickly. For most startups, that's a well-structured monolith.
Need help choosing the right architecture for your project? Book a free strategy call and we'll assess your requirements, team size, and growth trajectory to recommend the right approach.
Need help building this?
Our team has launched 50+ products for startups and ambitious brands. Let's talk about your project.