Many product organizations have well established and mature products that generate a lot of value , however their traditional monolithic design and tightly coupled architectures mean that the release cycles are long with complex inter dependencies. The architecture and designs though stable are dated in terms of today’s technological needs and changes.
Do these problems sound familiar to you ?
1. Your product has long , 12-18 month product releases.
2. More than a dozen scrum teams are trying to deliver one product release by working together
3. Lots of interdependencies between components and teams
4. Long cycle of Integration and Regression testing towards the end of the cycle after feature completion.
5. A production Severity 1 defect, usually causes severe disruption to more than one team. Finding out which component is at fault takes days of debugging.
6. The teams are adopting Agile and Scrum but finding it difficult to deliver working software in every sprint despite heroics.
7. The only way to get on to the cloud, is to host the entire monolithic product on to a single virtual machine and spin out new virtual machines for every new customer.
8. Rewriting the architecture is extremely disruptive and nobody is willing to fund it.
If these problems sound familiar , you might find it valuable to read on.
First of all, monolithic Applications are not necessarily bad. Ebay, Twitter , Amazon all started with Monolithic architectures and later transformed to more modular & micro service based architectures. Most startups begin with Monolithic architectures and later figure out how to scale.
The good news is that many of the contemporary successful software product companies in the world have already figured out how to make this transformation. It is a matter of learning from their experiences and applying them. Let us look at some specific steps:
1. Adopt a Cloud-Native approach and specifically focus on Functional decomposition. An approach that involves creating highly cohesive loosely coupled sub systems that align closely to business functionality.
2. The move to a decoupled architecture will not happen in one go or one release and evolves best over phases, Probably one component at a time.
3. Start by Identifying features/components that can be decoupled and function as a service. Once a component is identified for decoupling we should focus on:
> Asynchronous standardized communication between the component and the rest of the product
> Storage is local to the component. Shared storage creates dependencies between components.
> Provide and publish a standard API using which other components can connect and make use of this service. The only way to connect to a service should be via its API. There are no backdoor connections.
4. Once a component is available as a service , we can gauge how other components are using it and align accordingly based on their requirements.
5. Once this exercise is successful , Pick a new component in the next iteration to convert into an independent service
By adopting the above strategy, we eventually create components that are completely self reliant and offer a unique and valuable service to other components within the product. The team that owns a service, owns it end-to-end and is completely accountable while being able to maintain a certain level of autonomy in terms of the internal technology choices on how to build their service and scale it. Automation also becomes easier as the team has complete control and any external services can be virtualized. Lastly but importantly, The team can work in a truly Agile manner.
We have only scratched the surface on topic in this article. To Dig deeper , Here is some useful further reading and viewing to understand better on how to move a product from Monolithic to Microservices architecture.