Corrected 24 September 2026: removed unsupported adoption and cost statistics, replaced missing illustrations with a comparison table, and clarified architectural trade-offs.

Choose boundaries around a concrete problem

Microservices let a team deploy and scale parts of an application independently. They also introduce network calls, separate deployments and more operational work. A modular monolith keeps explicit boundaries inside one deployed application. Neither choice guarantees lower cost or better reliability.

Microsoft's architecture guidance describes both benefits and challenges, including data consistency, testing and network latency. Failure isolation depends on callers handling unavailable dependencies; separating a process does not automatically prevent cascading failures.

Compare the operating model

Modular monolith and microservices: practical trade-offs
DecisionModular monolithMicroservices
DeploymentModules ship together in one application.Services can ship separately when contracts remain compatible.
ScalingScale the application or separate background workers.Scale selected services to match their workloads.
Data changesA shared transactional database can simplify changes across modules.Separate data ownership requires explicit coordination across services.
DebuggingFewer network boundaries to trace.Correlated logs, metrics and distributed tracing become more important.
Team ownershipOne deployment can suit a small team with shared responsibilities.Independent services need clear maintenance and incident ownership.

Start with a decision record

Martin Fowler's Monolith First argues that starting with a monolith can help teams discover domain boundaries before distributing them. It is an architectural argument based on experience, not a universal rule or a measured adoption rate.

Our suggested decision record has four questions: Which measured bottleneck are we fixing? What must be deployed independently? Who operates the new service? What happens when it is unavailable? If the answers are unclear, improving module boundaries inside the existing application is a useful first step.

Plan data changes and failure recovery

Splitting a workflow across databases changes its failure modes. A local database transaction does not automatically cover a second service. The saga orchestration pattern coordinates local transactions and compensating actions, but adds retry and consistency considerations. A refund or reservation release is business behavior that must be designed, not a generic rollback button.

When a database change also needs to publish an event, the transactional outbox pattern addresses the risk of one write succeeding while the other fails. Consumers still need to handle duplicate delivery.

An illustrative AI workload

Consider an application whose document-processing jobs require GPUs while its account pages run on ordinary web servers. Separating the processing worker may allow independent capacity and deployment. That does not require turning account management, billing and every other module into separate services. This is a hypothetical design example, not a reported customer result.

Define job ownership, timeouts, retry limits and the user-visible state when processing fails. Record queue delays and failed jobs before deciding whether another service boundary would help.

Measure a small extraction before expanding

  1. Record current latency, deployment frequency, incident effort and operating cost.
  2. Choose one boundary with a clear owner and a reversible rollout.
  3. Define its API or event contract and test dependency failures.
  4. Compare the result with the baseline, including engineering and support time.

Use that evidence to decide whether to continue. This article makes no general claim about adoption percentages, reversal rates or guaranteed cost savings.