Dev Flags: Supercharge your Continuous Deployment by Dropping Database Feature Toggles

Dev Flags: Supercharge your Continuous Deployment by Dropping Database Feature Toggles

Those of us who use Trunk Based Development as the foundation of our approach to Continuous Delivery or continuous Deployment are familiar with the use of Feature Toggles to prevent work in progress changes becoming prematurely available to customers while we develop them. To use the ThoughtWorks vernacular; release toggles.

A mistake I have seen many teams make, and regret, is managing these release toggles from the database. This approach has several issues:

  1. Every release must test both paths, as the toggle could change at any time
  2. Developers working on the code base have less visibility into which flags are currently enabled in which environments
  3. Product Managers, developers, and testers often have to coordinate on the removal of feature toggles, this often leads to toggles simply not being removed
  4. Following on from above, old feature toggles often stop being tested. This means every stale feature toggle is a liability that could cause an incident.
  5. A full history of changes is either lost or needs tooling built to support it

Sure, many of the above issues could be solved with good tooling and strict processes, aside from #1. However all of these issues can be solved with tools your team has now: Source control & code.

By putting your toggles in code, you get the following advantages:

  1. Changes only need to test the active code paths in each release, as they cannot change without another release
  2. Changes to toggles have to go through the full SDLC/release pipeline and thus we can be confident they are working as expected
  3. Developers can clearly see what features are enabled in what environments, who worked on them, and when they were changed
  4. Developers can easily remove toggles once they have finished with them, as part of their feature clean up.

Because this approach seriously empowers developers to manage these toggles themselves, I believe this approach needs its own term: Dev Flags

The advantage of this name is that it is clear who is responsible for them: Developers! This is just part of how we get work done, Product managers don't need to be involved except to confirm they would like a new feature to go live in production.

This clearly delineates the costs involved in maintaining a feature toggle for other purposes, such as A/B Testing, Ops Toggles, and Canaries. By using two seperate systems, we can be clear with product managers, maintaining a new toggle will incur extra overheads on our time, impact our release cycles, and introduce an element of fatigue and complexity over time. This can help us ensure we collaborate on an effective plan to manage the lifecycle of our feature toggles when they are needed, and remove them as soon as they are no longer necessary.

How to implement Dev Flags? In projects using TypeScript for frontend and backend, I like to include these in a shared package. My folder structure might be:

Screen Shot 2021-10-03 at 11.07.31 am.png

And the contents of devFlags.ts:

type RuntimeEnvironments = 'dev' | 'stg' | 'prd';

type DevFlags = {
  useNewProfileScreen: boolean;
  usePhoneCheck: boolean;
};


type DevFlagsEnvironmentMap = Record<Exclude<RuntimeEnvironments, 'stg'>, DevFlags>;

const getEnvironmentDevFlagSet = (env: RuntimeEnvironments): DevFlags => {
  const envs: DevFlagsEnvironmentMap = {
    dev: {
      useNewProfileScreen: true,
      usePhoneCheck: true,
    },
    prd: {
      useNewProfileScreen: true,
      usePhoneCheck: false,
    },
  };

  const flagEnv = env === 'stg' ? 'prd' : env;

  return envs[flagEnv];
};

export const DEV_FLAGS = getEnvironmentDevFlagSet(env.RUNTIME_ENVIRONMENT);

Why do we exclude staging and instead treat it as prod? Because staging is where we confirm that the current deployment artefact is suitable for release to production. We can't do that if we're executing different code paths in staging and production.

In this one file I can see what features are in development, where they're active, who added which lines, and I can lookup usages to find these flags in the codebase.

As a rule of thumb, you want the number of dev flags in code to be equal to or less than the number of developers working in the code base. This requires some discipline to ensure you remove the flag after releasing the feature. Advantageously, developers are motivated to remember to remove flags because we like to keep our code clean, and we're empowered to do it, because it just another merge, same as we do all day.

Will you try Dev Flags with your team? Does your team do something else? Does it work for you? Let us know in the comments!

Cover photo: The Twin Jet Nebula, or PN M2-9, is a striking example of a bipolar planetary nebula. Bipolar planetary nebulae are formed when the central object is not a single star, but a binary system, Studies have shown that the nebula’s size increases with time, and measurements of this rate of increase suggest that the stellar outburst that formed the lobes occurred just 1200 years ago.