特性标志架构师

feature-flags-architect
分类通用
作者Alireza Rezvani
许可MIT
评分4.20/5
使用15.5K

功能标志架构师 (Feature Flags Architect)

一套端到端的功能标志管理规范:涵盖分类、发布、灰度放量和停用。大多数团队将标志视为临时的 if 语句;而本技能将其视为一个具有可衡量债务的受控生命周期。

使用场景

  • 添加新标志并需要制定发布计划
  • 审计代码库中过时或孤立的标志
  • 选择标志供应商(LaunchDarkly vs GrowthBook vs Statsig vs Unleash vs Flipt vs 自研)
  • 为高风险发布设计熔断开关(Kill-switch)路径
  • 在发布冻结前清理标志债务
  • 评估某个功能是否应该通过标志发布

核心原则:标志是生命周期,而非简单的 if

code
请求 → 设计 → 发布 → 放量 → 清理 → 归档

跳过清理阶段的标志会变成债务:死代码分支、过时的默认值、未经测试的代码路径以及不可控的影响范围。本技能中的三个脚本旨在强制执行这一生命周期。

快速上手

bash
# 1. 审计仓库中的标志债务
python scripts/flag_debt_scanner.py --repo . --max-age-days 90

2. 为新标志规划渐进式发布

python scripts/rollout_planner.py --population 100000 --target-percent 100 --duration-days 14 --strategy ring

3. 验证每个标志是否都有记录在案的熔断开关

python scripts/kill_switch_audit.py --repo . --flag-doc docs/feature-flags.md

四种标志类型(分类法)

不同类型的标志具有不同的生命周期和所有权。分类错误会导致债务增加。

| 类型 | 用途 | 典型生命周期 | 所有者 | 清理触发条件 |
|---|---|---|---|---|
| 发布 (Release) | 在生产环境中隐藏未完成的功能 | 数天至数周 | 工程 (Eng) | 达到 100% 放量 |
| 实验 (Experiment) | A/B 测试不同变体 | 数周 | 产品/市场 | 测试结束;选出胜出方案 |
| 运维 (Operational) | 熔断器、性能开关、紧急停止开关 | 数月至数年 | 工程/SRE | 被自动扩缩容或功能停用取代 |
| 权限 (Permission) | 基于用户/账户/方案的权益控制 | 数年(永久) | 产品 | 方案/角色被移除 |

只有“发布”和“实验”类标志应被纳入债务扫描器的监控名单。运维和权限类标志在设计上就是长期的。决策树请参考 references/flag_taxonomy.md

三款 Python 工具

所有工具仅依赖标准库。运行 --help 查看详情。

flag_debt_scanner.py

查找创建时间超过 --max-age-days 且使用率低的标志,建议将其作为清理对象。

bash
python scripts/flag_debt_scanner.py --repo . --max-age-days 90 --format text
python scripts/flag_debt_scanner.py --repo . --max-age-days 60 --format json > debt.json

