界面已本地化;技能介绍与说明文档按所选语言由 AI 自动翻译,代码、命令、路径和专业术语保留原文,以原作者文档为准。
探索技能
部署与运维 · SKILL.md

workflow-feature-flag

workflow-feature-flag

【部署与运维】Plan and run a feature-flag rollout. Use when "add a feature flag", "gradual rollout", "staged release", "kill switch", "dark launch", "flag cleanup", "canary release", "rollback plan", or "deploy without switching on".

独立 GitHub 快照 · 自动分类 · 以原作者文档为准

技能说明

GitHub

name: workflow-feature-flag description: > Plan and run a feature-flag rollout. Use when "add a feature flag", "gradual rollout", "staged release", "kill switch", "dark launch", "flag cleanup", "canary release", "rollback plan", or "deploy without switching on". license: MIT

workflow-feature-flag — Gate → Rollout → Monitor → Promote or Rollback

Degree of freedom: MIXED. Who is in the cohort and when to promote [HIGH freedom]; default-off, kill switch, and cleanup [LOW freedom — run exactly].

How to reason

  1. Observe — existing flag infra, default, targeting, metrics
  2. Interpret — deploy vs enable; who can be hurt if this is wrong
  3. Classify — dark launch / percent rollout / kill / promote / cleanup
  4. Severity — a default-on flag in prod is a failed gate

Worked example

Observe: new checkout step; no flag library; 100% of traffic would hit it on deploy. Interpret: ship dark, enable 5%, watch payment errors. Classify: add default-off flag + kill switch; do not delete the old path yet. Monitor: error rate > baseline → kill; stable → promote and remove the flag.

Self-critique before reporting

  • Default off — merge does not enable the feature
  • Kill exists — one switch turns it off without a rollback deploy
  • Cleanup named — flag removal is a tracked follow-through, not forgotten
  • Right owner — npm package publish → deploy-npm; observe window → workflow-ship-and-observe

Shipping code and switching it on are two separate acts. A feature flag lets you deploy on your schedule, enable for specific users or a percentage of traffic, and kill it instantly if anything goes wrong — without a rollback deploy. This skill gives that discipline to any feature.


Phase 0: Detect existing flag infrastructure [LOW freedom — run exactly]

package.json         → launchdarkly-node-server-sdk, @launchdarkly/js-client-sdk,
                       flagsmith, growthbook, unleash-client, posthog-js
.env.*               → LD_SDK_KEY, FLAGSMITH_ENV_KEY, GROWTHBOOK_API_HOST,
                       POSTHOG_KEY (reference by name only)
src/lib/flags.*      → custom feature-flag utility
src/config/flags.*   → env-var-based flags
Detected platformApproach
LaunchDarklyUse LD SDK client; flags managed in LD dashboard
PostHogUse PostHog feature flags API; tied to analytics context
GrowthBookOpen-source, self-hosted or cloud; SDK + feature API
FlagsmithOpen-source or cloud; REST API + SDK
None / customSimple env-var or database-backed flag (implement below)

Phase 1: Design the flag [HIGH freedom]

Before writing any code, define the flag contract:

Flag name:    [kebab-case, descriptive, present-tense: "new-checkout-flow"]
Description:  [What this flag controls — plain English]
Type:         Boolean / String variant / JSON payload
Targeting:    [Who sees it first: internal users? 5% of traffic? specific org IDs?]
Rollout plan: 0% → internal only → 5% → 25% → 100%
Kill-switch:  If Sentry error rate on [metric] exceeds [threshold], roll back to 0%
Cleanup date: [When to remove the flag — typically 2 weeks after 100% stable]

Naming rules:

  • kebab-case, present-tense action: new-checkout-flow, not checkoutV2 or feature123
  • Include the domain: billing-usage-dashboard, auth-passkey-login
  • No generic names like beta, v2, new-feature — they become permanent accidents

Phase 2: Implement the flag gate [LOW freedom — run exactly]

Option A: Simple env-var flag (no external service)

// src/lib/flags.ts
export const FLAGS = {
  newCheckoutFlow: process.env.NEXT_PUBLIC_FLAG_NEW_CHECKOUT_FLOW === 'true',
  billingUsageDashboard: process.env.NEXT_PUBLIC_FLAG_BILLING_USAGE_DASHBOARD === 'true',
} as const;

export type FeatureFlag = keyof typeof FLAGS;

Usage:

import { FLAGS } from '@/lib/flags';
if (FLAGS.newCheckoutFlow) {
  return <NewCheckoutFlow />;
}
return <LegacyCheckoutFlow />;

