Feature toggles in a microservice environment – Part 2: Implementation

No Comments

In part one of this series – Benefits and Drawbacks – we discussed the effects of using feature toggles. They provide greater flexibility when deploying and decouple the moment of deployments from the moment of the release of a feature. Next, we will take a look at how you can implement this in your environment.

Approaches

There are different approaches you could take to implement feature toggles in your environment, depending on the use case. These approaches can be categorized into two categories: build-time and run-time.

When using a build-time approach you can only switch your feature toggles on or off using commits; they are baked into your deliverable. These are the easiest to implement. You could, for example, comment out the particular code call. A better approach would be to use property files to define the state of the feature toggles. Most frameworks (such as Spring) have great support for this. There are several benefits from versioning your feature toggles – such as it being versioned in the first place – but it reduces the flexibility of your environment.

For greater flexibility you could use a run-time approach, because then you can turn the feature toggles on or off whenever you want. One of the most noteworthy approaches is using environment variables. These variables are read by your application to define the business logic to be executed. The downside of using these is that you have to reboot your application to apply the new state of your feature toggles. If your production environment can only be modified using CI pipelines, a practice called immutable infrastructure, you have to make a new commit to change this environment variable. Using property files would in that case be a better approach as they are already integrated into your framework and source code.

In a microservice environment it makes more sense to make a feature toggle service, which controls all the feature toggles. Rather than implementing this ourselves, we can deploy an open source service to do this for us. Unleash is one of the best options to do this.

How Unleash works

Unleash is a Node.js service with a PostgreSQL database which manages the state of your feature toggles. Other services in your architecture can request the current state of the feature toggles, which can then adjust the business logic being executed.

Unleash diagram

Diagram showing how Unleash works, as found in Unleash documentation: https://github.com/Unleash/

 

Free goodies

Unleash includes an administration UI which you can use to create, control, and delete those feature toggles. You can also define various ways to roll out a feature. You can roll it out for everyone at once, for a set percentage of users or just for one particular user.

Unleash Dashboard

A view of Unleash’s Administration UI

The best part is that your application code does not need to know how Unleash works; there are various client libraries already available for multiple programming languages, such as Java. These are high-level libraries which abstract any complexity added by using Unleash. The simplest implementation to use Unleash in Java (Spring or EJB) looks as follows:

@Service // or
@Stateless
public class FeatureToggler {
    private Unleash unleash;
 
    public FeatureToggler() {
        UnleashConfig config = UnleashConfig.builder()
                .appName("my-microservice")
                .fetchTogglesInterval(1)
                .unleashAPI("my-unleash-url")
                .build();
 
        unleash = new DefaultUnleash(config);
    }
 
    public boolean isToggleActive(final String feature) {
        return unleash.isEnabled(feature);
    }
}

That’s not complex at all, is it?

It initializes the Unleash client with the name of your app being “my-microservice”, the URL “my-unleash-url” and it fetches the current featue toggle state every second. The fetch interval of 1 second works pretty well in my experience. This is because a background thread fetches the latest state every second while using E-Tags to enable caching. Usage of background threads makes sure that the performance of your application is not negatively affected.

One of the greatest thing about Unleash is that you can release a feature across all microservices at once, even if they were deployed at different times. All you have to do is use the same name for the feature toggle across all the microservices updated for that particular feature.

Limitations of Unleash

While bringing lots of good stuff for free, Unleash also comes with its own set of limitations. Luckily, we can work around most limitations effectively.

Authentication

While authentication in Unleash is supported, it is not implemented by default. There are some example providers which you can plug into your installation, but if you want anything custom you have to implement it yourself. I wanted to use Keycloak for authentication and since there were no example providers for this yet, I had to write one myself. You can find the code for this here (Currently opened a PR).

Database

Unleash runs on PostgreSQL and… nothing else! If you do not use PostgreSQL at the moment you will have to start running it. Since we use Kubernetes, this was fairly simple, but if your environment is less flexible, it will be harder to do so. Perhaps adding MySQL and/or Oracle as supported would make a great Pull Request.

 

Conclusion: Feature toggles with Unleash

Unleash is a great service to implement in your microservice environment to enable feature toggles to be as flexible as possible. Despite all greatness Unleash brings, there are some limitations you might not be able to work around. In that case, environment variables or property files might be the better way to go.

Avatar

Mitchell is an enthusiastic developer with a knack for back-end development, cloud architecture and CI/CD practices. Besides building a model railroad, he likes spending his time learning new things to improve and spread the knowledge to others.

Comment

Your email address will not be published. Required fields are marked *