The strangler pattern is used in scenarios when you're migrating from monolithic systems by extracting pieces of functionality and moving that functionality into new services.
As more and more functionality gets replaced by the new services, the old monolith is becoming smaller and the collection of new services replacing the functionality is increasing. You're strangling the old system, using it for support while you're developing new services, and once your new services are implemented, the old system becomes obsolete and you can get rid of it.
The name for this pattern comes from the strangler fig tree. The strangler fig tree can live without having any roots and starts growing atop of other trees. It grows the roots downwards and envelops the host tree. At some point the original support tree dies, and the strangler fig tree takes its place.
Translating this to software - the idea is to have the new system or service be supported by the existing system. Both old and new systems coexist and once the new system is ready, it can take over and replace the old system.
The key benefit of the strangler pattern is to allow you to do incremental changes to the new system. Since the old system keeps running while you're making changes, you can stop or pause your migration at any point, without impacting the old system. During the migration the traffic continues to be served by the old system.
The strangler pattern works best for the scenarios where you can easily intercept the calls before they reach the functionality inside the monolith. For example, if the functionality you're trying to extract is exposed from the monolith through an API (e.g.
/invoices), then the strangler pattern is a good fit. However, if the functionality is buried deeper inside the monolith and not exposed from it, the strangler pattern might not be a good fit.
There are three steps involved when implementing the strangler pattern.
1. Identify the functionality
In the first step, you are identifying the part of an existing system you want to move out of the monolith. As part of this step, you should also place a proxy between the monolith and your gateway or the UI. This proxy can be any piece of software you can configure to route the traffic from one endpoint to another - we will use this proxy to eventually route the traffic from the monolith to the new service. At this point though, this proxy is just passing the calls through to the monolith.
2. Move the functionality
Once you have identified the functionality and you have the proxy in place, you can start extracting the functionality from the monolith and putting it into the new service. You can also break this step into multiple smaller steps. At first, you can only implement a service skeleton and return HTTP 501. Once you have that you can deploy the service to production, but don't release it. Deploying simply means that the service is running production, but it's not released and there's not traffic being sent to it. Doing this incrementally allows you to set up the CI/CD pipelines, ensure sure you have all metrics flowing, and also test this new service, without impacting the existing functionality.
3. Redirect the calls
Once you have fully implemented and tested the new service you can update the proxy configuration and redirect the calls from the monolith to the new service.
The strangler pattern is useful when you are extracting functionality from the monolith that can be easily intercepted at the edge of the monolith. By putting a proxy in place you can switch the calls from the monolith to the new service (and vice-versa) with a simple configuration change.
For functionality that is deeper inside the monolith and can't be intercepted at the edge, you can look at the branch by abstraction pattern.