Service extraction moves a coherent capability from an existing application into a separately deployed service. The new service receives requests through an explicit contract and owns the behaviour assigned to it. The original application may continue to handle the rest of the system while callers move in controlled stages.
What has to move
Copying classes into a new repository does not complete an extraction. The capability also depends on data, business rules, callers, scheduled work, permissions, and operational behaviour. Each dependency needs an owner on both sides of the new boundary.
| Concern | Before extraction | Required decision |
|---|---|---|
| Interface | Internal calls | Public contract and error behaviour |
| Data | Direct table access | Which component owns each write |
| Callers | Imports or local calls | Routing and migration order |
| Operations | Shared application runtime | Deployment, logs, and recovery |
The extracted service can use a different implementation, but its contract must preserve the behaviour that current callers still require.
Choosing a boundary
A candidate capability should have coherent rules and a boundary that the team can describe. A bounded context can provide that model boundary. A module with limited incoming and outgoing dependencies is usually easier to move than code used throughout the application.
An audit checks:
- Business cohesion. The behaviour serves one recognisable capability.
- Caller inventory. Every application, job, and integration that uses it is known.
- Data ownership. One component can become authoritative for each changed record.
- Contract stability. Requests, responses, and failure cases can be stated explicitly.
- Verification. Tests or runtime comparisons can confirm behaviour during the move.
These checks identify whether extraction is a practical migration step or only an architectural intention.
A staged extraction sequence
The team first places the capability behind an interface inside the monolith. Existing callers move to that interface while the implementation remains local. Next, the service is deployed and the interface redirects selected traffic to it. Data ownership moves according to a defined transition, and direct access from the old application is removed.
The Strangler Fig Pattern uses this type of routing to replace behaviour incrementally. A parallel path may support comparison, but write operations need a clear authority to avoid conflicting state.
What can block the move
A shared database often hides the hardest dependencies. Other modules may read or update the same tables, triggers may perform additional work, and reports may rely on the current schema. Extracting code while leaving unrestricted shared writes does not establish independent ownership.
A legacy codebase audit therefore maps the dependency graph, database access, and operational requirements before scheduling the move. The plan can then order contract creation, caller migration, data separation, and retirement of the old path. Service extraction is complete when the new service can change and operate within its stated boundary without relying on undocumented access to the original application.