Complete Guide

Feature Flags: The Complete Guide for Modern Software Teams

Learn everything modern software teams need to know about feature flags, feature management, and progressive delivery: what they are, the key types that matter, how to design them for production, and the rollout strategies that make releases safer.

See how Supaship delivers a developer-first feature flagging experience with Feature flags and Dynamic Configs, instant targeting rules, percentage rollouts, and a lightning-fast flag evaluation at the edge - all without requiring a deploy.

15 min read·Last updated March 2026
01 · Basics

What are feature flags?

A feature flag (also called a feature toggle or feature switch) is a software development technique that lets you enable or disable features at runtime, without deploying new code.

At its simplest, a feature flag is an if statement whose condition is controlled remotely rather than hardcoded. Instead of:

// Old way — requires a deploy to change
if (process.env.NEW_CHECKOUT === 'true') {
  renderNewCheckout()
}

You evaluate the flag at runtime from a remote source:

// Feature flag — flip without a deploy
const enabled = await flags.isEnabled(
  'new-checkout-flow',
  { userId: user.id, plan: user.plan }
)

if (enabled) renderNewCheckout()

This decouples deployment from release, giving your team control over when and to whom a feature is visible without requiring a deployment.

Key concepts

Flag key A string identifier like `new-checkout-flow` referencing the flag in your app code.
Targeting context Attributes passed at evaluation time (userId, plan, region, etc.) used to match targeting rules.
Evaluation The process of resolving which variant (on/off or a value) applies for the given context.
Environment Flags can differ per environment (development, staging, production) with independent state.
How flag evaluation works
1Your app calls the SDK
in-process
Pass a flag key and a context object with any attributes to target on: userId, plan, region, or custom properties.
flags.isEnabled("checkout-v2", { userId, plan })
2Targeting rules are evaluated
plan=pro ✓

Local evaluation

SDK fetches the full ruleset from the edge on init and caches it in-memory. All subsequent evaluations run locally with no network call.

or

Edge evaluation

SDK sends the context to the edge, rules are evaluated there, and only the result is returned. Simpler setup, no local cache needed.

Rule:    IF plan == "pro"  →  true
Context: { userId: "usr_42", plan: "pro" }
                                  ↑ match
3Your code gets the value
true
Boolean flags return true or false. Dynamic Configs return the matching JSON value. Gate your feature on the result.
if (enabled) renderNewCheckout()
With local evaluation, the ruleset cache stays fresh via SSE — flag changes propagate in under a second. With edge evaluation, each call gets the latest result automatically.
02 · Types

Types of feature flags

Not all flags are the same. Understanding the six core types helps you use the right tool for the job, and avoid letting flags live too long.

01

Release flags

Enable trunk-based development by merging unfinished code behind a flag. Ship to production confidently and flip the switch when ready.

new-checkout-flow
02

Experiment flags

Run A/B tests and multivariate experiments by routing users to different variants and measuring outcomes before committing.

homepage-hero-variant
03

Ops / kill-switch flags

Instantly disable a feature during an incident without a code deploy. The safety net every on-call engineer needs.

legacy-payment-fallback
04

Permission flags

Control feature access by user role, plan tier, or organisation. Power your product's entitlement model at runtime.

ai-suggestions-pro
05

Gradual rollout flags

Release to a percentage of traffic and increase incrementally, monitoring errors and metrics at each stage.

new-editor-v2
06

Beta / early access flags

Invite specific users or cohorts to try a feature before the general release. Collect feedback with minimal risk.

onboarding-v3-beta

Lifetime guidance

Release and experiment flags should be short-lived (days to weeks). Ops and permission flags are long-lived and intentional. Treat flags like branches: merge and delete them or they become debt.

03 · Architecture

Feature flag architecture

A production-grade feature flag system has four layers: a control plane, a delivery layer, an SDK, and an analytics pipeline.

