api-flags-posthog-flags

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Feature Flags with PostHog

使用PostHog实现功能标志

Quick Guide: Use PostHog feature flags for gradual rollouts, A/B testing, and remote configuration. Client-side:
useFeatureFlagEnabled
hook. Server-side:
posthog-node
with local evaluation. Always pair
useFeatureFlagPayload
with
useFeatureFlagEnabled
for experiments. Handle the
undefined
loading state on every flag check.

<critical_requirements>
快速指南: 使用PostHog功能标志实现逐步发布、A/B测试和远程配置。客户端:
useFeatureFlagEnabled
钩子。服务端:结合本地评估使用
posthog-node
。实验场景下务必将
useFeatureFlagPayload
useFeatureFlagEnabled
搭配使用。每次检查标志时都要处理
undefined
加载状态。

<critical_requirements>

CRITICAL: Before Using This Skill

重要提示:使用本技能前须知

All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type
, named constants)
(You MUST always pair
useFeatureFlagPayload
with
useFeatureFlagEnabled
or
useFeatureFlagVariantKey
for experiments - payload hooks don't send exposure events)
(You MUST use the feature flags secure API key (phs_*) for server-side local evaluation - personal API keys are deprecated for this use)
(You MUST handle the
undefined
state when flags are loading - never assume a flag is immediately available)
(You MUST include flag owner and expiry date in flag metadata - flags without owners become orphaned debt)
(You MUST wrap flag usage in a single function when used in multiple places - prevents orphaned flag code on cleanup)
</critical_requirements>

Auto-detection: PostHog feature flags, useFeatureFlagEnabled, useFeatureFlagPayload, useFeatureFlagVariantKey, PostHogFeature, isFeatureEnabled, getFeatureFlag, gradual rollout, A/B test, experiment, multivariate flag
When to use:
  • Gradual rollouts (deploy to 10% users, then 50%, then 100%)
  • A/B testing with experiments (measure impact of changes)
  • Kill switches (instantly disable features without deploy)
  • Remote configuration (change behavior without code changes)
  • Beta features opt-in (let users try new features)
  • User targeting (show features to specific cohorts)
When NOT to use:
  • Simple on/off switches that never change (use environment variables)
  • Configuration that must be compile-time (use build flags)
  • Secrets or sensitive data (use secret management)
  • Features that should always be on (just ship the code)
Key patterns covered:
  • Client-side flag evaluation with React hooks
  • Server-side local evaluation for performance
  • Boolean vs multivariate flags
  • Gradual rollouts with percentage targeting
  • A/B testing and experiments
  • Payloads for remote configuration
  • Local development overrides
  • Flag cleanup and lifecycle management

Detailed Resources:
  • examples/core.md - Boolean flags, multivariate flags, PostHogFeature component, payloads, experiments, rollouts, lifecycle management
  • examples/server-side.md - Server-side evaluation, local evaluation setup, distributed environments
  • examples/development.md - Local overrides, bootstrapping, onFeatureFlags callback
  • reference.md - Decision frameworks and anti-patterns

<philosophy>
所有代码必须遵循CLAUDE.md中的项目规范(短横线命名、命名导出、导入顺序、
import type
、命名常量)
(实验场景下,务必将
useFeatureFlagPayload
useFeatureFlagEnabled
useFeatureFlagVariantKey
搭配使用——payload钩子不会发送曝光事件)
(服务端本地评估必须使用功能标志安全API密钥(phs_*)——个人API密钥已被弃用)
(必须处理标志加载时的
undefined
状态——永远不要假设标志会立即可用)
(必须在标志元数据中包含标志所有者和过期日期——无所有者的标志会成为无人维护的技术债务)
(当标志在多个地方使用时,必须将其封装在单个函数中——避免清理时出现孤立的标志代码)
</critical_requirements>

自动检测项: PostHog功能标志、useFeatureFlagEnabled、useFeatureFlagPayload、useFeatureFlagVariantKey、PostHogFeature、isFeatureEnabled、getFeatureFlag、逐步发布、A/B测试、实验、多变量标志
适用场景:
  • 逐步发布(先部署给10%用户,再扩展到50%,最后100%)
  • 带实验的A/B测试(衡量变更影响)
  • 熔断开关(无需部署即可立即禁用功能)
  • 远程配置(无需修改代码即可更改行为)
  • Beta功能可选加入(让用户试用新功能)
  • 用户定向(向特定用户群组展示功能)
不适用场景:
  • 永不更改的简单开关(使用环境变量)
  • 必须在编译时配置的项(使用构建标志)
  • 机密或敏感数据(使用密钥管理工具)
  • 应始终启用的功能(直接发布代码即可)
涵盖的核心模式:
  • 使用React钩子进行客户端标志评估
  • 服务端本地评估以提升性能
  • 布尔型与多变量标志
  • 基于百分比定向的逐步发布
  • A/B测试与实验
  • 用于远程配置的Payload
  • 本地开发覆盖
  • 标志清理与生命周期管理

详细资源:
  • examples/core.md - 布尔型标志、多变量标志、PostHogFeature组件、Payload、实验、版本发布、生命周期管理
  • examples/server-side.md - 服务端评估、本地评估设置、分布式环境
  • examples/development.md - 本地覆盖、引导、onFeatureFlags回调
  • reference.md - 决策框架与反模式

<philosophy>

Philosophy

理念

Feature flags decouple deployment from release. You can ship code to production but control who sees it and when. This enables:
  1. Safe releases - Roll out to 1% first, monitor, then expand
  2. Fast rollback - Toggle off instantly without deploying
  3. Data-driven decisions - A/B test to measure impact
  4. Progressive delivery - Beta users first, then everyone
Core principles:
  • Flags are temporary - plan for cleanup from day one
  • Flags have owners - someone is responsible for each flag
  • Simple flags are better - percentage rollouts over complex conditions
  • Handle undefined - flags load asynchronously
When to use feature flags:
  • Risky features that need gradual rollout
  • Features requiring A/B testing for validation
  • Features that may need instant rollback
  • Beta programs with user opt-in
When NOT to use feature flags:
  • Every feature (creates maintenance burden)
  • Permanent configuration (use config files)
  • Features that are ready for 100% release
</philosophy>
<patterns>
功能标志将部署与发布解耦。你可以将代码部署到生产环境,但控制谁能看到以及何时看到。这实现了:
  1. 安全发布 - 先推送给1%用户,监控后再扩展
  2. 快速回滚 - 无需部署即可立即关闭功能
  3. 数据驱动决策 - 通过A/B测试衡量影响
  4. 渐进式交付 - 先给Beta用户,再全面开放
核心原则:
  • 标志是临时的 - 从第一天就规划清理方案
  • 标志有所有者 - 每个标志都有负责人
  • 简单标志更优 - 优先使用百分比发布而非复杂条件
  • 处理undefined状态 - 标志是异步加载的
何时使用功能标志:
  • 需要逐步发布的高风险功能
  • 需要通过A/B测试验证的功能
  • 可能需要立即回滚的功能
  • 支持用户可选加入的Beta项目
何时不使用功能标志:
  • 所有功能(会增加维护负担)
  • 永久配置(使用配置文件)
  • 已准备好100%发布的功能
</philosophy>
<patterns>

Core Patterns

核心模式

Pattern 1: Client-Side Boolean Flags

模式1:客户端布尔型标志

Use
useFeatureFlagEnabled
for simple on/off features. Always handle the
undefined
loading state -- treating it as
false
causes a flash of wrong UI.
typescript
const isNewCheckout = useFeatureFlagEnabled(FLAG_NEW_CHECKOUT);

if (isNewCheckout === undefined) return <Skeleton />;   // Loading
if (isNewCheckout) return <NewCheckout />;               // Enabled
return <LegacyCheckout />;                               // Disabled
Store flag keys as named constants in
lib/feature-flags.ts
to prevent typos and enable cleanup-by-grep.
See examples/core.md for full good/bad examples.

使用
useFeatureFlagEnabled
实现简单的开关功能。务必处理
undefined
加载状态——将其视为
false
会导致UI闪烁。
typescript
const isNewCheckout = useFeatureFlagEnabled(FLAG_NEW_CHECKOUT);

if (isNewCheckout === undefined) return <Skeleton />;   // 加载中
if (isNewCheckout) return <NewCheckout />;               // 已启用
return <LegacyCheckout />;                               // 已禁用
将标志键存储在
lib/feature-flags.ts
中的命名常量中,以防止拼写错误并便于通过grep清理。
查看examples/core.md获取完整的正反示例。

Pattern 2: Multivariate Flags and Variants

模式2:多变量标志与变体

Use
useFeatureFlagVariantKey
for A/B tests with multiple variants. Define variant constants alongside the flag key. Switch on variants with a default fallback to
control
.
typescript
const variant = useFeatureFlagVariantKey(FLAG_PRICING_PAGE);
if (variant === undefined) return <Skeleton />;

switch (variant) {
  case VARIANT_SIMPLE: return <SimplePricing />;
  case VARIANT_DETAILED: return <DetailedPricing />;
  default: return <ControlPricing />;
}
See examples/core.md for full example.

使用
useFeatureFlagVariantKey
实现多变体的A/B测试。将变体常量与标志键一起定义。根据变体进行分支,默认回退到
control
typescript
const variant = useFeatureFlagVariantKey(FLAG_PRICING_PAGE);
if (variant === undefined) return <Skeleton />;

switch (variant) {
  case VARIANT_SIMPLE: return <SimplePricing />;
  case VARIANT_DETAILED: return <DetailedPricing />;
  default: return <ControlPricing />;
}
查看examples/core.md获取完整示例。

Pattern 3: PostHogFeature Component

模式3:PostHogFeature组件

The
PostHogFeature
component provides automatic exposure tracking and built-in fallback handling with less boilerplate. Use
match={true}
for boolean flags or
match={VARIANT_KEY}
for specific variants.
typescript
<PostHogFeature flag={FLAG_BETA} match={true} fallback={<Legacy />}>
  <NewFeature />
</PostHogFeature>
See examples/core.md for boolean and variant examples.

PostHogFeature
组件提供自动曝光跟踪和内置回退处理,代码更简洁。布尔型标志使用
match={true}
,特定变体使用
match={VARIANT_KEY}
typescript
<PostHogFeature flag={FLAG_BETA} match={true} fallback={<Legacy />}>
  <NewFeature />
</PostHogFeature>
查看examples/core.md获取布尔型和变体示例。

Pattern 4: Payloads for Remote Configuration

模式4:用于远程配置的Payload

Use
useFeatureFlagPayload
for dynamic JSON configuration. Always pair with
useFeatureFlagEnabled
-- the payload hook alone does NOT send exposure events, breaking experiment tracking.
typescript
const isEnabled = useFeatureFlagEnabled(FLAG_BANNER); // Sends exposure event
const payload = useFeatureFlagPayload(FLAG_BANNER); // Gets config
const config = payload ?? DEFAULT_BANNER_CONFIG;
See examples/core.md for full good/bad examples.

使用
useFeatureFlagPayload
实现动态JSON配置。务必与
useFeatureFlagEnabled
搭配使用
——单独使用payload钩子不会发送曝光事件,会破坏实验跟踪。
typescript
const isEnabled = useFeatureFlagEnabled(FLAG_BANNER); // 发送曝光事件
const payload = useFeatureFlagPayload(FLAG_BANNER); // 获取配置
const config = payload ?? DEFAULT_BANNER_CONFIG;
查看examples/core.md获取完整的正反示例。

Pattern 5: Server-Side Flag Evaluation

模式5:服务端标志评估

Use
posthog-node
with the Feature Flags Secure API Key (
phs_*
) for local evaluation. This reduces latency from ~500ms (network call) to ~10-50ms (local). The
personalApiKey
config option takes the
phs_*
key despite its legacy name.
typescript
export const posthog = new PostHog(process.env.POSTHOG_API_KEY!, {
  host: process.env.POSTHOG_HOST || "https://us.i.posthog.com",
  personalApiKey: process.env.POSTHOG_FEATURE_FLAGS_KEY, // phs_* key
  featureFlagsPollingInterval: POSTHOG_POLL_INTERVAL_MS, // default 30s
});
See examples/server-side.md for API handler usage, local-only evaluation, and distributed/serverless environments.

结合功能标志安全API密钥(
phs_*
)使用
posthog-node
进行本地评估。这将延迟从约500ms(网络调用)降低到约10-50ms(本地调用)。尽管名称是遗留的,但
personalApiKey
配置项需要传入
phs_*
密钥。
typescript
export const posthog = new PostHog(process.env.POSTHOG_API_KEY!, {
  host: process.env.POSTHOG_HOST || "https://us.i.posthog.com",
  personalApiKey: process.env.POSTHOG_FEATURE_FLAGS_KEY, // phs_* 密钥
  featureFlagsPollingInterval: POSTHOG_POLL_INTERVAL_MS, // 默认30秒
});
查看examples/server-side.md获取API处理器用法、仅本地评估以及分布式/无服务器环境的相关内容。

Pattern 6: Flag Lifecycle and Cleanup

模式6:标志生命周期与清理

Every flag needs an owner, a creation date, and an expected removal date. Wrap flag checks in a single helper function so cleanup is a one-file change.
typescript
/**
 * Owner: @john-doe | Created: 2025-01-15 | Remove by: 2025-02-15
 */
export const FLAG_NEW_CHECKOUT = "new-checkout-flow";

export function isNewCheckoutEnabled(flag: boolean | undefined): boolean {
  return flag === true; // When removing: change to `return true;`
}
See examples/core.md for full documentation patterns and stale flag detection.
</patterns>
<red_flags>
每个标志都需要所有者、创建日期和预计移除日期。将标志检查封装在单个辅助函数中,这样清理只需修改一个文件。
typescript
/**
 * 所有者: @john-doe | 创建日期: 2025-01-15 | 移除日期: 2025-02-15
 */
export const FLAG_NEW_CHECKOUT = "new-checkout-flow";

export function isNewCheckoutEnabled(flag: boolean | undefined): boolean {
  return flag === true; // 移除时改为 `return true;`
}
查看examples/core.md获取完整的文档模式和过期标志检测方法。
</patterns>
<red_flags>

RED FLAGS

警示事项

High Priority Issues:
  • Using
    useFeatureFlagPayload
    alone for experiments (no exposure tracking)
  • Exposing Feature Flags Secure API key (
    phs_*
    ) on client (security violation)
  • No loading state handling (causes UI flash)
  • Flags without owners or expiry dates (becomes permanent debt)
Medium Priority Issues:
  • Magic string flag keys instead of constants (typos, hard to grep)
  • Complex targeting rules on high-traffic flags (performance hit)
  • Local evaluation in serverless/edge without external cache (cold start issues)
  • Not using PostHog toolbar for local testing (harder debugging)
Common Mistakes:
  • Checking flag in multiple places instead of wrapper function
  • Not bootstrapping flags for SSR (content flash on hydration)
  • Running experiments without defined primary metric
  • Peeking at experiment results before completion
  • Rolling out to 100% without cleanup plan
Gotchas & Edge Cases:
  • PostHog uses deterministic hashing - same user always gets same variant
  • Decreasing rollout percentage can remove users who were previously included
  • Local evaluation requires Feature Flags Secure API Key (
    phs_*
    ) - personal API keys are deprecated
  • Flags load asynchronously - first render always has undefined
  • GeoIP targeting uses server IP by default in posthog-node v3+
  • Experiments need minimum 50 exposures per variant for results
  • Stale flag = 100% rollout + not evaluated in 30 days
  • onFeatureFlags
    callback receives three parameters:
    flags
    ,
    flagVariants
    ,
    { errorsLoading }
    (third parameter)
  • External cache providers (Redis, KV) are experimental - Node.js/Python SDKs only
</red_flags>

<critical_reminders>
高优先级问题:
  • 实验场景下单独使用
    useFeatureFlagPayload
    (无曝光跟踪)
  • 在客户端暴露功能标志安全API密钥(
    phs_*
    )(安全违规)
  • 未处理加载状态(导致UI闪烁)
  • 无所有者或过期日期的标志(成为永久技术债务)
中优先级问题:
  • 使用魔术字符串作为标志键而非常量(易出错,难以通过grep查找)
  • 高流量标志使用复杂定向规则(性能影响)
  • 无外部缓存的无服务器/边缘环境中使用本地评估(冷启动问题)
  • 未使用PostHog工具栏进行本地测试(调试难度大)
常见错误:
  • 在多个地方检查标志而非使用封装函数
  • 未为SSR引导标志(水合时内容闪烁)
  • 运行实验但未定义主要指标
  • 实验完成前查看结果
  • 发布到100%但无清理计划
陷阱与边缘情况:
  • PostHog使用确定性哈希 - 同一用户始终获得相同变体
  • 降低发布百分比可能会移除之前已包含的用户
  • 本地评估需要功能标志安全API密钥(
    phs_*
    )- 个人API密钥已被弃用
  • 标志异步加载 - 首次渲染时始终为undefined
  • posthog-node v3+默认使用服务器IP进行GeoIP定向
  • 实验每个变体至少需要50次曝光才能得到有效结果
  • 过期标志 = 100%发布 + 30天未评估
  • onFeatureFlags
    回调接收三个参数:
    flags
    ,
    flagVariants
    ,
    { errorsLoading }
    (第三个参数)
  • 外部缓存提供商(Redis、KV)处于实验阶段 - 仅支持Node.js/Python SDK
</red_flags>

<critical_reminders>

CRITICAL REMINDERS

重要提醒

All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type
, named constants)
(You MUST always pair
useFeatureFlagPayload
with
useFeatureFlagEnabled
or
useFeatureFlagVariantKey
for experiments - payload hooks don't send exposure events)
(You MUST use the feature flags secure API key (phs_*) for server-side local evaluation - personal API keys are deprecated for this use)
(You MUST handle the
undefined
state when flags are loading - never assume a flag is immediately available)
(You MUST include flag owner and expiry date in flag metadata - flags without owners become orphaned debt)
(You MUST wrap flag usage in a single function when used in multiple places - prevents orphaned flag code on cleanup)
Failure to follow these rules will cause incorrect experiment results, security vulnerabilities, UI flashing, and technical debt.
</critical_reminders>

所有代码必须遵循CLAUDE.md中的项目规范(短横线命名、命名导出、导入顺序、
import type
、命名常量)
(实验场景下,务必将
useFeatureFlagPayload
useFeatureFlagEnabled
useFeatureFlagVariantKey
搭配使用——payload钩子不会发送曝光事件)
(服务端本地评估必须使用功能标志安全API密钥(phs_*)——个人API密钥已被弃用)
(必须处理标志加载时的
undefined
状态——永远不要假设标志会立即可用)
(必须在标志元数据中包含标志所有者和过期日期——无所有者的标志会成为无人维护的技术债务)
(当标志在多个地方使用时,必须将其封装在单个函数中——避免清理时出现孤立的标志代码)
不遵守这些规则会导致实验结果错误、安全漏洞、UI闪烁和技术债务。
</critical_reminders>

Sources

来源