--- id: wiki-2026-0508-feature-flags title: Feature Flags category: 10_Wiki/Topics status: verified canonical_id: self aliases: [Feature Toggles, Feature Switches, Feature Gates] duplicate_of: none source_trust_level: A confidence_score: 0.9 verification_status: applied tags: [devops, deployment, experimentation, release-engineering] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: TypeScript/Go framework: LaunchDarkly/Unleash/OpenFeature --- # Feature Flags ## 매 한 줄 > **"매 deploy 와 release 를 매 분리하는 runtime conditional"**. Pete Hodgson 의 매 4-axis taxonomy (release/experiment/ops/permission) 가 매 baseline. 매 modern stack — OpenFeature spec + provider (LaunchDarkly, Unleash, ConfigCat, Statsig) — 매 progressive delivery, A/B test, kill switch 의 매 통합 layer. ## 매 핵심 ### 매 4 종류 (Hodgson) - **Release toggle**: dark launch, gradual rollout (short-lived). - **Experiment toggle**: A/B/n test (medium-lived). - **Ops toggle**: kill switch, circuit breaker (medium-lived). - **Permission toggle**: per-user/tenant entitlement (long-lived). ### 매 axis - Lifetime: hours ↔ years. - Dynamism: build-time → runtime → request-time. - Scope: global → user → request. ### 매 응용 1. Trunk-based development + dark launch. 2. Canary / progressive rollout (1% → 100%). 3. Kill switch (incident mitigation). 4. A/B testing & holdout group. 5. Tier-based feature gating (free/pro/enterprise). ## 💻 패턴 ### OpenFeature SDK (vendor-neutral) ```typescript import { OpenFeature } from '@openfeature/server-sdk'; import { LaunchDarklyProvider } from '@openfeature/launchdarkly-server-provider'; await OpenFeature.setProviderAndWait(new LaunchDarklyProvider(SDK_KEY)); const client = OpenFeature.getClient(); const showNew = await client.getBooleanValue('new-checkout', false, { targetingKey: user.id, email: user.email, plan: user.plan, }); return showNew ? renderNewCheckout() : renderOldCheckout(); ``` ### Percentage rollout (deterministic hash) ```go import "hash/fnv" func rollout(flagKey, userID string, percent int) bool { h := fnv.New32a() h.Write([]byte(flagKey + ":" + userID)) return int(h.Sum32()%100) < percent } // Same user → same bucket across calls (sticky). ``` ### Kill switch (ops toggle) ```typescript async function fetchRecommendations(userId: string) { if (await flags.getBooleanValue('reco-kill-switch', false)) { return []; // disable the feature instantly during incident } return recoService.fetch(userId); } ``` ### Multivariate experiment ```typescript const variant = await client.getStringValue('checkout-variant', 'control', ctx); switch (variant) { case 'one-click': return ; case 'wallet': return ; default: return ; } metrics.track('checkout_view', { variant, userId }); ``` ### Local override (dev/test) ```typescript if (process.env.NODE_ENV === 'development') { OpenFeature.setProvider(new InMemoryProvider({ 'new-checkout': { defaultVariant: 'on', variants: { on: true, off: false } }, })); } ``` ### Flag cleanup (technical debt) ```bash # Find old flags rg "getBooleanValue\\('old-checkout'" --type ts # Provider audit: list flags > 90 days old, no recent eval, 100% rollout → delete. ``` ## 매 결정 기준 | 상황 | Approach | |---|---| | Dark launch / gradual | Release toggle, percentage rollout | | Hypothesis test | Experiment toggle + analytics | | Incident mitigation | Ops toggle (always available) | | Tier / paid features | Permission toggle (long-lived) | | Build-time only | Compile flag (no runtime cost) | **기본값**: OpenFeature SDK + managed provider (LaunchDarkly/Unleash). Kill switch 모든 critical path 에 매. ## 🔗 Graph - 부모: [[Continuous Delivery]] · [[Progressive Delivery]] - 변형: [[Kill Switch]] - 응용: [[Trunk-based Development]] - Adjacent: [[LaunchDarkly]] · [[Unleash]] ## 🤖 LLM 활용 **언제**: Release strategy 설계, incident playbook, experiment platform 평가. **언제 X**: Static config — env var / config file 충분. ## ❌ 안티패턴 - **Flag debt**: 100% rolled-out flag 를 매 안 지움 → cyclomatic complexity 폭발. - **Nested flags**: A&&B&&C — 매 test space 매 explosion. - **Flag in hot loop**: per-request eval 의 매 latency — cache locally. - **No fallback**: provider 다운 시 feature 깨짐 — default + cached value. - **Flag = config 오용**: 진짜 config 는 매 config service 로. - **No analytics linkage**: experiment 인데 evaluation 안 records. ## 🧪 검증 / 중복 - Verified (martinfowler.com Feature Toggles, OpenFeature spec, LaunchDarkly docs). - 신뢰도 A. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — 4-axis taxonomy + OpenFeature/percentage/kill-switch 패턴 |