Monolith vs Microservices: The Eternal Debate
Start with a monolith.Extract microservices only when specific scaling bottlenecks or organizational boundaries demand it.Premature microservices are the root of all evil in distributed systems.
The Hype Cycle
In 2015, Netflix said "We use Microservices." Everyone heard "We should use Microservices."
Netflix had 1,000 engineers.You have 3.
Context matters.Microservices solve organizational scaling problems, not just technical ones.
The Monolith Defense
A Monolith is a single deployable unit.It is beautiful because:
- No Network Latency: Function calls are instant.
- Atomic Transactions:
BEGIN TRANSACTION...COMMITworks. - Simple Deployment:
git pull && pm2 restart. - Simple Debugging: One log file. One stack trace.
Stack Overflow run on a monolith for 10 years.Shopify is a monolith.GitHub is a monolith.
The Fallacy of "Scalability"
People think "Monoliths can't scale." This is false.
You can scale a monolith vertically(bigger AWS instance).
You can scale a monolith horizontally(run 10 copies behind a Load Balancer).
The only thing you can't scale independently is deployment velocity for distinct teams.
If Team Billing wants to deploy on Tuesday, but Team Search broke the build on Monday, that's an organizational bottleneck. Microservices solve this.
The Cost of Microservices
When you switch to microservices, you trade "Complexity of Code" for "Complexity of Infrastructure."
| Challenge | Monolith | Microservices |
|---|---|---|
| Transactions | ACID(Easy) | Eventual Consistency(Sagas - Hard) |
| Reliability | Single Point of Failure | Cascading Failures(Circuit Breakers needed) |
| Observability | One Log | Distributed Tracing(Honeycomb / Jaeger) |
The Distributed Monolith
The worst architecture is the "Distributed Monolith." This happens when you split your code into services, but they are tightly coupled.
Example: Service A calls Service B, which calls Service C to return a response.
If Service C is down, Service A is down.You have maximized latency and maximized fragility.
Rule: Services should be autonomous. They should communicate via asynchronous events (Kafka/RabbitMQ) whenever possible.
The Modular Monolith
This is the Goldilocks solution.
Write code in specific folders / modules.Enforce boundaries(e.g., Module A cannot import from Module B directly; it must use a public API interface).
Deploy as one unit.
When one module becomes too big or needs independent scaling(e.g., Video Transcoding), extract only that module into a microservice.
Conclusion
Don't be Resume Driven Developer. Build a Modular Monolith. Extract services only when you feel the pain. Complexity is the enemy of velocity.