Monolith → Microservices via Strangler Fig
Very HighIncrementally extracting domains from a monolith into independently deployable services behind an API gateway using the strangler fig pattern: routing specific endpoint sets to new services while the monolith handles the remainder, until the monolith is replaced.
Topology Changes
From
Monolithic Application
To
Microservices with API Gateway
Topology Mutations
An API gateway (nginx, Kong, AWS API Gateway, or custom) is placed in front of the monolith. Initially passes all traffic through to the monolith unchanged. As services are extracted, the gateway routes specific path prefixes or endpoint sets to their respective service.
Operational Impact
API gateway becomes a critical path component: its failure affects all traffic. Requires health checking, circuit breakers, and rollback routing for service failures.
A clear service boundary is established at each extracted domain. The service owns its own process, deployment pipeline, and database. Cross-domain calls that previously were in-process function calls become network calls.
Operational Impact
In-process function calls had zero latency and shared transactions. Network calls add 1–10ms per hop and cannot participate in the calling service's database transaction.
Each extracted service owns its own database schema: no shared tables with other services. Cross-service data references that previously used foreign keys become eventual consistency references resolved at the application layer.
Operational Impact
Data that was previously queryable via JOIN is now owned by separate services. Cross-service queries require either API calls (N+1 risk) or async denormalization via events.
Operations that previously ran within a single database transaction now span service boundaries. Two-phase commit is impractical at service scale: eventual consistency via saga pattern is required.
Operational Impact
Business operations that previously atomically updated multiple tables must now be designed as sagas with compensating transactions for rollback. Partial failures become visible to users.
Migration Stages
Audit the codebase for domains with clear ownership boundaries, low coupling to other domains, and a team or business driver for extraction. Score candidates by: number of cross-domain dependencies, data sharing surface area, and team ownership clarity. Reject candidates with deep cross-domain foreign key dependencies until those can be untangled.
Deploy the API gateway in front of the monolith with all traffic forwarded unchanged. Zero change to application behavior. Validate that latency overhead is acceptable (typically <2ms added per request). This establishes the routing infrastructure before it is needed.
Extract the lowest-coupling, highest-team-ownership candidate domain into its own service. Provision its database. Implement dual-write from monolith to both old monolith tables and new service (to allow rollback). Route new traffic to service. Run both paths in parallel until confidence is established.
Run shadow traffic comparison: requests hit both monolith path and new service path, responses compared for parity. Identify discrepancies and resolve before cutover. Cut over routing in the API gateway for the extracted domain's endpoints.
Apply the established extraction pattern to each additional candidate domain. Each extraction becomes more predictable as the pattern matures and tooling is reused. Monitor the monolith's surface area shrinking over time.
Migration Risks
Operations that previously ran in a single database transaction now span services. A failure partway through a multi-service operation leaves data in a partially updated state. Without saga compensation logic, this creates permanent data inconsistencies.
Mitigation
Design sagas with explicit compensation steps before extracting any domain that participates in multi-table write operations. Test failure injection: kill the second service mid-saga and verify the compensating transaction fires and leaves data consistent.
Each extracted service adds operational surface: its own deployment pipeline, health checks, on-call runbook, and failure domain. Operational complexity grows with service count. Teams underestimate the platform investment required to run N services reliably.
Mitigation
Build a shared service template (containerization, logging, tracing, health check endpoints) before extracting the first service. Do not extract a second service until the first has been stable in production for 30+ days.
Cross-service queries that replace database JOINs via API calls create N+1 query patterns. A page that previously fetched 100 user records with a single JOIN now makes 100 API calls.
Mitigation
Identify all JOIN-equivalent data access patterns before extraction. Implement batch APIs and async denormalization via events for cross-service data access. Do not accept N+1 patterns as a necessary cost of microservices.
Coupling Changes
Each extracted service can be deployed independently of the remaining monolith
Consequence
Teams owning extracted services gain deployment autonomy; monolith deployments still require coordination
Services depend on each other via network: downstream service slowness degrades upstream services
Consequence
Circuit breakers and timeout budgets become mandatory operational configuration rather than optional
Schema-level coupling (shared database) is replaced by API-level coupling (service contracts)
Consequence
API versioning and backward compatibility become explicit concerns; schema migrations no longer affect all services
Consistency Model Changes
- ·Single-service operations remain strongly consistent within each service's database boundary
- ·Cross-service operations are eventually consistent: saga execution may take seconds to minutes to reach final state
- ·There is no global transaction coordinator: partial failure is a design constraint, not an error to be handled
- ·Idempotency must be designed into all service APIs: network retries will re-deliver requests
Rollback Risks
- ·API gateway routing configuration changes are fast to revert but the monolith code for the extracted domain must still exist
- ·Once dual-write is removed and the monolith's data is no longer updated, rolling back requires re-seeding from the service database
- ·Data that has been migrated to a per-service database cannot be rolled back to the monolith schema without a full data migration