Start with ownership, not endpoints

A service should own a coherent capability and its data. Splitting every entity into a separate deployment can turn a simple business operation into a chain of remote calls. The code is distributed, but the reasoning is still tightly coupled.

Ask who can change a rule, where its invariants are enforced, and which data must be consistent together. These questions are more useful than counting controllers or tables.

Look for the cost of a change

If an ordinary change requires coordinated releases across several services, investigate whether the boundary is cutting through one capability. Shared database writes and long synchronous call chains are useful warning signs, not automatic proof that microservices are wrong.

A modular monolith can be an honest starting point. Clear modules and ownership teach you where a future network boundary might belong.

Validate the boundary

Trace one complete workflow, including validation, failure and retries. Decide which service makes each decision and what happens when a dependency is unavailable. Use explicit contracts rather than reaching around a service into its database.

The goal is independent reasoning and manageable change. More services are not an architectural outcome on their own.