Start With an If: Feature Toggles

Feature toggles don't require complex tools or infrastructure. They start with a single variable and an if statement using your existing deployment process.

This article covers a practical progression from basic on/off toggles, to audience targeting, and then to deployment-free changes, with realistic expectations at each step.


The Core Idea

Deploy code to production disabled, then enable when ready. No long-lived feature branches.

ENABLE_FEATURE = false

if ENABLE_FEATURE then
    // new code
else
    // existing code
end if

This keeps the main branch (your primary production branch) deployable from day one. A deployable main branch supports continuous integration, minimizes merge conflicts, and accelerates feedback—foundations of trunk-based development. See Trunk-Based Development (opens in a new tab) and Continuous Delivery (opens in a new tab) for more on these practices.


Getting Started

1. Pick the Right Feature

Start with: UI label changes, buttons, error messages

Avoid (if new to feature toggles): Database changes, business logic, cross-repo work

2. Basic Toggle Example

New homepage labels:

// components/homepage/labels.js
const ENABLE_NEW_HOMEPAGE_LABELS = false;

export const getHomepageLabels = () => {
  if (ENABLE_NEW_HOMEPAGE_LABELS) {
    return {
      heroTitle: "Discover Your Next Adventure",
      ctaButton: "Start Exploring",
      feature1: "Smart Recommendations"
    };
  } else {
    return {
      heroTitle: "Welcome to Our Platform",
      ctaButton: "Get Started",
      feature1: "Feature One"
    };
  }
};

Usage:

const labels = getHomepageLabels();
return <h1>{labels.heroTitle}</h1>;

3. Deploy, Test, Activate

  • Commit to main, deploy normally (feature off)
  • Set true locally to test
  • Set true and redeploy to activate

Phase 1: Config in Code

Centralize toggles and introduce audience targeting.

Structure:

src/
  config/toggles.js
  utils/toggle.js

config/toggles.js:

export const TOGGLES = {
  ENABLE_NEW_HOMEPAGE_LABELS: {
    enabled: false,
    audiences: ['beta_users'],
    percentage: 10
  }
};

utils/toggle.js:

import { TOGGLES } from '../config/toggles';
import { getUserAudience } from '../auth';

export const isEnabled = (featureName) => {
  const feature = TOGGLES[featureName];
  if (!feature) return false;

  const audience = getUserAudience();
  const audienceMatch = feature.audiences.includes(audience);
  const percentageMatch = !audienceMatch && Math.random() < (feature.percentage / 100);

  return feature.enabled && (audienceMatch || percentageMatch);
};

Usage:

import { isEnabled } from '../../utils/toggle';

export const getHomepageLabels = () => {
  if (isEnabled('ENABLE_NEW_HOMEPAGE_LABELS')) {
    return { /* new labels */ };
  }
  return { /* existing labels */ };
};

Phase 2: Deployment-Free Toggles

Once toggles are stable in code, move config outside the codebase to enable changes without deploys.

Option 1: Environment Variables (generally requires a restart)

ENABLE_NEW_HOMEPAGE_LABELS=true
HOMEPAGE_LABELS_AUDIENCES=beta_users
HOMEPAGE_LABELS_PERCENTAGE=10

Option 2: Database Flags (no restarts required)

INSERT INTO feature_flags (name, enabled, audiences, percentage)
VALUES ('ENABLE_NEW_HOMEPAGE_LABELS', true, '["beta_users"]', 10);

Cost: 2-second DB update, no restart.


Quick Start

  1. Add ENABLE_NEW_HOMEPAGE_LABELS = false
  2. Wrap labels in if
  3. Commit to main, deploy normally

Start with one if statement. Benefits compound quickly.

HAVE QUESTIONS ABOUT THIS POST?
Reach out for clarification, deeper discussion, or related insights.