MicroservicesWhat is microservices?An architecture where an application is split into small, independently deployed services that communicate over the network, each owning its own data. are powerful at the right scale, but the industry conflated "what works for Netflix at 200 million users" with "what works for a startup at 200 users."
Real reasons to adopt microservicesWhat is microservices?An architecture where an application is split into small, independently deployed services that communicate over the network, each owning its own data.
Four problems that microservices solve well. If you don't have at least one, a monolithWhat is monolith?A software architecture where the entire application lives in a single codebase and deploys as one unit. Simpler to build and debug than microservices. is almost certainly better.
1. Independent scaling
Different parts of your system have different resource needs. In a monolith, you scale everything together. With microservices, you run 20 instances of your image processor and 2 of your admin panel.
# Kubernetes: scale services independently
apiVersion: apps/v1
kind: Deployment
metadata:
name: image-processor
spec:
replicas: 20 # CPU-intensive, needs many instances
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: admin-api
spec:
replicas: 2 # Low traffic, minimal resources needed2. Team autonomy
With 50+ engineers on one codebase, merge conflicts become daily events and deploys become coordination exercises. Microservices let teams own their service end-to-end: deploy schedule, testing strategy, even programming language. This is fundamentally an organizational argument, mapping directly to Conway's Law.
3. Fault isolation
In a monolith, a memory leakWhat is memory leak?When your program holds onto memory it no longer needs, causing usage to grow over time until performance degrades or it crashes. in reporting can crash the entire application. With microservices, a crashed recommendation service shows fallback content while the restWhat is rest?An architectural style for web APIs where URLs represent resources (nouns) and HTTP methods (GET, POST, PUT, DELETE) represent actions on those resources. keeps working.
// API Gateway with fallback
async function getProductPage(productId: string) {
const product = await productService.get(productId); // Required
let recommendations;
try {
recommendations = await recommendationService.get(productId);
} catch (err) {
recommendations = await fallbackPopularItems(); // Graceful degradation
logger.warn('Recommendation service unavailable', { productId });
}
return { product, recommendations };
}4. Different tech stacks
Your ML team writes Python, your APIWhat is api?A set of rules that lets one program talk to another, usually over the internet, by sending requests and getting responses. team writes TypeScript. With microservices, each team picks the best tool. Valid but often overstated, polyglot architectures add operational complexity.
Bad reasons to adopt microservicesWhat is microservices?An architecture where an application is split into small, independently deployed services that communicate over the network, each owning its own data.
| Bad reason | Why it's wrong | What to do instead |
|---|---|---|
| "Netflix/Google/Amazon does it" | They have 10,000+ engineers and billions of users | Build for your actual scale |
| Resume-driven development | "I want microservices on my CV" | Optimize for your product, not your resume |
| "Microservices are modern" | Monoliths are not legacy by definition | Choose architecture based on constraints |
| "We need to be ready to scale" | Premature architecture is premature optimization | Scale when you need to, not before |
| "Our monolith is messy" | Messy code stays messy across services | Clean up the monolith first |
| "We want independent deploys" | Modular monolith with feature flags achieves this | Try the simpler solution first |
If you can't deploy one service reliably, you definitely can't deploy twenty.
Prerequisites: what you need before microservicesWhat is microservices?An architecture where an application is split into small, independently deployed services that communicate over the network, each owning its own data.
Microservices shift complexity from your codebase to your infrastructure. You need infrastructure maturity to handle that shift.
| Prerequisite | Maturity level required | Why it matters |
|---|---|---|
| CI/CD pipeline | Automated, reliable, per-service | You'll deploy 10-50x more often |
| Containerization | Docker + orchestration (K8s) | Services need isolation and portability |
| Observability | Distributed tracing, centralized logging | Debugging crosses service boundaries |
| Service discovery | DNS or service mesh | Services need to find each other |
| Automated testing | Integration + contract tests | Can't manually test cross-service flows |
| DevOps culture | Team owns build + deploy + monitor | No separate "ops team" to bottleneck |
| Incident response | On-call rotation, runbooks | More services = more failure modes |
| API versioning | Backward-compatible changes | Services evolve independently |
If you're missing more than two items, you're not ready.
The team size heuristic
You need roughly one team (3-7 people) per service, plus a platform team. If you have 8 engineers and 12 microservicesWhat is microservices?An architecture where an application is split into small, independently deployed services that communicate over the network, each owning its own data., "ownership" becomes "nobody maintains it until it breaks at 2am."
Team size → Architecture mapping
1-5 engineers → Monolith (maybe modular)
5-20 engineers → Modular monolith, maybe 2-3 services for genuinely different workloads
20-50 engineers → Microservices start making sense (5-10 services)
50-200 engineers → Microservices with platform team
200+ engineers → Full microservices with service mesh, internal platformThe strangler fig migrationWhat is migration?A versioned script that changes your database structure (add a column, create a table) so every developer and server stays in sync.
Don't rewrite everything at once. The strangler fig pattern lets you migrate incrementally: put a proxy in front of your monolithWhat is monolith?A software architecture where the entire application lives in a single codebase and deploys as one unit. Simpler to build and debug than microservices., build new features as services, and gradually move existing functionality out.
Before:
Client → Monolith (handles everything)
During migration:
Client → API Gateway → /users → Monolith (still handles users)
→ /orders → Order Service (extracted)
→ /payments → Payment Service (extracted)
→ /* → Monolith (handles the rest)
After:
Client → API Gateway → Individual servicesIf the new service has problems, traffic goes back to the monolith.
Decision framework
- Do different parts need different scaling? If the cost difference is significant, microservicesWhat is microservices?An architecture where an application is split into small, independently deployed services that communicate over the network, each owning its own data. help.
- Are teams blocking each other on deploys? If you've tried feature flags and modular code first, microservices help.
- Do you have the infrastructure maturity? If no, invest there first.
- Is your team large enough? Fewer than 15-20 engineers, probably not.
- Do you know your domain boundaries? If no, keep the monolithWhat is monolith?A software architecture where the entire application lives in a single codebase and deploys as one unit. Simpler to build and debug than microservices..
Quick reference
| Factor | Favor monolith | Favor microservices |
|---|---|---|
| Team size | < 20 engineers | > 20 engineers |
| Deploy frequency | Same across features | Varies significantly per team |
| Scale requirements | Uniform | Different per component |
| Domain knowledge | Still learning boundaries | Well-understood, stable boundaries |
| Infrastructure maturity | Early stage | CI/CD, containers, observability in place |
| Data consistency needs | Strong ACID needed | Eventual consistency acceptable |