Insights / Production Engineering
Microservices: What Should You Split, and Why?
Decide when microservices are worth the operating cost, choose clear data boundaries and extract one capability with a tested recovery plan.

Loading insights
Loading insight article
Insights / Production Engineering
Decide when microservices are worth the operating cost, choose clear data boundaries and extract one capability with a tested recovery plan.

When releases become slow or one part of an application struggles under load, splitting the system can look like the obvious next step. Sometimes it helps. Sometimes it moves the same dependencies across a network and makes them harder to debug.
Microservices are independently deployable services with defined responsibilities and interfaces. Their value comes from useful independence: a team can change, scale or operate a capability without coordinating every neighbouring release. That value has to pay for additional deployments, network failures, data coordination and production support.
This guide helps product and engineering teams decide what deserves a separate service, what should remain together and how to test a first extraction. It uses a fictional legal-document application as a running example; the principles apply to other sensitive B2B products.
“The application is too big” is difficult to act on. “Document conversion queues delay interactive requests” is a specific problem with several possible solutions.
Examine release history, incidents and workload patterns. Are changes blocked by shared deployment, slow tests, unclear ownership or an unreliable dependency? A service boundary addresses only some of those problems.
Scroll horizontally to view all columns.
| Observed problem | Investigate first | Evidence that separation may help |
|---|---|---|
| Slow test runs | Test isolation and module dependencies | A stable capability can build and release independently |
| Expensive bursts of background work | A queue and separately scaled workers | The workload needs its own operating profile |
| Teams wait on one another | Ownership and interface decisions | A team can own a capability without frequent joint changes |
| One dependency causes broad incidents | Timeouts and failure containment | A separate boundary can contain a specific failure path |
| Cross-module changes are difficult | Domain boundaries and transaction needs | A coherent capability has few cross-boundary invariants |
A modular monolith is a single deployable application with deliberate internal boundaries. It can remain the right choice for a product whose features and transactions change together. A separate worker may solve a resource problem without creating a new business service.
Microsoft’s microservices overview describes both independent deployment and the operational complexity that accompanies it. Use that trade-off to assess a particular constraint, rather than setting a target number of services.
A useful boundary contains rules and records that belong together. Splitting controllers, validation and database access into separate services usually leaves one feature dependent on all of them.
In a fictional document application, matter management owns the matter’s lifecycle and access relationships. Document processing might own conversion jobs and processing results. Search serves a derived view for retrieval. Those are different responsibilities even if the same document identifier appears in each.
Before extracting anything, write down what each capability owns, what it must ask another owner and what it may only copy as a read model. A read model is a derived view optimised for reading; it is not automatically the authority for changing the underlying fact.
Scroll horizontally to view all columns.
| Capability | Owns | Must not silently take over |
|---|---|---|
| Matter management | Matter status and authorised membership | Processing job internals |
| Document processing | Job progress, conversion result and processing version | Matter access decisions |
| Search | An index with source and freshness information | The authoritative document or access record |
Microsoft’s domain analysis guidance uses bounded contexts to separate business meanings. For a smaller team, the immediate benefit can be a better internal module design. The analysis does not require deploying every context as a service.
A candidate needs more than an API endpoint. Name the team that owns changes, incidents, dependencies and data repair. List callers, scheduled jobs, reports and administrative scripts that touch the same records.
Ask what happens when the proposed service is unavailable. Can the rest of the product continue usefully? If every screen must synchronously call it, separation may create a new critical dependency rather than meaningful isolation.