System architecture overviewpublish → edge → SDK → result
Control plane
Dashboard · REST API · Flag configuration
Create flags, define targeting rules, set rollout percentages
Flagcheckout-v2enabled
Targeting rules
IF plan == "pro"truerule 1
ELSE 25% of userstruerule 2
ELSEfalsefallback
supaship.com
↓ publish changes instantly
Global edge network
300+ locations worldwide · ruleset cached at the edge
< 1s propagation
New York
p99 3ms
Frankfurt
p99 4ms
Singapore
p99 5ms
São Paulo
p99 6ms
Tokyo
p99 5ms
Sydney
p99 7ms
Mumbai
p99 6ms
293 more…
↓ SDK fetches ruleset · or evaluates at edge
Your application + SDK
flags.isEnabled("checkout-v2", ctx) → true | false
JSReactNodePythonGo
↓ evaluation events
Analytics pipeline
1.2 M
evals / day
43 ms
p99 latency
< 1 s
flag propagation
1

Control plane

The UI and API where teams create flags, define targeting rules, and manage environments. Changes propagate in real time.

2

Delivery layer

Flags are pushed to a CDN or streamed via SSE/WebSocket to SDKs. Edge evaluation ensures sub-millisecond latency.

3

Client SDK

A lightweight library in your app that evaluates flags locally using a cached ruleset, with no network round-trip per evaluation.

4

Analytics pipeline

Evaluation events, impression counts, and latency metrics feed into dashboards to monitor rollout health.

Local vs remote evaluation

Local evaluation: the SDK holds a cached copy of all flag rules and evaluates them in-process. Zero network latency. Requires background polling or a streaming connection to stay fresh.

Remote evaluation: the SDK sends the context to a server which returns the result. Simpler SDK, but adds a network hop per request. Unsuitable for high-frequency evaluations.

Bootstrapping & SSR

For server-rendered apps, evaluate flags server-side and bootstrap the SDK with the evaluated state. This eliminates flicker (the UI change after hydration) and avoids an extra round-trip on load.

// Next.js — eval server-side, bootstrap client
const flags = await getFlags({ userId })
return <ClientProvider bootstrap={flags} />
04 · Rollout strategies

Feature flag rollout strategies

A safe release is a staged release. These six strategies form a progressive confidence ladder; each step de-risks the next.

01

Step 01

Dark launch

Deploy code to production and execute logic silently, with no user-visible changes. Validate performance and correctness at scale before anyone sees it.

02

Step 02

Internal dogfood

Enable for employees first. Your team experiences the feature in production, surfacing UX issues and edge cases before external exposure.

03

Step 03

Beta / canary

Open to a small, opted-in cohort. Gather qualitative feedback from real users who expect rough edges and report them.

04

Step 04

Percentage rollout

Gradually expand from 1% → 5% → 25% → 100%. Monitor your error rate and key metrics at each threshold before proceeding.

05

Step 05

Geographic or segment rollout

Release to one region, plan tier, or user segment first. Ideal for compliance-sensitive features or market-specific changes.

06

Step 06

Full release

Flip to 100% and remove the flag from code within 1–2 sprints. Flags are technical debt; clean them up before they accumulate.

Progressive rollout: traffic exposure over timeEach stage gates entry to the next
1
Dark launch
Code runs, UI unchanged
0%
Infra validation
2
Internal dogfood
Employees only
2%
UX smoke test
3
Beta / canary
Opted-in users
8%
Qualitative feedback
4
1% rollout
Watch error rate & p99
1%
Error baseline
5
25% rollout
Monitor business metrics
25%
Metric gate
6
Full release
Remove the flag within 2 sprints
100%
Ship & clean up
05 · Comparison

Feature flags vs environment variables

Environment variables are set at build or deploy time. Feature flags are evaluated at runtime. The difference is foundational.

Capability
Feature flags
Env variables
Change without deploy
Target specific users / segments
Instant rollback
Gradual percentage rollout
Works at runtime
SDK integration needed
Simple key-value storage
No external dependency
Available at build time

When to use each

Use environment variables for infrastructure config: database URLs, API keys, service endpoints, and values that are fixed for a deployment. Use feature flags for product decisions: what users see, gradual rollouts, and anything you might need to change without redeploying.

06 · In Supaship

Feature flags in Supaship

Supaship supports two primitives: boolean feature flags for on/off decisions, and Dynamic Configs (JSON configs for advanced use cases like structured UI copy, thresholds, and per-user settings). Both share the same targeting and rollout engine. Here's what that looks like in practice.

1

Create a flag in seconds

