Software Development

Feature Toggles (Feature Switches or Feature Flags) vs Feature Branches

Feature Branches

If you are using branches, you are not doing Continuous Integration / Deployment / Delivery!

You might have great Code Coverage with unit tests, you might be doing TDD, you might have functional and integrations tests written in BDD format and you might run all of them on every commit to the repository. However, if you are having branches, integration is delayed until they are merged and that means that there is no continuous integration.

 
People tend to like feature branches. They provide flexibility to decide what to release and when. All there is to do is to merge features that will be released into the main branch and deploy to production. The problem with this approach is the delay. Integration is delayed until the merge. We cannot know whether all those separately developed features work well together until the merge is done and all the unit, functional, integration and manual tests are run. On top of that, there is the problem caused with the pain of merge itself. Days, weeks or even months of work are suddenly merged into the main branch and from there to all not-yet-to-be-released branches. The idea of Continuous Integration is to detect problems as soon as possible. Minimum delay until problems are found.

The most common way to mitigate this problem is to have feature branches small and short-lived. They can be merged into the main branch after only a day or two. However, in many cases this is simply not possible. Feature might be too big to be developed in only few days. Business might require us to release it only in conjunction with other features.

In other words, feature branches are great for allowing us to decide what to release and when. They provide us the flexibility but they prevent us from doing Continuous Integration. If there would be only one branch, we could do continuous integration but the release problems that were solved with feature branches would come back to haunt us.

Feature Toggles

Feature Toggles (sometimes called Feature Switches or Feature Flags) should solve the need to be able to deploy only selected set of features while keeping only one (main) branch. With them we can do all the work in one branch, have continuous integration taking care of the quality of our code and use flags to turn features off until they are ready to be released. We can have all the benefits of Continuous Integration together with the flexibility to choose which features will be available and which will be hidden. Moreover, it is a step towards Continuous Deployment. If we do have satisfying automated test coverage and can switch features off and on, there is nothing really preventing us from deploying to production each commit that passed all verification. Even if some bug sneaks into the production, with Feature Toggles if would be very easy to turn that feature off until it’s fixed.

The basic idea is to have a configuration file that defines toggles for features that are pending to be fully released. Alternative to a configuration file can be a database table. The application should use those toggles to decide whether to make some feature available to the users or not. They might even be used to display some functionality to a subset of users based on their role, geographic location or random sample.

There are only few rules to be followed:

  • Use toggles only until they are fully deployed and proven to work. Otherwise, you might end up with “spaghetti code” full of if/else statements containing old toggles that are not in use any more.
  • Do not spend too much time testing toggles. It is in most cases enough to confirm that the entry point into some new feature is not visible. That can be, for example, link to that new feature.
  • Do not overuse toggles. Do not use them when there is no need for them. For example, you might be developing a new screen that is accessible through the link in the home page. If that link is added at the end, there might be no need to have toggle that hides it.

Examples

There are many libraries that provide the solution for Feature Toggles. However, implementing them is so easy that you might choose to do it yourself.

Here are few examples of possible implementations of Feature Toggles. They use AngularJS but the logic behind them could be applied to any other language or framework.

[JSON with Feature Toggles]

{
  "feature1": {
    "displayed": false
  },
  "feature2": {
    "displayed": true
  },
  "feature3": {
    "displayed": false
  }
}

I tend to have more values in my toggles JSON. Some of them as disabled, description, allowed_users, etc. The above example is only the bare bones minimal solution.

Next, we should load the JSON into, in this example, AngularJS scope.

[AngularJS that loads Feature Toggles into the scope]

$http.get('/api/v1/data/features').then(function(response) {
  $scope.features = response.data;
});

Once Feature Toggles are in the scope, the rest is fairly easy. Following AngularJS example hides the feature when displayed is set to false.

[AngularJS HTML that hides some element]

<div ng-show="features.feature1.displayed">
  <!--Feature HTML-->
</div>

In some cases, you might be working on a completely new screen that will replace the old one. In that scenario something like the following might be the solution.

[AngularJS that returns URL depending on Feature Toggle]

$scope.getMyUrl = function() {
  if($scope.features.feature2.displayed) {
    return 'myNewUrl';
  } else {
    return 'myOldUrl';
  }
}

Then, from the HTML, it would be something like the example below.

[AngularJS HTML that toggles URL]

<a href="{{getMyUrl()}}">
  This link leads somewhere
</a>

In some other cases change might be on the server. Following REST API best practices, you’d create a new API version and use Feature Toggle to decide which one to use. Code could be like following.

[AngularJS that performs request that depends on Feature Toggle]

var apiUrl;
if($scope.features.feature2.displayed) {
  apiUrl = '/api/v2/myFancyFeature';
} else {
  apiUrl = '/api/v1/myFancyFeature';
}
$http.get(apiUrl).then(function(response) {
  // Do something with the response
});

Same logic applied to the front-end could be applied to the back-end or any other type of the application. In most cases it boils down to simple if/else statements.

Viktor Farcic

Viktor Farcic is a Software Developer currently focused on transitions from Waterfall to Agile processes with special focus on Behavior-Driven Development (BDD), Test-Driven Development (TDD) and Continuous Integration (CI).
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
James Woods
9 years ago

The assumptions you make about working with branches are wrong from the start. There is nothing stopping you running integration tests on the feature branch, that is purely a matter of how you set up your test system. You then write about the supposed pain of merging. In any well managed codebase you do not have multiple developers making changes to the same lines of code at the same time, even if they all worked on the trunk this would be recipe for disaster. Assuming sanity has prevailed and developers are working on separate areas merging is never going to… Read more »

Quiaks
Quiaks
9 years ago

Client-side javascript code with flags? I think it’s insecure

Back to top button