Microservices are everywhere. Tech giants use them, conference speakers praise them, and job postings demand experience with them. But here’s what they don’t tell you: microservices might be killing your startup.
The Allure of Microservices
I get it. The promise is seductive:
- Independent deployments
- Technology flexibility
- Team autonomy
- Infinite scalability
But for most teams I’ve worked with, microservices introduce more problems than they solve.
The Real Costs
1. Operational Complexity
With microservices, you’re not just running one application—you’re running dozens. Each service needs:
- Its own deployment pipeline
- Health checks and monitoring
- Log aggregation
- Service discovery
“We went from deploying once a week to managing 15 deployment pipelines. Our velocity actually decreased.” — A CTO who learned the hard way
2. Distributed Systems Are Hard
Things that are trivial in a monolith become complex challenges:
// In a monolith: simple function call
const order = await createOrder(userId, items);
const payment = await processPayment(order.id);
await updateInventory(items);
// In microservices: distributed transactions
try {
const order = await orderService.create(userId, items);
const payment = await paymentService.process(order.id);
await inventoryService.update(items);
} catch (error) {
// What if payment succeeds but inventory update fails?
// Welcome to saga patterns and eventual consistency
await compensate(order, payment);
}
3. Network Latency
Every service-to-service call adds latency. What was a 5ms database query becomes:
- 5ms database query
- 2ms serialization
- 10ms network hop
- 2ms deserialization
- Repeat for each service
A simple page load might involve 20 service calls, turning milliseconds into seconds.
When Microservices Make Sense
I’m not saying microservices are always wrong. They work well when you have:
- Large teams (50+ engineers) that need to work independently
- Different scaling requirements for different parts of your system
- Genuine domain boundaries that rarely change
- DevOps expertise to manage the infrastructure
The Modular Monolith Alternative
For most teams, I recommend a modular monolith:
src/
├── modules/
│ ├── users/
│ │ ├── controllers/
│ │ ├── services/
│ │ └── repositories/
│ ├── orders/
│ │ ├── controllers/
│ │ ├── services/
│ │ └── repositories/
│ └── payments/
│ ├── controllers/
│ ├── services/
│ └── repositories/
├── shared/
│ ├── database/
│ └── utils/
└── main.ts
Benefits:
- Clear boundaries without network overhead
- Easy to extract services later if needed
- Single deployment simplifies operations
- Transactions just work
Making the Decision
Ask yourself these questions:
- Do we have more than 30 engineers?
- Are different parts of our system at vastly different scales?
- Do we have dedicated DevOps/Platform engineers?
- Have we identified clear, stable domain boundaries?
If you answered “no” to most of these, stick with a well-structured monolith.
Conclusion
The best architecture is the one your team can effectively build and maintain. For most startups and small teams, that’s a modular monolith—not microservices.
Don’t let hype drive your architecture decisions. Let your actual needs guide you.
Need help evaluating your architecture? I offer consulting sessions to help teams make informed decisions.