Article

14min read

Migrating from Monolith to Microservices: How do Feature Flags Fit in?

If you’re looking to get started on building an application, you may be wondering whether to design it as a monolith or build it as a collection of microservices. In fact, this has been a long-standing point of debate for many years among application architects.

So what is the difference between these two architectures and how do you decide which one to choose and which one is best for your organization?

While monolithic architectures have been used for many years, microservices seem to be taking over as it’s becoming a key driver of digital transformation.

Indeed, in a world where speed and agility are more important than ever, you may find that switching over to the more versatile microservices approach to build applications that are quicker to create and deploy the go-to-strategy to remain competitive and to be able to continuously deliver software without delay.

In this post, we will investigate the above questions by comparing monolithic and microservices application architectures to help you in your decision. We will also explain, since moving to microservices might be a risky endeavor, how feature flags may help reduce some of that risk.

Monolithic vs Microservices

Monolithic architecture

Before we move on to the migration process, we will quickly go through the definitions of these architectures and why one may take precedence over the other.

By definition, a monolith refers to a “large block of stone”. In the same way, a monolithic application is an application made up of one piece or block built as a single indivisible unit. 

In that sense, in a typical monolith application, code is handled in one single, tightly knit codebase and so data is stored in a single database. 

Although this type of application is considered to be the common and traditional method to build applications, it may cause some major problems and over time may become unmanageable. 

The image below illustrates the makings of this architecture, which consists of a client-side user interface, server-side application and a database. They all function as a single unit and so changes are made in the code base and require an update of the entire application.

Monolithic Architecture Diagram
Source

Below, we will list some of the difficulties and drawbacks associated with this architecture, which prompts many to move to microservices.

Drawbacks of monolithic applications

  • Less scalability- components cannot be scaled independently; instead, the whole application will need to be scaled, not to mention that every monolith has scalability limitations. 
  • Reliability issues- given how the components of a monolithic application are interdependent, any minor issue may lead to the breakdown of the entire application.
  • Tight coupling- the components of the application are tightly coupled inside a single execution meaning that changes are harder to implement. Furthermore, all code changes affect the whole system, which could significantly slow down the development process.
  • Flexibility- with monolithic applications, you will need to stick to a single technology as integrating any new technology would mean rewriting the entire application which is costly and time consuming.
  • Complexity- as a monolithic application scales up, it becomes too complicated to understand due to how the structure is tightly connected and becomes even harder to modify that eventually it may become too difficult to manage the complex system of code within the application.

Despite its drawbacks, monoliths do offer some advantages. Firstly, monolithic applications are simple to build, test and deploy. All source code is located in one place and can be quickly understood. 

This offers the added advantage when it comes to debugging. As code is one place, any issues can be easily identified to be fixed.

As already mentioned, a monolithic approach has been in existence for a long time and since it’s become such a common method for developing apps, this means that engineering and development teams have the sufficient knowledge and skills to create a monolithic program.

Nonetheless, the many disadvantages of monolithic architecture has led to many businesses shifting to microservices.

Microservices architecture

Unlike a monolithic architecture, microservices architecture divides an application into smaller, independent units and breaks down an app into its core functions-each function is called a service. 

Every application process is handled by these units as a separate service and each service is self-contained; this means that in the event that a service fails, it won’t impact the other services.

In other words, the application is developed as a collection of services, where each service has its own logic and database and the ability to execute specialized functions. The following image depicts how this architecture works:

Microservices Architecture Diagram

You can look at each microservice as a way to break down an application into pieces or units that are easier to manage. In the words of Martin Fowler:

“In short, the microservice architectural style [1] is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API.”

In other words, microservices architecture is a way to design software applications as suites of independently deployable services that communicate with one another through specific methods, i.e by using well-defined APIs.

Microservices: The answer to accelerated application development and time to market?

More distributed systems architectures such as microservices are increasingly replacing the more traditional monolithic architecture. One of the main reasons is that systems designed with microservices architecture are easier to modify and scale.

Due to its distributed nature, developers can develop multiple microservices simultaneously. 

Since services can be deployed independently, each service is a separate codebase that can be managed by a small development team, as can be seen in the image below, which illustrates the major differences between these two architectures: 

