Modular monolith or microservices? Start with the boundaries.
How to decide whether independent services solve a real constraint for your product and team.

Separate business responsibilities clearly, then decide which boundaries need independent deployment, operation or capacity.
Separate code structure from deployment structure
A monolith is an application deployed as one unit. It can contain carefully separated modules, or it can be tangled and difficult to change. Microservices place responsibilities in separately deployed services that communicate across boundaries. Those services can also be well organized or tangled. The number of deployments does not tell you whether the product has a coherent design.
A modular monolith keeps distinct responsibilities within one deployment. For a hypothetical operations product, scheduling, customer records and reporting might each have a defined interface and clear ownership of their behavior. The application remains operationally compact while the team limits how one area depends on another.
Start by asking which responsibilities belong together and which changes frequently cross them. If the team cannot explain those boundaries inside one application, distributing the same uncertainty across several services is unlikely to clarify it. First understand the concepts the product uses and the rules that must remain true as people work.
Identify a reason for independent services
Independent services can be useful when a responsibility needs a different release cadence, a different runtime or a materially different capacity profile. They can also help teams own a defined area without coordinating every release. These are specific benefits to investigate, rather than automatic properties of a growing company.
Consider a hypothetical document product where conversion jobs consume substantial computing resources while ordinary editing remains light. Separating conversion into workers may let the team expand that capacity independently. It does not necessarily require dividing customer accounts, permissions and every other responsibility into separate services at the same time.
Microsoft’s microservices guidance describes benefits such as independent deployment and scaling alongside challenges including complexity and data consistency. Use both sides of that trade-off. Ask what independence is needed, which evidence supports that need and whether a smaller change can provide it. A deployment boundary should earn its operational consequences.
Understand the cost of crossing a network
Inside one application, a function call and a shared transaction can make certain changes straightforward. Across services, an interaction may be delayed, interrupted or completed even when the caller does not receive confirmation. The team must decide how to recognize each outcome and what to do next. This is part of the feature’s behavior, not incidental plumbing.
Data ownership becomes especially important. If several services freely edit the same records, their deployments remain coupled through hidden assumptions. If each owns its data, a business operation spanning them needs an explicit coordination approach. The founder does not need to select the algorithm, but should expect the team to explain what a customer sees when only part of the operation completes.
Traceability also matters. OpenTelemetry’s trace model connects spans across an operation, helping engineers follow work through components. A distributed product needs a practical way to relate an incoming request to the services and background jobs it triggers. Without that visibility, an ordinary support question can become a search across disconnected logs.
Assess what the team can operate
Every independently running service needs a release path, configuration, access controls, monitoring and a recovery approach. Shared tooling can reduce repeated work, but someone still needs to understand the behavior. The architecture should fit the team’s ability to maintain those responsibilities alongside product development.
Ask who responds when a service fails and how they find the relevant information. If the answer is always one person who understands the entire system, the proposed split may not create the organizational independence expected. Conversely, a team with clear ownership and established operational practices may be well placed to benefit from a service boundary.
Also consider local development. An engineer should be able to make and validate a normal change without reconstructing the whole production environment. Define which dependencies are required, which can be represented locally and where integration checks happen. The objective is a workable feedback cycle that still catches errors at the real boundaries.
Choose an incremental path
When the evidence favors a modular monolith, make its boundaries real. Give modules clear entry points, keep ownership of rules explicit and review changes that reach across those boundaries. A folder structure alone does not stop unrelated areas from depending on each other’s internal details. The team needs a shared understanding backed by suitable code checks and review.
When the evidence favors extraction, choose one responsibility with a clear interface and a demonstrable benefit. Define its inputs, outputs, failure behavior and data ownership before moving it. Establish a comparison that will show whether the separation actually improved the constraint that motivated the work.
Record the conditions that would justify another split. This keeps the architecture responsive to the product without making every growth milestone a restructuring project. The useful question is whether the current arrangement supports customer demand and allows the team to change it reliably. A single well-structured application can do that. A set of well-operated services can do that too. The decision rests on the boundaries, the workload and the people responsible for running them.
Frequently asked questions
When are microservices worth considering?
Consider them when a specific part of the product needs independent deployment, operation or capacity, and the team can support the added complexity. Start with clear business responsibilities rather than a preference for a deployment pattern.
Can a monolith still have clear modules?
Yes. Code structure and deployment structure are different decisions. A single application can separate responsibilities into modules with explicit boundaries without deploying each module as its own service.
What extra work comes with microservices?
Cross-service calls can fail or respond late. Teams need to manage contracts, tracing, deployment, data ownership and recovery across those boundaries. Independent services are useful only when their benefits justify that operating work.