feature-flags
Feature flag patterns. Gradual rollouts, A/B testing, kill switches, LaunchDarkly, environment flags.
소스 정보
- 저장소
- skeletorflet/opencode-kit
- 최근 소스 활동
- 2026년 4월 3일 15:32
- 감지된 SKILL.md 언어
- 영어
- 스타
- 9
- 포크
- 1
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
SKILL.md 표시 중
SKILL.md
소스 지침 · 읽기 전용 미리보기- name
- feature-flags
- description
- Feature flag patterns. Gradual rollouts, A/B testing, kill switches, LaunchDarkly, environment flags.
# Feature Flags
> Ship safely. Separate deployment from release.
---
## 1. Types of Feature Flags
| Type | Purpose | Lifetime |
|------|---------|---------|
| **Release toggle** | Gradual rollout, hide incomplete | Days–weeks |
| **Experiment toggle** | A/B testing | Duration of test |
| **Ops toggle** | Kill switch, circuit breaker | Indefinite |
| **Permission toggle** | Feature per plan/role | Indefinite |
| **Config flag** | Dynamic configuration | Indefinite |
---
## 2. Implementation Approaches
| Approach | When |
|----------|------|
| Environment variables | Simple, per-deployment |
| Database flags | Dynamic, no redeploy |
| Redis flags | Fast reads, dynamic |
| Managed service (LaunchDarkly, Unleash) | Complex targeting |
---
## 3. Simple Implementation (DB + Redis)
```ts
// Schema
model FeatureFlag {
key String @id
enabled Boolean @default(false)
rolloutPct Int @default(0) // 0-100
allowList String[] @default([]) // User IDs
updatedAt DateTime @updatedAt
}
// Flag evaluation
async function isEnabled(flagKey: string, userId?: string): Promise<boolean> {
const cached = await redis.get(`flag:${flagKey}`);
const flag: FeatureFlag = cached ? JSON.parse(cached) : await loadFromDB(flagKey);
if (!flag || !flag.enabled) return false;
// Allow list
if (userId && flag.allowList.includes(userId)) return true;
// Percentage rollout (consistent per user)
if (flag.rolloutPct > 0 && userId) {
const hash = murmurhash(`${flagKey}:${userId}`) % 100;
return hash < flag.rolloutPct;
}
return flag.rolloutPct === 100;
}
```
---
## 4. LaunchDarkly Integration
```ts
import { init } from "launchdarkly-node-server-sdk";
const client = init(process.env.LAUNCHDARKLY_SDK_KEY!);
await client.waitForInitialization();
// Evaluate flag with user context
const enabled = await client.variation("new-checkout", {
key: user.id,
email: user.email,
country: user.country,
plan: user.plan,
}, false); // default value
if (enabled) {
return <NewCheckout />;
} else {
return <OldCheckout />;
}
```
---
## 5. React Hook
```tsx
function useFeatureFlag(key: string): boolean {
const { data } = useQuery({
queryKey: ["flags", key],
queryFn: () => fetchFlag(key),
staleTime: 60_000, // 1 min
});
return data?.enabled ?? false;
}
// Usage
function Checkout() {
const newCheckout = useFeatureFlag("new-checkout");
return newCheckout ? <NewCheckout /> : <OldCheckout />;
}
```
---
## 6. Gradual Rollout Strategy
```
Rollout stages:
0% → Deployed but hidden (dark launch)
1% → Canary (catch crashes)
10% → Limited beta
25% → Wider test
50% → Half users
100% → Full release
Flag deleted → Code cleaned up
Monitor per stage:
- Error rate
- Latency
- Business metrics
- User feedback
```
---
## 7. Flag Management Rules
```
Lifecycle rules:
├── Every flag has an owner + expiry date
├── Release flags: delete after 2 weeks of 100% rollout
├── Experiment flags: delete after analysis
├── Name: {domain}.{feature} (e.g. checkout.new-flow)
└── Document purpose in flag description
Tech debt prevention:
├── Track flags in JIRA/Linear ticket
├── PR to remove flag after release
└── Alert when flag older than 90 days
```
---
## 8. Kill Switch Pattern
```ts
// Ops toggle for circuit breaker
const USE_STRIPE = isEnabled("payments.stripe");
const USE_PAYPAL_FALLBACK = isEnabled("payments.paypal-fallback");
async function processPayment(order: Order) {
if (USE_STRIPE) {
return await stripeCharge(order);
}
if (USE_PAYPAL_FALLBACK) {
return await paypalCharge(order);
}
throw new Error("No payment provider available");
}
```
---
## 9. Anti-Patterns
| ❌ Don\'t | ✅ Do |
|----------|-------|
| Nested flag conditions | One flag, one decision |
| Flags forever | Set expiry, clean up |
| No monitoring | Track flag evaluation metrics |
| Flag in wrong layer | Evaluate server-side for security |
| Hardcoded user lists | Use targeting rules |
GitHub에서 보기