For server-side percentage rollout without a vendor, use a hash of the user ID:

function isInRollout(userId: string, flagName: string, percentage: number): boolean {
  const hash = parseInt(
    require('crypto').createHash('md5')
      .update(`${userId}:${flagName}`)
      .digest('hex').slice(0, 8),
    16,
  );
  return (hash % 100) < percentage;
}

Option B: PostHog flags (already in the stack)

import { useFeatureFlagEnabled } from 'posthog-js/react';

function CheckoutPage() {
  const useNewFlow = useFeatureFlagEnabled('new-checkout-flow');
  if (useNewFlow) return <NewCheckoutFlow />;
  return <LegacyCheckoutFlow />;
}

Server-side (Next.js Server Component):

import { PostHog } from 'posthog-node';
const client = new PostHog(process.env.POSTHOG_KEY!);
const isEnabled = await client.isFeatureEnabled('new-checkout-flow', userId);

Option C: LaunchDarkly

import { useFlags } from 'launchdarkly-react-client-sdk';
const { newCheckoutFlow } = useFlags();

Phase 3: Stage the rollout [LOW freedom — run exactly]

Step 1: Internal only (0% of real users)

Set the flag enabled only for internal team accounts / test emails. Verify the feature works end-to-end for the team.

Check for errors in Sentry immediately after enabling:

sentry:search_issues
{
  "organizationSlug": "<ORG>",
  "query": "new issues in the last 1 hour",
  "projectSlugOrId": "<PROJECT>",
  "regionUrl": "<REGION_URL>",
  "limit": 10
}

Step 2: 5% rollout

Enable for 5% of real users (random cohort). Monitor for 24–48 hours.

Define the health gates before enabling:

  • Error rate for the flagged feature path must stay < baseline + 0.5%
  • P95 response time must stay < baseline + 200 ms
  • No new Critical/High Sentry issues

Check Supabase logs for unexpected errors:

supabase:query_logs
{
  "sql": "select timestamp, event_message, log_attributes['request.method'] as method, log_attributes['request.path'] as path, log_attributes['response.status_code'] as status_code from logs where source = 'edge_logs' order by timestamp desc limit 100"
}

Step 3: 25% → 50% → 100%

Each step: enable, wait 24 h, check Sentry + Supabase + business metrics. Only proceed when the health gates are green.


Phase 4: Rollback procedure [LOW freedom — run exactly]

If any health gate fails at any stage:

  1. Set the flag to 0% immediately (no deploy needed — this is the whole point)
  2. Capture the Sentry issue IDs and root-cause analysis:
    sentry:analyze_issue_with_seer
    

{ "organizationSlug": "", "issueId": "<ISSUE_ID>", "regionUrl": "<REGION_URL>" }

3. Fix the root cause (do not re-enable until fixed and re-tested internally)
4. Document what happened in the flag's description

---

## Phase 5: Promote to 100% and clean up  [LOW freedom — run exactly]

Once the feature is stable at 100% for at least 1 week:

1. Remove the flag check from the code — ship the new path as the default
2. Delete the fallback code (old path)
3. Delete the flag from the flag platform (LaunchDarkly / PostHog / etc.)
4. Remove the env var from all environments
5. Delete the flag from `src/lib/flags.ts` (for the env-var approach)

**Why cleanup matters:** Stale flags become permanent conditions. Code that says
`if (FLAGS.newCheckoutFlow)` six months later is a landmine nobody dares touch.

CLEANUP CHECKLIST:

  • Flag gate removed from source code
  • Old fallback code deleted
  • Flag deleted from the flag platform
  • Env var removed from .env* and deployment config
  • No more references to the flag name in the codebase

---

## Phase 6: Rollout report  [LOW freedom — do not skip]

```markdown
## Feature Flag Rollout — [flag-name] — [Date]

### Flag
- Name: [flag-name]
- Description: [what it controlled]
- Targeting: [who saw it, what percentage stages]

### Rollout timeline
| Date | Stage | Duration | Health status |
|------|-------|----------|---------------|
| ... | 0% → Internal | 2 days | ✅ Green |
| ... | Internal → 5% | 2 days | ✅ Green |
| ... | 5% → 100% | 3 days | ✅ Green |

### Health gate checks
- Sentry new issues at each stage: [count]
- P95 response time delta: [ms]
- Error rate delta: [%]

### Outcome
**Promoted to 100% / Rolled back** — [reason]

### Cleanup scheduled
[Date to remove the flag from code]
我的收藏