skip to content

questions

6

What is a feature flag, and how does using one to gate a new code path let a team deploy code to production without releasing it to users yet?

level: juniorimportance: must knowfreq 75%

answer

  1. deploy != release
  2. dark launch
  3. trunk-based development enabler
  4. runtime conditional outside binary
  5. flip not redeploy

basics

~20 s

A feature flag is an on/off switch in code that lets you turn a feature on for some or all users without redeploying. It separates 'the code is live on servers' from 'users can see/use it.'

solid answer

~30 s

A feature flag is a runtime conditional (if flagIsOn(...)) wrapping a code path, controlled by a config value outside the binary. Deploying ships the code dark (flag off); releasing flips the flag on for chosen users, without a redeploy. This decouples deploy cadence (continuous, low-risk, reversible via rollback) from release cadence (business-controlled, targeted, instantly reversible via flag flip). It enables trunk-based development: merge incomplete work behind a flag instead of long-lived branches, avoid painful merge conflicts, and let ops kill a broken feature in seconds instead of waiting on a new deploy/rollback cycle.

go deeper

for a junior

Should describe the basic mechanism (an if/else driven by an external switch) and say in plain terms that it lets you ship code without showing it to users yet.

for a middle

Should articulate the deploy/release split explicitly, mention trunk-based development as the motivating workflow, and know that flags need to be removed eventually.

for a senior

Should discuss the cost side unprompted -- code complexity from combinatorial states, testing burden, evaluation-consistency risk within a session -- not just the benefits.

for a principal

Should connect flag practice to organizational velocity (why large orgs standardized on it) and articulate flag lifecycle as a first-class engineering process with ownership and expiry, not just a feature.

## What a feature flag is, mechanically A feature flag (also called a feature toggle) is a piece of runtime configuration -- typically a boolean or a multi-variant value stored outside the compiled binary, in a config service, database row, or file -- that a running program reads to decide which code path to execute. Mechanically the pattern is simple: instead of shipping code that always runs the new logic, the code becomes a conditional such as `if (flags.isEnabled("new-checkout")) { newCheckoutFlow() } else { oldCheckoutFlow() }`. - **Both paths ship together.** The old and the new code paths are compiled into the same artifact and deployed together. - **The flag-management system decides.** A flag-management system -- an in-process SDK talking to a flag service, or something as simple as an environment variable or a database row read on each request -- tells the running process, at evaluation time, which branch to take. - **Flipping takes effect within seconds.** Flipping the flag from off to on requires no new deploy, no new build, and -- because the SDK typically polls or streams updates -- takes effect within seconds across the fleet. ## Why the pattern exists: deploy is not release The reason this pattern exists is to break the coupling between two activities that traditional deployment conflates: **deploy** (get new code running on production infrastructure) and **release** (make a capability visible and usable to real users). Without flags those two events are the same act -- merging and shipping code IS exposing it. That forces teams into two bad habits: 1. They hold back a feature branch for weeks until it is fully done, fighting merge conflicts, drifting from main, blocking other changes that touch the same files. 2. They ship half-finished work live and hope nobody notices. Flags let engineers merge continuously to a trunk branch -- the core practice of **trunk-based development** -- landing incomplete or risky code behind a flag that defaults to off. The code is *dark launched*: it runs in production, exercised by CI/CD or even synthetic traffic, but real users never see it until someone with release authority, often a product manager rather than an engineer, flips the switch, independent of any deploy pipeline. ## The trade-off The trade-off cuts on both sides. On the benefit side: - Releases become instant and instantly reversible: flip the flag back off in seconds, versus a code rollback plus redeploy that can take minutes and re-introduces deploy risk. - Releases can be targeted -- turn a feature on for five percent of users, for internal staff only, for one customer's account -- instead of all-or-nothing. - Deploy risk is decoupled from release risk, so "ship early, release later" becomes normal. On the cost side: - Every flag is a second code path that must be tested, and a codebase that grows flags without discipline accumulates complexity: nested conditionals across flags produce a combinatorial set of states that are, in practice, never all tested. - Flags also introduce a new runtime dependency, the flag-evaluation call itself. If it is a network call on every request that adds latency and a new failure mode; if it is a local cached SDK, it adds a small memory and CPU footprint plus a staleness window between someone flipping the flag and a given server instance seeing the update. ## Failure modes Failure modes show up in a few characteristic ways. 1. **Flag debt**, the most common in production: nobody deletes the flag once the feature is fully rolled out and stable, so the codebase keeps carrying a dead conditional and a dead old-code-path indefinitely. 2. **Another failure mode, evaluation inconsistency**: if flag state is read fresh per-request without any pinning, the same user can see the old and new UI on different clicks within one session, which is confusing and can break stateful flows such as starting a checkout with the old flow's fields and submitting to the new flow's handler. 3. **A third** is the flag service itself being unavailable or slow -- does the SDK serve last-known-good state, or block? ## Where it shows up in the wild A concrete, well-known real-world example: LaunchDarkly (and similarly Unleash, Flagsmith, or Split) is built specifically around this deploy/release split -- teams merge to main continuously, deploy on every merge via CI/CD, and product owners control the actual customer-facing rollout from a dashboard, entirely decoupled from when engineering shipped the code. Netflix and Facebook popularized this pattern at scale specifically to let thousands of engineers ship to a shared trunk daily without every commit being an instant, all-or-nothing customer-facing event.

  • If a team never removes feature flags after a feature is fully rolled out, what specifically goes wrong in the codebase over time?
    Each dead flag leaves a permanent conditional branch that must still be read, tested, and reasoned about even though only one branch ever executes; with dozens of stale flags the number of theoretically possible code-path combinations explodes even though almost none are exercised, so tests and code review both slow down and confidence in 'that path is truly dead' erodes. It also makes the code harder to read since new engineers can't tell which branches are still in flight versus permanent.
  • How is 'deploy' different from 'release' in this model, concretely, in terms of who controls each and how they're reversed?
    Deploy is an engineering action, gated by CI/CD and code review, and reversed with a rollback/redeploy of the binary. Release is a product/business action, gated by whoever owns the flag dashboard, and reversed instantly by flipping the flag back off with no redeploy needed at all. Separating them means a broken release can be undone in seconds, while deploys can stay frequent and low-drama because they no longer equal going live.
  • Why does dark-launching new code (deployed, flag off) still carry any production risk at all if users can't see it?
    The new code still runs -- for example background jobs, schema migrations it triggers, or code paths hit by internal or synthetic traffic -- so it can still consume resources, throw exceptions into logs and alerts, or contend for locks and connections even while flagged off for real users. A completely inert flag is only truly zero-risk if the conditional short-circuits before touching any shared resource.

