Topic 6.3
Approvals, Environment Gating & Feature Flags Together
In one line
Manual approvals (Phase 2.2, Phase 4.3) and feature flags (Topic 6.1) solve genuinely complementary problems — combining them gives a team both a fast, automatic deployment pipeline and deliberate, human-controlled feature releases.
Key ideas
- 01
This topic combines two ideas already introduced separately — Phase 2.2 and Phase 4.3's platform-specific manual approval mechanisms, and Topic 6.1's feature-flag concept — into one coherent, genuinely practical release strategy many mature real teams actually use.
- 02
The key realization: DEPLOYING and RELEASING are two genuinely separate actions that most teams historically conflated into one — deploying puts new code onto production infrastructure; releasing makes that code's new functionality actually visible and active for real users. A manual approval gate controls the first; a feature flag controls the second, and they don't have to happen at the same time at all.
- 03
A genuinely common, mature pattern: deploy new code to production AUTOMATICALLY and continuously (fast, low-risk, since the new functionality stays behind a flag, DORMANT and inactive by default) while the actual FEATURE RELEASE — flipping the flag on for real users — remains a genuinely deliberate, separate, human-controlled action, entirely decoupled from the deployment pipeline's own automatic cadence.
- 04
This lets a team get almost all of Continuous Deployment's speed benefit (Topic 6.1) for the DEPLOYMENT half, while keeping genuine, deliberate human judgment for the RELEASE half — often with much finer control than a simple on/off manual pipeline gate provides, since a flag can be enabled for a genuinely small percentage of real users first (a form of canary release, Topic 6.2, but controlled entirely at the APPLICATION level rather than infrastructure traffic-splitting).
- 05
Feature flags also enable genuinely fast, INSTANT rollback of a problematic FEATURE specifically — flipping a flag back off takes effect immediately, with no new deployment, no pipeline run, and no infrastructure change needed at all — often meaningfully faster than any infrastructure-level rollback mechanism (Kubernetes'
rollout undo, Helm'srollback), since it requires no new artifact to actually deploy anywhere. - 06
The genuine trade-off this topic surfaces: feature flags add real code-level complexity (conditional logic checking a flag's state, and eventually, genuine technical debt from flags that were never cleaned up after a feature became permanent) — a team should have a real, deliberate process for REMOVING a flag once a feature is fully, permanently released, rather than letting dormant, forgotten flags accumulate indefinitely in the codebase.
Code & diagrams
Two genuinely separate decisions, controlled by two genuinely separate mechanisms.
The application-level check that makes deploy and release genuinely independent.
// Deployed to production immediately via the automated pipeline —
// but genuinely inactive for every user until the flag is explicitly enabled
if (featureFlags.isEnabled("new-checkout-flow", currentUser)) {
return newCheckoutFlow.process(order);
} else {
return legacyCheckoutFlow.process(order);
}
// A feature flag service can enable this for:
// - nobody (fully dormant, safest default after deployment)
// - internal team members only (early, low-risk validation)
// - 5% of real users (a genuine canary, controlled at the app level)
// - 100% of users (fully released — the flag can now be removed)Explain it without notes
Why does separating 'deploying code' from 'releasing a feature' let a team deploy more frequently and confidently than when the two are conflated into one action?
Why can flipping a feature flag off often resolve a problem faster than any infrastructure-level rollback mechanism?
Practice
For a hypothetical new feature, sketch how you would deploy it behind a flag, roll it out to an increasing percentage of users over time, and what your plan would be for eventually removing the flag once fully released.
Explain, in one sentence, the genuine risk of a codebase accumulating many feature flags that were never removed after their features became permanent.
Trade-offs
- ↔
Feature flags provide genuinely powerful decoupling and instant rollback, but they add real ongoing complexity to a codebase (every flag is a conditional branch, and eventually a piece of technical debt if not cleaned up) — a small team or a low-stakes feature may reasonably decide a simple, direct deployment without a flag is genuinely simpler and not worth this added machinery, reserving feature flags specifically for changes where the gradual-rollout and instant-rollback benefits clearly outweigh the added code complexity.
Done when you can
I understand the genuine distinction between deploying code and releasing a feature to users.
I can explain why decoupling the two with a feature flag lets a team deploy more frequently and confidently.
I understand the real cost of feature flags (code complexity, technical debt) and why they need a deliberate removal process.