Come join our happy hour in Seattle! – Click here.

Toggling Constants With Feature Flags

Contents

Split - Toggling-Constants-With-Feature-Flags

Split’s React application uses a feature flag toggling system to make it easier to add and remove feature flags from our code base.

Every month or two, someone asks: “I’ve got this constant that I need to change based on the feature flag. What should I do?”

A Quick Reminder About Toggling

The toggling technique (e.g., connectToggler() in the Split Redux SDK) involves making a separate version of functions for each feature flag treatment. These functions are then wrapped with a “toggler.”

When compared to sprinkling individual getTreatment() calls around in the code base, this technique makes the code easier to reason about and easier to test. It also makes adding and removing feature flags much easier. We actually have a script that does most of the work for adding and removing feature flags.

This looks like:

const toggledFunction = toggler(FEATURE_FLAG_NAME, treatmentAFunction, treatmentBFunction);
// …
const result = toggledFunction(someArgment);
TypeScript

Constants

There are three techniques we’ll talk about here:

  • Using distinct constant names
  • Using separate constant files
  • Wrapping constants with a function

In the discussion, we’ll assume that we have a constant (SOME_CONSTANT) whose value we want to be 23 in TreatmentA and 45 in TreatmentB:

const SOME_VALUE = 23;
TypeScript

Distinct Names

The easiest solution is just to use distinct constant names:

const SOME_VALUE_TREATMENT_A = 23;
const SOME_VALUE_TREATMENT_B = 45;
TypeScript

We can then import this into the functions that use the constant. As long as those are toggled, this works well:

import { SOME_VALUE_TREATMENT_A } from "someConstantsFile";

const treatmentAFunction = (inputParam) => {
  const newValue = inputParam * SOME_VALUE_TREATMENT_A;
  //  …
};

import { SOME_VALUE_TREATMENT_B } from "someConstantsFile";

const treatmentBFunction = (inputParam) => {
  const newValue = inputParam * SOME_VALUE_TREATMENT_B;
  //  …
};
TypeScript

Pros and Cons

This technique is very easy to implement, and it is easy to understand.

However, this tends to make cleaning up the feature flag more difficult. Once you remove one of the treatments, you must manually edit the file with the constants, and then rename all the uses of the constant (though that last is very easy with some languages and IDEs).

Distinct Constant Files

A second approach is to make a separate file of constant values for each treatment. For example, before toggling the function, we might have these files, constants.ts and myFunction.ts.

constants.ts
myFunction.ts

And after toggling, we have:

.
├── myFunction/
│   └── index.ts
├── TreatmentA/
│   ├── constants.ts
│   └── MyFunction.ts
└── TreatmentB/
    ├── constants.ts
    └── MyFunction.ts

Pros and Cons

This solution has all the benefits of the toggling system, and so is ideal if your constants are closely related to the function being toggled.

  • The constants are isolated from each other
  • It is easy to remove them when the feature flag is removed

This also does not work if the file with the constants is not so easily grouped with the consumers. It is not uncommon to have a group of constants in a more “global” location, and for these values to be used in various otherwise unchanged files. In this case, this technique does not work.

Wrapping the Constants With a Function

A third technique converts all the access to your constants into a function call. The code below shows an example.

Before

// globalConstants.ts

export const SOME_VALUE = 23;
export const SOME_OTHER_VALUE = true;
TypeScript
// someFunction.ts

import { SOME_VALUE } from "../globalConstants";

const myFunction = (props) => {
  const someValue = props.foo * SOME_VALUE;
  // …
};
TypeScript

After

// globalConstantsTreatmentA.ts

const getConstantsTreatmentA = () => ({
  SOME_VALUE: 23,
  SOME_OTHER_VALUE: true,
});

export { getConstants };
TypeScript
// globalConstantsTreatmentA.ts

const getConstantsTreatmentA = () => ({
  SOME_VALUE: 23,
  SOME_OTHER_VALUE: true,
});

export { getConstants };
TypeScript
// someFunction.ts

import { getConstants } from "../../someLocation/getConstants";

const myFunction = (props) => {
  const { SOME_VALUE } = getConstants();
  const someValue = props.foo * SOME_VALUE;
  // …
};
TypeScript

Now, when myFunction accesses the constants, it will get either the treatmentA value, or the treatmentB value based on the value of the feature flag at that moment.

Pros and Cons

This provides all the benefits of a toggling system. Other parts of the code are unaware of the presence of the feature flags, making the code easier to reason about and test. As a result, it is easy to add and remove toggled code without impacting other parts of the system. This makes adding and removing flags very safe.

The biggest downside is certainly the fact that one must make a function call to get the constant value.

Summary

Providing a constant with a different value based on the presence of a feature flag can be challenging. But when using a feature toggling system, there are several techniques you can consider using to achieve your goal.

All of the techniques here have their own benefits. You should pick the technique that will maximize your development velocity while also making it safe to add and remove your feature flags.

Get Split Certified

Split Arcade includes product explainer videos, clickable product tutorials, manipulatable code examples, and interactive challenges.

Switch It On With Split

Split gives product development teams the confidence to release features that matter faster. It’s the only feature management and experimentation platform that automatically attributes data-driven insight to every feature that’s released—all while enabling astoundingly easy deployment, profound risk reduction, and better visibility across teams. Split offers more than a platform: It offers partnership. By sticking with customers every step of the way, Split illuminates the path toward continuous improvement and timely innovation. Switch on a trial account, schedule a demo, or contact us for further questions.

Want to Dive Deeper?

We have a lot to explore that can help you understand feature flags. Learn more about benefits, use cases, and real world applications that you can try.

Create Impact With Everything You Build

We’re excited to accompany you on your journey as you build faster, release safer, and launch impactful products.