← Flutter Reference

Feature Flags vs A/B Testing

Growth

By Abdelrahman Saed — Senior Mobile Engineer. Last updated: 2026-08-10.

Quick answer

Feature flags control who can see a feature (release governance). A/B testing measures which variant performs better (experimentation). They overlap — an A/B test is often implemented using feature flags — but they are different tools with different jobs. Conflating them leads to shipping flags without metrics, or running tests without rollout safety.

Use feature flags for trunk-based development, dark launches, staged rollouts, and kill switches. Use A/B testing when you have a metric you want to move and a hypothesis about how. In practice: flag every non-trivial feature, and A/B test only where you have the volume and a clear success metric.

Feature comparison

FeatureFeature FlagsA/B Testing
PurposeRelease control / governanceExperimentation / learning
Question answeredWho sees this?Which variant wins?
VariantsOn/off, %, audience2+ randomized cohorts
Needs metricsNo (often watches crashes)Yes (primary success metric)
Statistical rigorNone neededSignificance testing
Typical durationDays to weeks (rollout)Until significance reached
CleanupRemove flag at 100%Ship winner, delete loser
OverlapUsed to implement A/B testsImplemented via flags
Best forTrunk-based, dark launches, kill switchesConversion, retention optimization

Detailed comparison

What each solves

Feature flags decouple deployment from release. You merge code to main (deployed) but keep a feature off for users until it is ready (released). Variants: on/off, percentage rollout, audience targeting, kill switch. The goal is safety and control.

A/B testing compares two or more variants against a success metric (conversion, retention, click-through). Users are randomized into cohorts, you collect telemetry, and a statistical test decides whether the difference is significant. The goal is learning.

An A/B test is often implemented with a feature flag (flag returns variant A or B), which is why people conflate them. But a flag without measurement is just a rollout tool, and a measurement without controlled rollout is just analytics.

When to flag without testing

Most flags are not experiments. You flag a risky refactor to roll out to 1% then 10% then 100%, watching crash rates — that is release governance, not an experiment. You flag a feature dark-launched behind a toggle so you can turn it off without a hotfix — that is a kill switch. Trunk-based development depends on this: incomplete features merge to main behind a flag.

When to A/B test

A/B testing is worth it when: you have enough users to reach statistical significance in a reasonable time, you have a clear primary metric, and the change is consequential enough to justify the rigor. Small UI tweaks on a 5M-user app? Worth testing. Niche B2B feature with 200 users? Probably not — just ship it and watch qualitatively.

The trap: flags as permanent config

The most common failure mode is flags that never get cleaned up. A flag added for a rollout stays in the codebase for years, branching logic accumulating. Pair every flag with a removal ticket once it reaches 100%. The same applies to concluded A/B tests — ship the winner and delete the loser variant.

Tooling

Feature flags: GrowthBook, LaunchDarkly, Firebase Remote Config, PostHog, or a homegrown config service. A/B testing: the same tools often do both (GrowthBook, PostHog, Firebase A/B testing). At the app layer, a flag-service abstraction lets you swap providers.

Code comparison

Feature flag — staged rollout (no measurement)

final flag = await flagService.eval('new_checkout', user: currentUser);
// flagService controls % rollout + audience targeting
if (flag.enabled) {
  return NewCheckoutFlow();
} else {
  return LegacyCheckoutFlow();
}

A/B test — randomized variant + metric tracking

final variant = await experiment.assign(
  'checkout_redesign_v2',
  user: currentUser,
  // variants: 'control' | 'treatment'
);

// track the primary metric on conversion
analytics.capture('checkout_completed', {
  'experiment': 'checkout_redesign_v2',
  'variant': variant,
  'value_usd': order.total,
});

return variant == 'treatment' ? NewCheckoutFlow() : LegacyCheckoutFlow();

The flag version gates access. The experiment version randomizes and instruments. Same plumbing, different intent — and the experiment only means something if you have the volume and a defined metric.

Which should you choose?

Choose feature flags when: you practice trunk-based development, you want to decouple deploy from release, you need staged rollouts or kill switches, or you are dark-launching a risky change. This is a release-engineering tool — default to flagging non-trivial features.

Choose A/B testing when: you have a clear success metric, enough users to reach significance, a hypothesis about user behavior, and the change is consequential. Not every flag needs a test — test where the decision is genuinely uncertain and measurable.

Related definitions

Related reading

FAQ

Do I need a fancy tool for feature flags?

No. A simple remote config (Firebase Remote Config, a JSON file on a CDN, PostHog) works for most apps. You need a flag service when you want fine-grained audience targeting, instant kill switches, or experimentation layered on top. Start simple; adopt a platform when pain demands it.

When is A/B testing a waste of time?

When you lack the user volume to reach significance, when you have no clear primary metric, or when the change is obviously better (accessibility fixes, crash fixes). Testing for the sake of testing burns engineering time and produces noise.

Should every flag be cleaned up?

Yes. Every rollout flag should have a removal ticket once it reaches 100%. Accumulated flags create branching debt that makes the codebase harder to reason about. Concluded experiments should ship the winner and delete the loser.

Can I run an A/B test without a dedicated experimentation platform?

Yes for simple cases — assign a variant based on a stable user ID hash (so the same user always sees the same variant), log the assignment and the outcome metric to your analytics (PostHog, Amplitude, Firebase Analytics), and run a chi-square or t-test yourself once you have enough samples. This is fine for one-off tests. You need a real platform (GrowthBook, PostHog Experiments, LaunchDarkly) when you want automatic significance calculation, mutual exclusion between concurrent experiments, and audience targeting without hand-rolling the bucketing logic.


Available for hire. Abdelrahman Saed is a Senior Mobile Engineer (Flutter) — open to full-time, fractional, contract, or advisory work. Hire me →

Book a 20-minute call · Download the CV (PDF) · See how I work