检测启发式算法:
1. 遍历 --repo 寻找匹配常见标志调用模式的代码引用:
- flag("..."), isFlagEnabled("..."), featureFlag("

  • ..."), getFlag("...")

- client.variation("...", ...), unleash.isEnabled("..."), growthbook.feature("...")
2. 为每个唯一的 flag 标识符查找引入它的最早提交 (git log --diff-filter=A -S <name>)。
3. 如果引入时间 > --max-age-days 且使用次数 ≤ --min-uses,则标记为 DEBT(技术债)。

输出 flag 名称、存续天数、文件引用及建议操作。JSON 模式适用于 CI。

rollout_planner.py

根据用户基数、目标百分比、持续时间和策略生成分阶段发布计划。

bash
python scripts/rollout_planner.py --population 100000 --target-percent 100 --duration-days 14 --strategy ring
python scripts/rollout_planner.py --population 50000 --target-percent 25 --duration-days 7 --strategy linear
python scripts/rollout_planner.py --population 1000000 --target-percent 100 --duration-days 30 --strategy log

策略:

  • ring(环形):1% → 5% → 25% → 50% → 100%,等间距分布。高风险发布的默认选择。

  • linear(线性):每日恒定增长率。中风险发布的默认选择。

  • log(对数):前期快速,后期缓慢。有信心且低风险发布的默认选择。

  • cohort(群体):按命名群体(内部 → Beta → 免费用户 → 付费用户 → 全部)。

输出一个 Markdown 表格,包含每阶段的日期、百分比、预期用户数、终止标准和验证步骤。

kill_switch_audit.py

将代码中发现的 flag 与文档进行交叉比对,验证每个 flag 是否都写明了熔断(kill switch)路径。

bash
python scripts/kill_switch_audit.py --repo . --flag-doc docs/feature-flags.md
python scripts/kill_switch_audit.py --repo . --flag-doc runbooks/flags.md --format json

检查项:
1. 每个在代码中发现的 flag 在 --flag-doc 中都有对应条目。
2. 每个条目必须声明:负责人、类型、熔断触发条件、监控面板。
3. 报告缺失文档的 flag (FAIL) 或缺失字段的 flag (WARN)。

建议将其作为新 flag 发布前的合并门禁(pre-merge gate)。

服务商选择 (5 个主流 + 自研)

| 服务商 | 最适用场景 | 计费模式 | 绑定风险 | 开源选项 |
|---|---|---|---|---|
| LaunchDarkly | 企业级、复杂定向、审计/合规 | 按 MAU 计费,昂贵 | 高 | 否 |
| GrowthBook | 中端市场、侧重 A/B 测试、开源友好 | 按 MAU + 开源 | 低 | 是 (自托管) |
| Statsig | 增长/产品团队、高级实验 | 免费额度 + 按 MAU | 中 | 否 |
| Unleash | 开源优先、自托管、开发者友好 | 开源 + 企业版 | 低 | 是 |
| Flipt | 轻量级、k8s 原生、简单需求 | 仅开源 | 无 | 是 |
| DIY (自研) | <100 个 flag、无需定向、完全控制 | 无 | 无 | N/A |

决策规则:

  • <50 个 flag 且无需定向 $\rightarrow$ 使用配置文件或环境变量自研。

  • 需要分析 + 实验 $\rightarrow$ Statsig 或 GrowthBook。

  • 需要合规/SOC2 审计日志 $\rightarrow$ LaunchDarkly。

  • 必须自托管(数据驻留/物理隔离) $\rightarrow$ Unleash 或 Flipt。

  • 详情参阅 references/provider_comparison.md

工作流

工作流 1:在 flag 保护下发布新功能

code
1. 分类:属于 4 种 flag 类型中的哪一种?
   → Release(工程开发最常用)
2. 运行 rollout_planner.py 设计发布节奏
3. 在编写代码前,将 flag 条目添加到 docs/feature-flags.md:
   - 名称、负责人、类型、熔断触发条件、面板 URL
4. 编写带有 flag 的代码
5. 运行 kill_switch_audit.py —— 合并前必须通过
6. 以 0% 部署;验证熔断机制有效
7. 执行发布计划;若触发终止标准则立即中止
8. 维持 100% 运行 7 天以上:移除 flag,删除废弃分支,归档文档条目

工作流 2:

季度标志(Flag)清理
code
1. 运行 flag_debt_scanner.py --repo . --max-age-days 90 > debt.md
2. 针对每个被标记的项目:
   a. 确认其已达到 100%(或已被停用)
   b. 找到引入该标志的 issue/PR;确认所有者同意移除
   c. 删除失效分支;移除标志配置
   d. 运行 kill_switch_audit.py —— 此时显示的标志数量应减少一个
3. 更新 CHANGELOG:"移除了 N 个过期标志"

工作流 3:选择供应商

code
1. 预估标志数量(当前数量 + 12 个月预测值)
2. 需求功能:
   - 定向规则(用户、账户、地理位置、百分比)?
   - A/B 测试 + 统计分析?
   - 审计日志 / SOC2 合规?
   - 自托管 / 数据驻留?
3. 价格预算 (MAU * 每个 MAU 的成本)
4. 参考 provider_comparison.md 中的决策树
5. 在签约前构建一个为期 30 天的概念验证 (PoC)

工作流 4:设计熔断开关 (Kill Switch)

code
1. 识别故障模式:
   - 延迟激增(阈值是多少?)
   - 错误率激增(阈值是多少?)
   - 业务指标回退(阈值是多少?)
2. 将各项连接至中止机制:
   - 手动:仪表盘链接 + On-call 操作手册
   - 自动:告警阈值触发,将标志自动切回 0%
3. 在生产环境发布前,先在 Staging 环境测试熔断开关
4. 在 flag-doc 中记录;通过 kill_switch_audit.py 审计

参考资料

  • references/flag_taxonomy.md — 4 种类型、决策树、所有权、生命周期
  • references/provider_comparison.md — LaunchDarkly / GrowthBook / Statsig / Unleash / Flipt / 自研的权衡
  • references/rollout_strategies.md — 环形 / 线性 / 对数 / 队列 / 地理位置发布,中止标准,监控
  • references/flag_lifecycle.md — 申请 → 设计 → 发布 → 逐步放量 → 清理 → 归档

斜杠命令

/flag-cleanup — 对当前仓库运行完整的清理工作流:扫描技术债,生成移除计划,审计熔断开关。

资源模板

  • assets/flag_request_template.md — 新标志申请填表(名称、所有者、类型、熔断开关、发布计划)

反模式

  • 在 50 处使用 if (FLAG_FOO) 的永久标志 — 这应该是带有运行时配置的“权限标志”,而非“发布标志”
  • 没有所有者的标志 — 当原开发人员离职后,无人清理
  • 未记录熔断开关 — 当功能崩溃时,没人知道如何禁用
  • 运行了 6 个月的 A/B 测试 — 请选出胜出方案;无限期运行即是技术债
  • 将标志作为视觉微调的功能开关 — 应通过部署发布,而非使用标志

可验证的成功标准

掌握此技能的团队应达到:

  • 100% 的新标志在合并时通过 kill_switch_audit.py 审计

  • 全库运行 flag_debt_scanner.py --max-age-days 90 返回的过期标志 $\le 5$ 个

  • 每个标志都有记录在案的所有者、类型和熔断开关

  • 发布标志(Release flag)从 100% 放量到退役的平均时间 $< 60$ 天