The Slow Fade
Once you have your Intercepting Proxy, your new Microservice, and your Data Synchronization in place, you are ready to strangle. This is where the pattern earns its name — the gradual transfer of life from the old system to the new.
Phase 2a: Deploy Dark (Shadow Mode)
Deploy the new service to production but send zero real user traffic to it. Instead, use the proxy to mirror (also called "shadow") traffic: send a copy of real requests to the new service, but discard its responses. Compare the new service's responses to the monolith's responses to find discrepancies. This validates correctness under real production load without any user impact.
# NGINX traffic mirroring
location /api/userprofile {
proxy_pass http://legacy_monolith; # Real response comes from here
mirror /mirror_userprofile; # Copy of request sent here (response discarded)
mirror_request_body on;
}
location = /mirror_userprofile {
internal;
proxy_pass http://new_user_service$request_uri;
}
Phase 2b: Canary Release
Configure the proxy to send a small percentage (1-5%) of real user traffic to the new service. Monitor everything:
- Error rates (5xx responses)
- Latency (p50, p95, p99)
- Business metrics (are users completing the same actions successfully?)
# NGINX weighted upstream for canary
upstream userprofile_backend {
server monolith.internal:8080 weight=95;
server user-service.internal:3000 weight=5;
}
Phase 2c: Ramp Up
If metrics look healthy, increase traffic: 10% → 25% → 50% → 75% → 100%. Each increase should soak for at least 24-48 hours to catch time-dependent issues (batch jobs, timezone-related bugs, weekly traffic patterns). Never ramp up during a Friday afternoon or before a holiday.
Phase 3: Retire
Once 100% of traffic is hitting the new service and it has been stable for a defined period (typically 2-4 weeks):
- Stop the CDC pipeline for this slice (if data sync is no longer needed)
- Remove the routing rule from the proxy (simplify configuration)
- Delete the old code from the monolith's codebase
- Drop the old database tables (after a verified backup)
- Update documentation and architecture diagrams
- Celebrate. The team needs to feel the win.
Rinse and repeat this process for the next piece of functionality until the monolith is gone.
Key Point: The "retire" phase is where discipline matters most. Teams often leave dead code in the monolith because "it's not hurting anything." But dead code increases cognitive load, confuses new team members, and can accidentally be re-activated. Treat code deletion as a first-class deliverable, not an afterthought. Some teams track "lines of legacy code deleted per sprint" as a migration progress metric on their team dashboard — making the invisible work visible to stakeholders.