Skip to Content
Technical Articles

Library for feature-flags in nodejs on cloud foundry

We have deployed applications in multi-tenant mode to multiple customers.
Now it is time to add new features.
How will we deliver those features to our customers?

  • For all customers at once?
  • The first day to 25% of the customers, the second to 50%, …
  • For some subscribed tenants only?
  • Do we want to test different variations?
  • How can we rollback quickly?

To make our life easier SAP Cloud Foundry provides the feature flag service.

For those who are using nodejs applications and want to check the state of the flags or want to provide an easy api in nodejs to read the features via rest API. I created a library called sap-cf-features.

You can find a simple example application in this github repository.
Add the feature flag entitlement to your account and deploy it with the npm run deploy command.

Let’s take a look at the mta.yaml file to check how we add the feature flag service and how we use it.
At the bottom of the file we define that the service should be created when deploying the project.

  ...
  #FEATURE_FLAGS
  - name: featureflags_service
    parameters:
      service-plan: standard
      service: feature-flags
    type: org.cloudfoundry.managed-service

in the approuter module, we add the feature service as a dependend module.

...
  - name: featuresexample
    type: nodejs
    path: approuter
    parameters:
      disk-quota: 512M
      memory: 512M
    requires:
      - name: featuresexample_destination
      - name: featuresexample_html5_repo_runtime
      - name: featuresexample_uaa
      - name: featuresexample_portal
      - name: featureflags_service
...

We will add the express router of the sap-cf-features lib in the approuter with an extension on the approuter. Just to save some work and resources, typically we do this in a nodejs service that is attached to the approuter via a destination.

Check the approuter.js file in the approuter folder.

const approuter = require("@sap/approuter")();
const {featureFlagRouter} = require("sap-cf-features");

approuter.beforeRequestHandler.use(
  '/feature-flags', featureFlagRouter()
);

approuter.start();

the result of this code is that all routes starting with /feature-flags will return a result from the feature flag service. Initially, there is no flag defined. So let’s do that first.

In your trial account, go to your space > service instances and search for the featureflags_service entry and click the open dashboard button.

Open%20dashboard%20of%20the%20feature%20flag%20service

Open dashboard of the feature flag service

Hit the button new flag and enter all fields

We’ve created a boolean feature and by enabling it, it get’s the value “true”.

Let’s create a feature-2 with type string.

This feature has 3 possible values.

Option A, option B, option C.

The default value = Option A.

With the strategy options, we can decide to give other values to identifiers. In the sap-cf-features library, the identifier is always the id of the subscribed tenant, so you can configure different values for different tenants.

Caution: There is a weird behavior on booleans without a direct delivery strategy defined. If the enable switch is on, the value is true, except when there is a direct delivery defined, then it is only true for the tenant specified in direct delivery. In my opinion, it should be more clear if there was a default variant setting for booleans too, like there is for string flags. For this reason, I add a direct delivery to dummy to feature-1. So when the flag is enabled, it is false for everyone. You can add tenant names in direct delivery or release the flag to make it true.

Dummy%20strategy%20for%20feature-1

Dummy strategy for feature-1

After creating these flags we can try to retrieve the values from the approuter-service.
Please click the link in the featureflags application and change in the url “/cp.portal/site#Shell-home” to “/feature-flags/” or “/feature-flags/<name-feature>”

this is the response for the /feature-flags:

{
  feature-2: "Option A",
  feature-1: false
}

 

This response we can easly consume in UI5 apps to adapt the behaviour of the UI.
In this example, I just show a table with the available feature flags. Open the url of the featureflags application again and open the application by clicking on the feature flags tile.

To show you the direct delivery strategy we can use the tenant name.
Find your tenant name (subdomain):

Copy the name of your tenant. and open feature-2 in the feature-flags dashboard. In the strategy section, we add the tenant-name for var2.

So in this case, the flag will return “Option A” except if your tenant name is xxxxxxtrial, then it will return var2 “Option B”.

Let’s refresh the ui page …

Besides the express/connect router, the library also contains some functions to check the value of a feature in a nodejs app.

    const {getFeatureFlags, getFeatureFlag, getFeatureFlagBoolean, getFeatureFlagString} = require('sap-cf-features');

    // get all feature flags for a certain tenant
    const featureFlags = await getFeatureFlags(undefined, "tenantName");
    // get some feature flags for a certain tenant
    const featureFlags = await getFeatureFlags(["feature-1", "feature-2"], "tenantName");
    // get one feature flag value for a certain tenant
    const featureFlagValue = await getFeatureFlag("feature-1", "tenantName");
    const featureFlagValueBoolean = await getFeatureFlagBoolean("feature-1", "tenantName");
    const featureFlagValueString = await getFeatureFlagString("feature-2", "tenantName");

At this moment the express/connect router is sending the tenant name to the features API to evaluate features. When using the other functions here, you have to pass the tenant name in the functions. It’s free for you to choose the identifier, if you want the features to release on a user base instead of tenant base, then you can pass usernames here.

I hope you will enjoy this library!

kr,

Joachim

 

 

 

Be the first to leave a comment
You must be Logged on to comment or reply to a post.