Transferring from monolith to microservices
We are on the cusp of a revolution in application architecture. According to IDC (International Data Corporation), by 2022, 90 percent of all new applications will be based on microservices architectures.
Many enterprises are thinking about migrating their existing apps to microservices-based architectures. But there are many critical questions to ask first. How do you rearchitect an existing system without having to stop all other work on it? How big should a microservice be? When might microservices be a bad idea? What are some of the migration patterns you could adopt when splitting up a monolith?
Here are a few migration patterns you could follow to start your transformation journey from monolith to microservices.
- The idea here is to have our new system initially supported by, and wrapping, the existing system.
- The old and the new can coexist, giving the new system time to grow until it can potentially entirely replace the old system.
- This approach allows for incremental migration to a new system.
- The strangler fig approach also gives us the ability to pause and even stop the migration, while still taking advantage of the new system delivered so far.
- When implementing this approach for our software, we strive to not only take incremental steps toward our new application architecture, but also ensure that each step is easily reversible, reducing the risk of each incremental step.
Branch by abstraction
- This approach involves creating an abstraction for the functionality to be replaced.
- To use the new abstraction, you change clients of the existing functionality.
- With branch by abstraction, you create a new implementation of the abstraction with the reworked functionality.
- To use the new implementation, you switch over the abstraction.
- After cleaning the abstraction, you can remove the old implementation.
- Rather than calling either the old or the new implementation, with the parallel run approach, we call both. This allows us to compare the results to ensure they are equivalent.
- Despite calling both implementations, only one is considered the source of truth at any given time.
- Typically, the old implementation is considered the source of truth until the ongoing verification reveals that we can trust our new implementation.
- This technique can be used to verify not just that our new implementation is giving the same answers as the existing implementation, but also that it is operating within acceptable nonfunctional parameters.
- The decorator pattern allows you to attach new functionality to something without the underlying thing knowing anything about it.
- Using a decorator makes it appear that our monolith is making calls to our services directly, even though we haven’t changed the underlying monolith.
- Rather than intercepting these calls before they reach the monolith, we allow the call to go ahead as normal.
- Then, based on the result of this call, we can call out to our external microservices through whatever collaboration mechanism we choose.
Change data capture
- With a change data capture pattern, we react to changes made in a datastore rather than trying to intercept and act on calls made into the monolith.
- For a change data capture to work, the underlying capture system must be coupled to the monolith’s datastore.
- Change data capture is a useful, general-purpose pattern, especially if you need to replicate data.
- In microservices migration, the sweet spot for this approach is where you need to react to a change in data in your monolith, but are unable to intercept this at the perimeter of the system using a strangler or decorator and cannot change the underlying codebase.