There’s a pattern almost every flag-heavy codebase ends up with: one flag that should only be considered if another flag is already on. The new checkout flow needs the new payment form. The enterprise analytics view needs the customer to be on the enterprise plan. The migration to the new database backs the half-dozen features that read from it. Until now, that gating lived in your application code — if (parent) { check child } — and drifted across services as the parent’s targeting changed. As of this week, it doesn’t have to.
Prerequisite flags are now first-class in Featureflip. A child flag declares the parent it depends on and the variation that parent must serve, and the platform enforces the dependency before any of the child’s targeting rules run. The gating logic moves out of your application and into the flag itself.
Key Takeaways
- Prerequisites are variation-match: the child only fires when the parent serves the specific variation you name. That makes them work for multivariate plan flags, not just on/off booleans.
- The dependency lives in the platform, not in your code. Parent targeting changes automatically flow through to every dependent flag.
- When a prerequisite gates a child off, the SDK tells you which parent did it — debuggable from a single log line, no server round-trip.
- For teams evaluating Featureflip against LaunchDarkly or ConfigCat, prerequisite flags now migrate 1:1.
Three places prerequisites earn their keep
Most of the value lands in three patterns that come up over and over once a team has the construct.
Coordinated feature rollouts
You’re rolling out a new checkout flow. The new payment form, the redesigned receipt email, and the rewritten order confirmation page all need to fire together — or none of them should. Without prerequisites, each child flag has to duplicate the parent’s targeting (country == US AND plan == enterprise AND beta_opt_in == true), and the moment that targeting drifts in any one of the three, the user experience splinters. With prerequisites, the children declare new-checkout-v2 = on and the parent owns the rollout schedule on its own. When you ramp the parent from 1% to 10% to 100%, every dependent ramps with it automatically.
Plan-tier entitlements
A SaaS product typically has a flag per gated feature — advanced analytics, SSO, custom domains — plus a parent flag that names the plan tier. Each entitlement declares the plan-tier flag as a prerequisite. When a customer downgrades, the parent’s targeting flips, and every entitlement under it falls back to off in the same evaluation cycle. No per-flag plumbing, no nightly reconciliation job, no risk of one entitlement staying enabled because someone forgot to update its rule. Variation-match earns its design here: a multi-tier plan flag can have entitlements that require specifically enterprise, others that require pro-or-higher (via a separate parent), all on the same flag graph.
Cutovers and kill switches
Migrating from one backend to another — a database, a payment processor, a recommendation engine? Make the migration flag the parent, and every read-path and write-path feature that depends on the new backend declares the migration flag as a prerequisite. The cutover becomes one flip on the parent. The kill switch — rolling back to the old backend — is also one flip, and you don’t have to maintain N rollback procedures for the N features that touched the new path.
How they work, briefly
A prerequisite is two strings: the parent flag’s key, and the variation the parent must serve. Each flag environment configuration carries an ordered collection of them, alongside its targeting rules and fallthrough.
When a child flag is evaluated, the platform walks its prerequisites in order. For each one, it evaluates the parent against the same user context, compares the served variation to the expected variation, and short-circuits to the child’s off variation if they don’t match. Only if every prerequisite passes does the evaluator run the child’s targeting rules. The same algorithm runs server-side in the Evaluation API and locally in every server-side SDK (JS, Python, Go, Java, C#, Ruby, PHP), so a flag check returns the same answer no matter where it runs.
A few guardrails are worth knowing about, even if you never touch them directly. Cycles — A → B → A — are blocked at save time, with the offending chain printed back in the error. You can’t delete a flag (or remove a variation) that other flags depend on; the API names the dependents so you know exactly what to unwire first. And there’s a hard depth cap of 10 on prerequisite chains, well above what any realistic dependency graph needs, as a safety net.
What it looks like from the SDK
Most application code picks up prerequisite behavior automatically — the prerequisites are enforced inside the evaluator before any variation is selected, so boolVariation, stringVariation, and friends keep working unchanged. The new surface is the evaluation reason, which now tells you when a prerequisite gated a flag off and which parent did it:
import { FeatureflipClient, createNodePlatform } from '@featureflip/sdk';
const client = FeatureflipClient.get( { sdkKey: process.env.FEATUREFLIP_SDK_KEY!, baseUrl: 'https://eval.featureflip.io' }, createNodePlatform(),);await client.waitForInitialization();
const context = { user_id: 'user_42', plan: 'pro' };const detail = client.variationDetail('beta-checkout', context, false);
if (detail.reason === 'PrerequisiteFailed') { console.log(`beta-checkout gated off by ${detail.prerequisiteKey}`);} else if (detail.value === true) { renderNewCheckout();}That prerequisiteKey field is the piece that closes the debuggability gap. With the application-side workaround, the symptom of a misfiring gate was usually “the child flag isn’t doing what I expected” — and the engineer reading the dashboard saw a child whose rules all evaluated cleanly, with no indication that the real reason was something on a parent flag. The first-class construct names the parent explicitly, in the same evaluation detail your application already has access to.
Editing prerequisites in the dashboard
The flag editor in the web app exposes a “Prerequisites” section beneath the targeting rules. Each row is two dropdowns: pick the parent flag, then pick the variation it must serve. The variation list re-populates when you change the parent, so it never goes stale against the parent’s current variations.
The two failure cases — cycles and dependent-blocking deletes — render inline rather than as opaque API errors. If you try to save a prerequisite that would create a loop, the form shows you the chain (flag-a → flag-b → flag-a) and refuses. If you try to delete a flag or remove a variation that other flags depend on, the response includes the dependent flag keys so you can navigate to each one and unwire it before retrying.
Migrating from LaunchDarkly or ConfigCat
Prerequisite flags were one of two surfaces that previously required hand-rework when migrating to Featureflip from either platform. That changes with this release.
LaunchDarkly’s prerequisite model is variation-match, the same shape as Featureflip’s. A migration script that walks a LaunchDarkly project export and produces equivalent Featureflip prerequisites is a couple of dozen lines of field-name translation, not a redesign.
ConfigCat’s prerequisite flag is also variation-match and migrates the same way. The one structural difference: ConfigCat supports an explicit “does not equal” comparator on prerequisites; Featureflip only supports “equals” (matching LaunchDarkly’s semantics). If you have prerequisites in ConfigCat that use “does not equal”, you’ll express them in Featureflip by inverting the expected variation — usually a small refactor on a small subset of flags, not a project-wide rewrite.
For procurement-gated buyers, this matters because prerequisite flags were one of the named items on the “missing feature” list. They’re not on that list anymore.
Frequently asked questions
What’s the difference between a prerequisite and a targeting rule?
A targeting rule decides what variation to serve based on context attributes (country, plan, user ID). A prerequisite decides whether to consider serving anything other than off, based on another flag’s result. Prerequisites run before targeting rules; if any prerequisite fails, the targeting rules never get a chance to fire.
Can prerequisite flags create infinite loops?
No. Cycles are detected at save time and rejected with the offending chain (flag-a → flag-b → flag-a) returned in the error response. There’s a depth cap of 10 on the evaluator as a defense-in-depth safety net, but the primary defense is structural: the API won’t accept a config that would create a loop.
How deep can a prerequisite chain go?
The hard limit is 10, and in practice most production flag graphs are 1–3 deep. If you’re approaching the limit, that’s usually a signal to flatten the dependency structure — one parent with several direct dependents tends to be cleaner than a long chain.
What happens to dependent flags when I disable the parent?
The dependent flags serve their off variations with the evaluation reason set to PrerequisiteFailed (or the equivalent per-SDK casing), and prerequisiteKey names the parent that gated the child off. This is the same behavior you’d get if the parent simply served a variation that the child’s prerequisite didn’t expect.
Can I delete a flag that other flags depend on?
Not until the dependents drop their references. The API returns a 400 with code FLAG_HAS_DEPENDENTS and the list of dependent flag keys, and the web UI renders the list so you can navigate to each one and remove the prerequisite. The same guard applies to removing a variation that other flags expect.
Try it
The fastest way to see prerequisites in action is to start a Solo project — free forever for one project — create two flags, and reference one from the other in the new Prerequisites section of the flag editor. The full evaluation reason surfaces on variationDetail from the first flag check, so you can confirm the gating live without instrumenting anything.
Prerequisites slot in alongside the rest of the targeting and segmentation surface. The broader question of when to add a flag at all — and how to keep your flag practice healthy — is covered in the broader best-practices pillar, the feature flag cleanup playbook, and the feature flag anti-patterns post.