Feature Flags: Deploy Unstable Features

Today, I’m gonna tell you a story. A story about how to deploy unstable features without compromising the application.

While working on the projects, I’ve been asked to develop many features in an early stage. When the specifications were not finished, or the integration was partial.

How to rollout the complete application when only a single feature isn’t finished? I don’t want a single feature to block the rollout of a new version of my application.

How to solve this situation without spending two more weeks finishing the work?

Feature flags

What if I push the code, but with the feature disabled?

Let’s start assuming I want to use the feature flags at the beginning.

The easiest way is to create a constant which indicates the feature is disabled. Then, surround my new feature with if conditions.

public class MyService {
   private static final boolean FEATURE_FLAG = false;

   public void handleRequest() {
      if (FEATURE_FLAG) {
         handleNewVersion();
      } else {
         handleOldVersion();
      }
   }
}

That’s clean. But usually, I know a feature is unstable and I want to hide it at the last minute.

Ok, no problem. Git is my friend.

Let’s pick all the classes with changes and rename them. Let’s restore the original files from Git. Now, use one class or the other depending on the feature flag.

public class MyController {
   private static final boolean FEATURE_FLAG = false;

   private final MyNewService myNewService;
   private final MyOldService myOldService;

   @PostMapping("/do")
   public ResponseEntity<Void> doSomething() {
      if (FEATURE_FLAG) {
         myNewService.handleRequest();
      } else {
         myOldService.handleRequest();
      }
   }
}

Dynamic feature flag

All this sounds good when I really don’t want to execute the code. I’ll need to rollout my application again to enable the feature.

But want if I want to test the feature? Enable it for some days, disable it, and compare both behaviors.

Ok, that’s more like A/B testing.

For those situations, I have a table in the database called FeaturesConfiguration. I store there all the features flags. So, instead of reading my feature flag values from contants, I read them from the database.

And when I want to change the behavior, I update the value in the database.

Warnings

This seems to be the solution for all the stable features. But there are some considerations to take into account.

This generates two workflows. With the feature enabled and with the feature disabled. I have to test my application in both workflows. Ensure the application is stable in both situations. Otherwise, I can’t use the dynamic feature flags. I must wait until the feature is stable.

Clean up

Once the feature is fully developed and deployed, I don’t need the flag anymore.

It will be activated all the time.

Here is when I must clean up my code to remove all the conditions. Otherwise, I need to maintain two versions of the application. That’s a lot of work.

Conclusion

When do I use feature flags? With features which need a long time to be developed. When I want to split the deployment of a feature.

Or when a feature seems to be unstable at the end of the release cycle, and we try to fix again and again the bugs. When you mix the rush with an unstable feature, you never have a good result.


Never Miss Another Tech Innovation

Concrete insights and actionable resources delivered straight to your inbox to boost your developer career.

My New ebook, Best Practices To Create A Backend With Spring Boot 3, is available now.

Best practices to create a backend with Spring Boot 3

Leave a comment