Most of us have experienced the problem of picking the right moment to release a new feature; when will deploying the new version of the artifact have the least impact on the users of our application?
The first problem we faced was downtime. We wanted to minimize the time users were not able to access an application. This problem was solved by techniques such as ‘rolling deployments’, where we run multiple instances of our application and upgrade one instance at a time to the new version so we have no downtime.
How rolling deployments work, from https://searchitoperations.techtarget.com/definition/rolling-deployment
We further optimized this solution when we migrated to a microservice architecture by using rolling deployments on the microservice level. Using this strategy greatly improves the availability and reliability of an application because the risks are limited to a small part of the application.
Using this strategy, we can still have the following problems, both technological and functional:
- What happens when two versions of the application, with different functionality, are used at the same time (during rolling deployments)?
- What if we want to publish a feature at a different time than the new version is released?
- What if our feature depends on an API of an external supplier that is not ready yet?
- What if a feature is in our master branch, but we want to release an update of another feature right now?
- What if we want to publish a feature to only a certain (set of) user(s)?
- What if we want to enable a feature across multiple microservices at the same time?
There are various strategies to solve the questions raised above. You could choose to use green/blue deployments instead of rolling deployments to cope with the difference in functionality. You could create hotfix branches to work around the new feature on your master branch. Or you could use canary deployment to only publish features to certain users.
In this blog, I present a different solution to the problems posed above: feature toggles.
What are feature toggles?
Feature toggling is the art of toggling code/features on and off within your application. A feature toggle can be as simple as commenting out a certain line of code.
Example of a feature toggle, from https://martinfowler.com/articles/feature-toggles.html
In general you want the solution to be a little more sophisticated than this, since having your codebase riddled with comments like this makes it barely maintainable. In my next blog post I will dive into how we can solve this in a much better way.
Use cases for feature toggles
There are various use cases in which feature toggles can improve the behavior of your application and the processes in your development team.
Supporting branching strategies
Feature toggles can help support the branching strategy in your project. When using trunk-based development in your team(s), you should create feature branches and merge your feature branch as often as possible to the master branch (the trunk).
It is hard to do this without feature toggles since there is a (big) chance your feature will go to production even though it’s not finished. Feature toggles will deactivate your code so that the code will not run in production (and/or other environments).
When developing an application with a microservice architecture, you will often have to write code in multiple services. Chances are that when you finish a feature, it also depends on another service, and thus they need to be released in a certain order. This makes release management harder than it needs to be. By using the same feature toggle in multiple microservices, you can toggle functionality across your entire architecture, enabling you to release in any order.
Typically, we always run more than one instance of our application these days. This helps us achieve higher usability and enables us to use rolling deployments. One of the drawbacks of rolling deployments is that two versions of the application are deployed simultaneously for a short time. This could lead to unpredictable behavior if you’re not careful.
Utilizing feature toggles, you can enable a feature after all nodes have upgraded to the new version, thus keeping your application reliable.
Sometimes we want only a certain user, or a set of users, to be able to access a feature. We can achieve that by making the feature toggles aware of the user, thus enabling different functionality for them. Using these beta-testers in this way ensures your application works correctly when releasing the feature to the other users.
Types of feature toggles
There are different types of feature toggles, based on the context they are used in. Most of the time feature toggles should exist as short as possible (we will dive into the ‘why’ later), but in other cases you might want them to exist for longer periods of time. You might even want them to be there forever! Let’s take a look at the most common ones.
Release toggles are feature toggles that decouple deployment from the release of the feature. Toggles of this type should be short-lived since you will have to maintain the old code until the toggle is removed, even though it will never provide any business value anymore.
Ops toggles are feature toggles that ops can use to disable certain functionality in a crisis. They can be viewed as ‘manual circuit breakers’. These toggles can live a very long time in your application, but should always provide acceptable fallback behavior.
Experiment toggles are feature toggles that can be compared to release toggles, except that they are only enabled for a certain set of users. This set of users can be a predefined list of specific users or chosen at random. The experiment toggle should only exist until the feature is released to everyone, or it is decided the feature will not make it to the general public.
Drawbacks of feature toggles
No matter how cool feature toggles may be, they certainly have their drawbacks. They should always be considered seriously and should never be allowed to proliferate uncontrollably.
Introducing feature toggles increases the complexity of your application. You have to utilize an if-statement or strategy pattern to execute a different path in your code. If you do not remove the toggles when appropriate, the abundance of toggles can hurt the maintainability of your code.
Using feature toggles also introduces testing complexity. You will have to write tests for both the on and off state of your toggle. When creating multiple toggles that overlap, testing complexity might increase so much it becomes a serious problem.
A solution to these problems is to keep the number of feature toggles to a minimum and remove them as soon as possible. You should set up a process in your team, such as creating a product backlog item containing the removal of the feature toggle. This also helps the product owner to be aware of the technical debt still present in the application.
Feature toggles are not a good fit for everything; large architectural changes cannot be covered by a feature toggle. In these cases, you’ll have to come up with a different solution as you might have done before.
Feature toggles can provide you with greater flexibility in release procedures in various situations. They provide a clean way to toggle features in an environment, can reduce risks while deploying and provide a way to enable certain users beta-access to new features.
While they are very useful, they also have their drawbacks. Testing complexity can increase with every feature toggle introduced and uncontrollable proliferation of feature toggles should be prevented. Nevertheless, if they are managed correctly, they can be a very powerful tool.
Want to read more about the topic? A new part of the series has been published here.