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 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 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