Migrating monolith app to microservices
Source

This results in shortened development cycles so releases are ready for market faster.

Microservices, as a result, are used to speed up the application development process as this type of architecture enables the rapid delivery of large, complex applications on a frequent basis. 

Moreover, since these services are deployed independently, a team can update an existing service without redeploying the entire application unlike monolithic architecture. This makes continuous deployment possible. 

This also makes these types of applications less risky to work with than monolithic applications. Risk mitigation, then, is one of the key drivers for adoption of microservices.

This makes it easier to add new changes or functionalities to it than to a monolithic program. This means that updating the program is more straightforward and less troublesome.

With monolithic applications, even the most minor modifications require redeployment of the entire system and so feature releases could be delayed and any bugs require a significant amount of time to be fixed.

Thus, microservices fits within an Agile workflow as using such an approach makes it easier to fix bugs and manage feature releases. You can update a service without redeploying the entire application and roll back if something goes wrong.

Not to mention that a microservices architecture addresses the scalability limitations that come with monolithic architecture. Because of its smaller, autonomous parts, each element can be scaled independently so this process is more cost- and time-efficient.

Finally, each service can be written in a different language without affecting the other services. Developers are also unrestricted by the technology they choose so they can use a variety of technologies and frameworks instead of going for a standardized one-size fit all approach.

To sum up the differences…

The table below summarizes some of the major differences between the two architectures:

  Monolithic  Microservices
Deployment Simple deployment of the entire system  More complex as there are independent services which need to be deployed independently
Scalability Harder to scale; the whole system needs to be redeployed Each element can be scaled independently without downtime
Testing Easier to test: end-to-end testing Harder to test; each component needs to be tested individually
Flexibility Limited to single technology Freedom of choice of tech stack
Security Communication with a single unit and so security is handled in one place Large system of standalone services communicating via network protocols raises security concerns
Adoption  Traditional way to build applications so easier to implement and develop as developers possess necessary skills Specialized skills are required
Resiliency Single point of failure- any issue can cause a breakdown in the entire application A failure in one microservice doesn’t affect the other services

Tread carefully with microservices

In sum, a microservices architecture offers many advantages. Nonetheless, this type of architecture may not be suited for all companies so a proper evaluation will need to be made to choose the best approach for them depending on factors such as type of product or audience.

As a result, before moving onto the migration process, it is important to proceed carefully before attempting this migration as a microservices architecture is not without its cons. 

Among some of the drawbacks of microservices include:

  • We’ve already mentioned how monolithic architectures have been used for a long time that many engineering teams have the knowledge and experience to create a monolithic program. Meanwhile, building a microservice application without the necessary skills could be a risky endeavor as a microservice architecture is a distributed system and so you would need to configure all the modules and database connections.
  • Just a monolithic application could become complex with time, standalone services that make up a microservice application could also lead to high developmental and operational complexities.
  • Because of the distributed system that makes up this architecture, testing such an application is more difficult because of the large number of deployable parts.
  • Debugging and deploying these large numbers of independently deployable components are also much more complex processes. (However, should any individual microservice become unavailable, the entire application will not be disrupted).
  • Testing, such as integration and end-to-end testing, can become difficult due to its distributed nature. This is in contrast to monolithic apps which consist of a single unit that makes it easier to run end-to-end testing.

In the end, transitioning to a microservices architecture will ultimately depend on the pain point you’re trying to solve.

You’ve got to ask yourself whether your current (monolithic) architecture is giving you trouble and whether actually migrating to microservices will help solve your issues.

Make the transition less risky: Feature flags and microservices

With the above in mind, DevOps teams might still want to make the transition from monolithic to microservices architecture due to its compatibility with Agile development workflows, that come with with lower risks and fewer errors.

During this process, teams will look to replace the old code and roll out the new code at once, which could be very risky.

Therefore, migration to a microservice-based ecosystem could turn out to be a challenging and time consuming process, especially for businesses with large and complex systems with monolithic architecture.

This is where feature flags come into play.

Feature flags are a great asset when it comes to releases and we’re not only referring to front-end releases but also when it comes to your architectural strategy.

Feature flags give you greater control over the release process by choosing when and to whom you will release products and features by separating deployment from release.

