Microservices are easy to draw and expensive to live with. I have seen teams split early for “scale” they did not have, then drown in network failures, duplicate auth, and deployment choreography that nobody owned end to end.
When I push for a boundary
A service earns its life when a domain has a clear owner, a different change cadence, or a failure mode that must stay isolated. Payments, notifications, and heavy async work are common candidates. “We might need Kubernetes someday” is not a boundary.
- Start modular in one deployable unit until pain is measurable.
- Split along business capability, not along folder names that felt tidy.
- Require observability before independence, logs, metrics, tracing, alerts.
- Count operational cost: deploys, secrets, versioning, local DX.
The decision meeting I want
Good microservice decisions sound boring: “This domain changes weekly and breaks guest booking when it fails, so we isolate it and give it a clear API contract.” Bad ones sound exciting: “We will be like Netflix.” I would rather ship a boring modular monolith that works than a constellation of services that cannot answer a simple support ticket.
Architecture is product risk management. If the split does not reduce risk or increase delivery speed for a real team, it is decoration.
Key takeaways
What to remember
- Split when ownership and failure modes demand it.
- Modular monolith first until pain is measurable.
- Observability before independence.





