Feature Transforms

Feature Transforms are the evolution of feature flags.

Consider a vanilla feature flag. A new feature is expressed when the flag is on. The feature flag SDK evaluates the flag by its key – often a username – and the name of the flag.

import { SplitFactory } from '@splitsoftware/splitio';

const factory = SplitFactory({
  core: {
    authorizationKey: '28bddhnjht06lvi8e5aa9rkmv5glsc40ltaa'
  },
  debug: false
});

const client = factory.client();

async function neutral() {
  console.log('enter neutral');

  // Wait for SDK to be ready
  await client.ready();

  const treatment = client.getTreatment('dmartin', 'feature_transform');
  console.log('treatment', treatment);

  if (treatment === "on") {
    expressFeature();
  } else if (treatment === "off") {
    // do nothing
  } else if (treatment === "control") {
    throw new Error("could not evaluate flag: " + treatment);
  } else {
    throw new Error("surprise treatment: " + treatment);
  }

  console.log('exit neutral');
}

function expressFeature() {
  console.log('expressFeature');
}

// Run it
(async () => {
  try {
    await neutral();
  } catch (err) {
    console.error(err);
  } finally {
    client.destroy();
  }
})();

But the treatment that comes back is more interesting. It can be “on” or “off”, but also “control” or something else entirely. You have no choice but to expect the developer will study the treatments available to the flag.

Dynamic Config

There is an alternative, what Harness FME calls “dynamic config” A dynamic config is a JSON document associated with each treatment.

Consider a flag that has three treatments: red, blue, and orange. The dynamic config for blue might look like this:

{ 
  "name": "blue",
  "urls": [ 
		"https://navy", 
		"https://midnight", 
		"https://cerulean" 
		] 
 }

The most notable thing is that the JSON payload can say much more than just a treatment in our previous example. In particular, it names itself and provides an array of URLs.

The JSON for the red and orange treatments will obey the schema, but have unique values. For example, red might look like:

{ 
"name": "red", 
"urls": [ 
	"https://magenta", 
	"https://fire", 
	"https://pink" 
	] 
}

The schema is the key to success. If you have a schema, you can test the flag this way:

const result = client.getTreatmentWithConfig('dmartin', 'feature_transform');
const json = JSON.parse(result.config);
console.log(json.name);
console.log('json', json);

Note that treatment is no longer used at all. The flag could have two treatments, three treatments, or twenty. As long as each treatment has the same JSON schema, the author of the flag can take action. No ugly if-then-else-if-else-if-… code blocks are necessary.

You may still want to handle the control treatment and it’s easy.

const result = client.getTreatmentWithConfig('dmartin', 'feature_transforx'); // flag name typo
if(result.treatment === "control") {
// handle control treatment, e.g. turn off flag
}

Or you can also handle the case that the JSON is not available.

Finally, we’re at feature transformation.

It is exciting to put JSON data in a dynamic config, but the data then resides in the dynamic config where it is subject to version drift, becoming stale.

What if the JSON data looked like this:

{
  "$id": "https://example.com/person.schema.json",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Person",
  "type": "object",
  "properties": {
    "firstName": {
      "type": "string",
      "description": "The person's first name."
    },
    "lastName": {
      "type": "string",
      "description": "The person's last name."
    },
    "age": {
      "description": "Age in years which must be equal to or greater than zero.",
      "type": "integer",
      "minimum": 0
    }
  }
}

This is an example from https://json-schema.org/learn/miscellaneous-examples

Now the feature flag returns a schema instead of data. At runtime, the code can create instances of of the Person schema:

{
  "firstName": "John",
  "lastName": "Doe",
  "age": 21
}

The feature flag is now acting transformationally. The flag doesn’t provide data anymore, but the means with which to create data.

By insisting on a schema from the flag, the code must pull the data itself. No stale data buried in the feature flag, and guaranteed fresh data when the flag is evaluated.

The JSON schema can code more types of transformation

Written with StackEdit.