As architects help enterprises modernize their core capabilities and transition to modern systems as part of digital transformations, the strangle pattern is a useful pattern in the architect’s repertoire. The idea is to slowly drain the life out of a legacy application by replacing legacy services and technical debt with a modern implementation. As a design pattern it can be applied to software development projects, cloud architecture, monolith applications moving to microservices, enterprise integrations, and beyond. This article will go beyond just describing the pattern with a fancy diagram and actually dive into how this pattern can actually be used in practice for effective modernization strategies of legacy systems.
The concept of the strangulation pattern is the same regardless of the type of project and takes a phased approach that is implemented over time allowing you to iterate from a current state, to multiple interim states, and finally a target state which includes completely removing the legacy system from the enterprise.
The premise of the strangle pattern is that you create a facade to proxy requests to legacy services or applications in which all current client implementations will access. Part of this means that all existing clients get moved over to use the new facade and simultaneously direct access to the legacy system or service is blocked except for requests coming in through the facade. This facade could be in one of many different forms, but the idea is to have a pass through proxy which takes inbound requests and forwards them on, mostly untouched, to the original and legacy backend.
Let’s use an example to demonstrate how this looks in practice. Take a retailer or a manufacturer as an example. Let’s imagine that this enterprise uses a single software solution that handles different sets of capabilities related to product management, inventory, and vendors. This entire bloated piece of software is slated for replacement over time, but how do we get there?
The first step will be to institute the facade and ensure all traffic is now flowing through the facade to the legacy system. If there are multiple ways of accessing the data in the legacy system and clients are actively using these different ways, then all of these interfaces need to go through a facade. The architecture could include refactoring to have one single source for each service endpoint or you may end up with facades covering different types of system access.
In this example, an API management layer is used as a facade in order to access a legacy systems SOAP web service end points.
As you start to separate the capabilities and offload the functionality from the legacy systems to new modern systems, you can re-route the outbound requests away from the legacy systems and to the new systems.
As you change out the backend, your facade still acts as the primary endpoint for service requests and it takes care of routing the outbound request appropriately and this can be done transparently with little impact to the clients using it.
As time progresses, this is iterated upon with each new incumbent system, and eventually you get to a point where the legacy system can be successfully retired.
A caveat to the happy path scenario above is that if you are dealing, like in this case, with enterprise software and not software developed in-house, you have no control over the contracts or interface specifications of the new modern system. It may not even look like anything close to the original legacy systems interface, and that presents some additional challenges.
If this was custom developed software and you were migrating a monolithic application to a set of new microservices you could plausibly (and probably should) use the existing contract or service specifications to make a completely new compatible interface that has a compatible spec with the legacy service. Your new service would then interface and orchestrate a set of microservices instead of the monolith while keeping 100 percent backward compatibility with existing clients and allowing the facade to continue as a pass through proxy without any transformation or adaptation.
But, in the case of enterprise software, you will need to provide some kind of translation between the facade and the new system in order to ensure that old clients are still compatible with the new system. How and when this happens is a significant decision that has to be included as part of the architecture. It may or may not be feasible to define a common contract or specification for an endpoint upfront at the start of the project and migrate legacy components to that prior to even moving to the new solution. You may even end up with a set of adapters for legacy systems and new modern APIs to be used by newer clients with the intent to move over legacy clients to the new interfaces in the future. Even with this approach, you’ve successfully pushed out a legacy system and brought in a new modern system with minimal impact to existing clients. How you approach it will depend on many factors.
It is important to carefully consider how any transformation happens and if any adapters are used as part of the architecture to support the older integrations. Although you may be keeping backward compatibility with existing clients you may inadvertently be adding new problems for existing clients such as impacting quality of service and performance due to new overhead. This needs to be considered carefully as part of the architecture and mitigated to ensure that there are no unintended consequences as a result in the shift to a more sustainable architecture that modernizes legacy systems.