For the sample application, users could still open matter records while conversion jobs wait. The interface would show that a document is processing. That is a plausible containment boundary. If conversion instead occurs synchronously inside every page request, the interaction needs redesign before extraction can provide that benefit.
Moving code into another deployment does not create independence if both applications still write the same tables. An undocumented database join can be a tighter dependency than a documented API.
Each business fact needs a clear write authority. Physical database separation is a deployment decision; ownership, access restrictions and contracts establish the logical boundary. A shared database server may host separate stores, while an apparently separate database can still be tightly coupled through copied schemas and coordinated writes.
In the sample product, the processing service receives a scoped document reference and produces a versioned result. It cannot change matter membership. The application must recheck permission before returning the result to a user, including when it comes from a cache or search index.
Microsoft’s data guidance explains the consistency challenges when services manage their own data. Identify which facts must change together in one transaction. If a proposed split makes a frequent, essential invariant difficult to maintain, reconsider the boundary.
For multi-tenant products, carry organisation and record identity through requests, jobs and events, then verify them at each access point. A tenant ID inside a message is an input to validation, not proof of authority.
A synchronous call asks another service for an answer now. It needs a timeout and a defined response when the dependency is slow. A queue accepts work for later. An event announces something that happened. These are different contracts, even if they use similar infrastructure.
Scroll horizontally to view all columns.
| Interaction | Appropriate when | Failure question to answer |
|---|---|---|
| Request and response | The caller needs an immediate result | Can it fail safely or use an acceptable fallback? |
| Queued command | A named owner can complete work later | Who retries, cancels and resolves abandoned jobs? |
| Event | Other capabilities react to a recorded change | How are duplicates, delays and old versions handled? |
| Derived read model | A screen can tolerate bounded staleness | How does it show freshness and recover missing updates? |
Avoid building a long chain of required calls for a simple user action. Each dependency adds another way for the action to fail or miss its latency budget. Decide which work belongs in the immediate response and which can continue afterwards.
Use distributed traces to follow an operation across services. OpenTelemetry explains traces as connected spans that describe a request’s path. Include useful identifiers and timing, while keeping document content and other sensitive payloads out of routine telemetry unless explicitly required and protected.
A local transaction can commit a database change atomically. A workflow involving several services can stop after only some steps have succeeded. Your design needs to describe that state, not simply retry everything.
If a service must update its own data and publish an event, an outbox can store the intended event in the same local transaction. A separate publisher delivers it. This closes the gap between committing the change and remembering to publish, but duplicate delivery still needs handling.
For repeated commands, check whether the receiver can identify the same operation and return a consistent result. AWS’s idempotency guidance explains why a stable request identity helps make retries safer. Do not assume every external API offers that behaviour.
Some completed actions need compensation: a later business action that addresses an earlier effect. Compensation is not a database rollback. A sent email, disclosed document or external commitment cannot be erased by reverting a deployment. Keep consequential steps behind appropriate checks and record what a recovery process can actually undo.
Choose a narrow candidate with understandable callers and data. Establish an internal interface first, then prove it can work behind a separate deployment. This lets the team test the boundary before changing every consumer.
The strangler fig pattern supports incremental replacement through a routing boundary. Applied to the fictional conversion capability, a controlled slice of eligible jobs can reach the new processor while other work stays on the existing path.

Scroll horizontally to view all columns.
| Step | Evidence before continuing |
|---|---|
| Record the baseline | Existing behaviour, workload and the specific constraint are documented |
| Create the seam | Callers use an explicit interface with behaviour checks |
| Compare safely | Outputs can be compared without duplicate side effects |
| Route a limited slice | Eligibility, ownership and failure handling are visible |
| Test return and repair | Routing can change back and changed data can be reconciled |
| Review the result | The constraint improved without unacceptable new operating work |
Avoid uncontrolled dual writes during migration. Name the write authority at every stage, including the transition. Define how new data is copied back or reconciled if traffic returns to the earlier implementation.
Every service adds operating responsibilities: deployment, configuration, secrets, dependency updates, access controls, monitoring, backups where applicable and an incident route. Reuse platform conventions so each extraction does not become a separate infrastructure project.
Set a service-level objective that reflects the user-facing workflow, then monitor the dependencies needed to meet it. For queued work, queue age and completion delay may matter more than HTTP response time. Test slow consumers, poison messages and unavailable downstream systems.
Backups need a recovery exercise. Check whether restoring one service leaves it inconsistent with events or data retained elsewhere. Include retention and deletion obligations in derived indexes, queues and replicas; removing the primary record may not remove its copies.
For AI product development, isolate model or document workloads where there is a concrete need, while keeping domain ownership clear. A model call is not automatically a microservice. The prototype-to-production article covers related delivery gaps.
A useful review can end in three ways: improve the current modules, separate a specific worker or dependency, or extract a business capability. Each is a legitimate outcome if it addresses the observed constraint.
Write down the chosen boundary, alternatives, expected benefit, operating owner and conditions for reconsideration. If extraction proceeds, define a first limited release and an explicit stop condition. A smaller diagram is valuable when it gives the team a system it can change and operate with confidence.
Share the product constraint and the boundary you are considering. I can help review the data, dependencies and a limited first release.
Discuss your architecture(opens in new tab)No fixed milestone makes them necessary. Reassess the product’s release constraints, workload and ownership as it grows. A modular application with targeted workers can remain suitable when it meets those needs.
It can be a candidate when jobs are asynchronous, resource needs differ and inputs and outputs are clear. Check access controls, file handling, retry behaviour and operating ownership before choosing it. The example here is not a universal recommendation.
They can, depending on the requirements. The key question is who may read or write each store and how changes are coordinated. Sharing tables and depending on private schemas undermines independence even when deployment units are separate.
No. Containers, managed application services and other deployment options can support separate services. Choose an operating platform the team can support and that meets the workload’s requirements.
You need more than a traffic switch. Check contract compatibility, data authority, changed records and external effects. Test how work returns to the earlier route and how any differences are reconciled.
Compare the original constraint with the result: independent releases, a contained failure or a justified workload improvement. Include incidents, support effort and infrastructure cost. Service count does not establish success.
Tell me about the system or workflow you are working on.
30-minute intro call on Calendly