Separate modularity from deployment
A modular monolith divides the code into domains with clear interfaces, while the system is deployed as a single unit. Microservices also split the units of deployment. Either approach can be well organized or a mess; the number of services is not, on its own, a measure of design quality.
The practical question is how much independence you actually need. If two parts change together and rely on the same data, splitting them early can add coordination overhead. If one part needs a different deployment cadence or scaling profile, separating it is worth considering. The decision should rest on a need you can articulate.
Draw boundaries around the business work
Service boundaries can be built around business capabilities. AWS documentation describes decomposing by business capability and stresses that the approach requires an understanding of the business. That is why it matters to involve domain experts, rather than just splitting services by layers such as screens, tables and integrations.
In an ordering system, for example, the catalog and billing may be separate domains. Before splitting them, you need to understand who holds the state of the transaction and what happens when a payment succeeds but the order update fails. This is a design scenario, not an automatic recommendation to split every ordering system.
Account for the added operational work
Every independently deployable unit needs a way to be built and monitored, plus secrets management and incident handling. Interfaces between components also become contracts that have to be managed over time. Do not assume the team already has all of these capabilities just because the cloud makes it quick to spin up a service.
- Is there a proven need to deploy this domain independently?
- Who owns an incident that spans more than one service?
- How are contracts and events versioned?
- How does the system behave when only some services are available?
When to start with a single unit
With a small team or a domain that is still evolving, you can build clear boundaries within a single deployment unit and test them as you go. Separate responsibilities, restrict data access and define interfaces, and document where dependencies are intentional. This lets you learn before also committing to an operational split.
The choice is not a lifelong commitment. Define signals that would justify revisiting it: releases delayed by coordination, differing availability requirements or independent team ownership. Without such signals, a broad migration can turn into a project with no clear business outcome.
Decide, and keep a path for change
Write a short decision record covering the context, alternatives, benefits and costs. If you choose to split, pick one domain and use it to rehearse deployment, failure and rollback. If you choose a modular monolith, establish how you will prevent every part from directly accessing all data.
The first step is to map three core processes and identify which parts change together. Boundary design can start there. A target number of services set in advance is no substitute for that information.