Supaship has two types of feature flags.
Boolean flags return true or false , ideal for feature gating and kill-switches.
Dynamic Configs are JSON configs for advanced use cases: structured UI copy, feature thresholds, per-segment settings, and anything that would otherwise be a hardcoded constant.
Both use the same targeting and rollout engine.

  • Boolean flags: on/off gating, kill-switches, and access control
  • Dynamic Configs: JSON configs for advanced use cases, no deploy needed
  • Per-environment state: production and staging are isolated
  • Flag description for team clarity
Create flag modal — name, type, description
Targeting rules editor — conditions and segments
2

Target the right users

Define targeting rules using any attribute you pass in the evaluation context (userId, plan, company, or custom properties). Rules are evaluated top-down and return the first match.

// Pass any context attributes at evaluation time
const enabled = await client.getFeature("ai-suggestions", {
  context: {
    userId: "usr_123",
    plan: "pro",
    company: "acme-corp",
  },
})
3

Roll out progressively

After your targeted rules, set a percentage rollout for the remaining audience. Assignments are sticky: the same user always gets the same result, so you don't create inconsistent experiences as you ramp.

  • Sticky user bucketing based on userId hash
  • Adjust the percentage values without a deploy
  • Combine targeted rules with percentage fallback
  • Instant kill-switch: turn off the targeting to disable the feature for all
Rollout percentage slider and sticky bucketing explanation
Flag evaluation analytics — impressions and variant breakdown
4

Monitor every evaluation

Every flag evaluation is tracked. See impression counts, variant distributions in real time. Use this to confirm your rollout percentages are behaving correctly before expanding.

<50ms
Evaluation latency
100%
Sticky bucketing
Real‑time
Flag propagation
SDK quick-start@supashiphq/javascript-sdk

Install

npm install @supashiphq/javascript-sdk

Boolean flag

import { SupaClient, FeaturesWithFallbacks }
  from '@supashiphq/javascript-sdk'

const features = {
  'new-onboarding': false,
} satisfies FeaturesWithFallbacks

const client = new SupaClient({
  apiKey: process.env.SUPASHIP_API_KEY!,
  environment: 'production',
  features,
  context: { userId: user.id, plan: user.plan },
})

// Fully typed — returns boolean
const show = await client.getFeature('new-onboarding')

if (show) renderNewOnboarding()

Dynamic Config

import { SupaClient, FeaturesWithFallbacks }
  from '@supashiphq/javascript-sdk'

const features = {
  'checkout-copy': {
    headline: 'Get started',
    cta: 'Sign up free',
  },
} satisfies FeaturesWithFallbacks

const client = new SupaClient({
  apiKey: process.env.SUPASHIP_API_KEY!,
  environment: 'production',
  features,
  context: { userId: user.id, plan: user.plan },
})

// Fully typed — returns { headline: string; cta: string }
const config = await client.getFeature('checkout-copy')

renderCheckout(config)

Batch fetch · multiple flags in one call

const results = await client.getFeatures(['new-onboarding', 'checkout-copy'], {
  context: { userId: user.id, plan: user.plan },
})
// { 'new-onboarding': true, 'checkout-copy': { headline: '...', cta: '...' } }
07 · Tools

Best feature flag tools in 2026

There's no single right answer. The best tool depends on your team size, budget, and technical requirements.

Supaship

Recommended

Developer-first · free to start · sub-50ms evaluations

Free plan with unlimited flags and team members
Boolean flags + Dynamic Configs
Percentage rollouts + targeting
Lightning-fast flag evaluation at the edge
Best developer experience
Lowest pricing in the market
Newer entrant
Limited integrations

LaunchDarkly

Enterprise-grade · extensive integrations

Mature platform
Rich workflow automation
Enterprise compliance
A/B testing (Experimentation)
Release pipelines
Session replays
Expensive at scale
Complex pricing

ConfigCat

Simple · SDKs for many languages

Easy to set up
Good free tier
Simple targeting
Limited advanced targeting
Basic analytics

Unleash

Open-source · self-hostable

Self-hosted option
Open-source
No vendor lock-in
Operational overhead
Less polished UI

Get started

Ready to ship with confidence?

Supaship gives you feature flags, targeting, and rollout controls, free to start, up in 5 minutes.