Thus, you can turn features on or off for certain users by simply wrapping them up in a feature flag without redeploying, lessening the risk associated with the release process.

Just as feature flags enable progressive delivery of features instead of a big bang release, the same idea applies when it comes to migrating to services: it’s best to do it one piece at a time instead of all at once. 

The main idea is to slowly replace functionality in the system with microservices to minimize the impact of the migration.

You would essentially be making small deployments of your microservices by deciding who sees the new service instead of going ahead with a big bang migration.

This will be preceded by analyzing your current system to identify what you can start to migrate. You can experiment with functionalities within your customer journey to start migrating and gradually direct traffic to it via feature flags away from your monolith and then slowly kill off the old code. 

There are other ways to go about the migration process- which often involve a roll out of the new code all at once- but feature flags lessen the risk usually associated with microservices releases through progressive rollout instead.

Split your monolith into microservices using feature flags

The key is to move from monoliths towards microservices in incremental ways. Think of it as if you’re untangling a knot that’s been tightly woven together and feature flags as the tools that will help you to gradually unravel this knot.

  • Start with identifying a functionality within your monolith to migrate to a microservice architecture. It could be a core or preferably an edge functionality such as a code that sends coupon or welcome emails to users in the case of an e-commerce platform, for example.
  • Proceed by building a microservice version of this functionality. The code that controls the functionality within the monolith will need to be diverted to where the new functionality lives, i.e within the microservice.
  • Then, wrap a feature flag around this microservice with the traffic going to the old version. Once the feature flag is turned on, the microservice code is turned on so you can direct traffic to the new version to test it.
  • Note that you should keep the existing functionality in place in the monolith application during the transition so you can then alternate between different versions or implementations of this functionality-the one in the monolith and the one in the new microservice.
  • If anything goes wrong, you will be able to revert traffic back to the monolith with the original functionality. Hence, you can switch between the two functionalities until you’re satisfied that the microservice is working properly.
  • Using a dedicated feature flag management tool, you can test the microservices to ensure everything is working as expected. Feature flags allow you to target certain users such as percentage rollouts (similar to a canary deployment), through IP address or whatever other user attributes you set. 
  • If no issues come up, then you can turn the flag on for more users and continue to monitor the microservice to ensure that nothing goes wrong as you increase the traffic to it.
  • Should anything go wrong, you can roll back by turning the flag off (i.e kill switch) and delete the old application code.
  • Make sure you remove the flag once you no longer need it to avoid the accumulation of technical debt.
  • Then, you will repeat this process with each functionality and validate them with your target users using your feature flag management tool.

Remember, the whole point is to create these microservices progressively to ensure things go smoothly and with feature flags, you further decrease the risk of the migration process.

This is based on the idea of the ‘strangler fig’ pattern

This term is inspired by a kind of plan, where in a similar way to the plant, the pattern describes a process of wrapping an old system with a new one, the microservice architecture, using an HTTP proxy to divert calls from the old monolith functionality to the new microservice.. 

This would allow the new system to gradually take over more features from the old system, as can be seen in the image below, where the monolith is ‘strangled’: 

Progressively decompose a monolithic application

In this scenario, a feature flag can be applied to the proxy layer to be able to switch between implementations.

Conclusion

Monoliths aren’t all bad. They’re great when you’re just getting started with a simple application and have a small team; the only issue comes from their inability to support your growing business needs.

On the other hand, microservices are a good fit for more complex and evolving applications that need to be delivered rapidly and frequently and particularly when your existing architecture has become too difficult to manage. 

There is no one-size fits all approach. It will eventually depend on the unique needs of your company and the capabilities of your team.

Should you decide to take the plunge and shift to microservices architecture, make sure that you have a feature management tool where you can track the flags in your system and how your features are performing.

AB Tasty’s server-side functionality is one such tool that allows you to roll out new features to subsets of users and comes with an automatic triggered rollback in case something goes wrong during the migration process. 

The most important takeaway is to carefully consider whether you really need to migrate and if so, why. You must evaluate your options and think about the kind of outcome you’re hoping to achieve and whether a microservices architecture provides the right path to this outcome.

You might also like...

Subscribe to
our Newsletter

bloc Newsletter EN

AB Tasty's Privacy Policy is available here.