Like a light switch wired to a bulb that's already installed and wired up: installing the bulb (deploying) and turning the room's light on for guests (releasing) are two separate, independently reversible actions.

saying these in an interview costs you the question

  • Says a feature flag and an environment variable/config value are the same thing with no distinction from deploy/release
  • Thinks flipping a flag requires a new deployment
  • Can't explain who typically controls the flag flip (product) versus who deploys the code (engineering)
  • Assumes flags have no ongoing maintenance cost once shipped
  • Conflates 'the code is running' with 'users can see it'

context

open as a page

Feature flags are often grouped into categories such as release flags, ops or kill-switch flags, experiment flags, and permission flags. What distinguishes these categories, and why does each need a different lifecycle or cleanup policy?

level: middleimportance: must knowfreq 70%

basics

~20 s

Not all flags are used the same way: some hide a feature until it's ready (release), some let you turn something off in an emergency (ops), some split traffic to compare two versions (experiment), and some control who is allowed to use a feature long-term (permission). Because they serve different purposes, some should be deleted quickly and others are meant to live forever.

open as a page

When a feature flag system does a percentage rollout, say enabling a flag for 10% of users, how does it decide which specific users fall in that 10%, and why must that decision be consistent across repeated evaluations for the same user rather than random each time?

level: middleimportance: must knowfreq 65%

basics

~20 s

The system turns each user's ID into a number (via a hash) and checks if that number falls under the 10% cutoff. Because the same ID always hashes to the same number, the same user always lands on the same side of the line, so they don't flicker between old and new experience.

open as a page

Why does flag debt accumulate in a codebase over time even on disciplined teams, and what concrete engineering practices keep it from becoming a serious liability?

level: seniorimportance: should knowfreq 50%

basics

~20 s

Every flag adds an extra code path, and it's easy to add a flag but nobody's job to remove it later, so old, forgotten flags pile up. Teams fight this with expiry dates, dashboards showing stale flags, and treating flag removal as a normal, required step of finishing a feature.

open as a page

If the feature-flag evaluation service itself becomes unreachable or slow, what should a client SDK do, and how does the answer differ between a flag guarding a nice-to-have feature versus a flag acting as a kill switch for a risky dependency?

level: seniorimportance: should knowfreq 55%

basics

~20 s

If the flag system can't be reached, the app should fall back to a safe default instead of crashing or hanging, usually the last value it knew, cached locally. For most features, safe means off; for a kill switch protecting against a broken dependency, safe might mean staying off (fail closed) so the risky code never runs by accident.

open as a page

When a feature flag has multiple targeting rules, for example always off for free-tier users, always on for internal staff, and a 50% rollout for everyone else, how does a flag evaluation engine typically resolve conflicts between rules, and what architectural trade-offs come from evaluating those rules client-side in a browser or mobile SDK versus server-side?

level: principalimportance: should knowfreq 40%

basics

~20 s

Targeting rules are usually checked in order, top to bottom, and the first one that matches a user wins, so rule order matters a lot. Doing that check in the browser or app is fast but exposes your rules and upcoming features to anyone who inspects the app; doing it on your server keeps rules private but adds a network step.

open as a page