Feature Flags
Feature flags allow EGI to deploy code to production without exposing it to all users. They enable controlled rollouts, A/B testing, beta programs, and safer deployments. EGI uses PostHog for feature flag management.
When to Use Feature Flags
Feature flags are appropriate in the following situations:
| Scenario | Example |
|---|---|
| Gradual rollout | Rolling out a new dashboard to 10% of users, then 50%, then 100% |
| Beta testing | Giving a specific list of users early access to a feature |
| Kill switch | Ability to disable a feature instantly in production without a deployment |
| A/B testing | Comparing two implementations of a feature to measure which performs better |
| Client-specific features | Enabling functionality for one client but not others in a multi-tenant product |
| Incomplete features | Merging work-in-progress code to main behind a flag to avoid long-lived branches |
When Not to Use Feature Flags
- Configuration values that change per environment (use environment variables instead)
- Permanent feature toggles that will never be removed (use role-based access or product tiers instead)
- Secrets or sensitive logic (flags are client-readable; do not gate security controls behind flags)
Naming Conventions
Feature flag names use snake_case and follow this structure:
[scope]_[feature_name]
| Component | Description | Example |
|---|---|---|
scope | The area of the product the flag affects | dashboard, onboarding, billing, api |
feature_name | A short, descriptive name for the feature | new_chart_view, guided_setup, bulk_export |
Examples:
dashboard_new_chart_viewonboarding_guided_setupbilling_annual_planapi_v2_endpoints
Rules:
- Always use snake_case (no hyphens, no camelCase)
- Keep names under 50 characters
- Be specific enough that the flag's purpose is clear without looking up documentation
- Never include dates, ticket numbers, or developer names in flag names
Flag Types in PostHog
Boolean Flags
The simplest type. The flag is either on or off.
if (posthog.isFeatureEnabled('dashboard_new_chart_view')) {
return <NewChartView />
}
return <LegacyChartView />
Use boolean flags for: kill switches, simple rollouts, and feature gating.
Multivariate Flags
The flag returns one of several string values, allowing you to test multiple variants.
const variant = posthog.getFeatureFlag('onboarding_flow_variant')
switch (variant) {
case 'control':
return <StandardOnboarding />
case 'streamlined':
return <StreamlinedOnboarding />
case 'guided':
return <GuidedOnboarding />
}
Use multivariate flags for: A/B/n tests and experiments with more than two options.
Rollout Strategies
Percentage Rollout
Gradually increase the percentage of users who see the feature.
Recommended rollout schedule:
| Stage | Percentage | Duration | Action |
|---|---|---|---|
| Canary | 5% | 1--2 days | Monitor for errors and unexpected behavior |
| Early rollout | 25% | 3--5 days | Check analytics for engagement and performance |
| Broad rollout | 50% | 3--5 days | Confirm no regressions at scale |
| Full rollout | 100% | -- | Flag cleanup begins |
At each stage, check the following before advancing:
- No increase in error rates
- No performance degradation
- User behavior metrics are stable or improving
- No negative feedback through support channels
User Targeting
Enable the feature for specific users or user groups.
Common targeting criteria:
- Internal team -- Flag enabled for EGI and Anchor team members for internal testing
- Beta users -- Flag enabled for a specific list of user IDs who opted into the beta program
- Client-specific -- Flag enabled for users belonging to a particular organization or account
- Role-based -- Flag enabled for users with a specific role (e.g., admins only)
Configure targeting in PostHog using person properties set during user identification.
Beta Programs
For features with a formal beta program:
- Define beta criteria and communicate them to the client or user group
- Create the feature flag with user targeting for beta participants
- Collect structured feedback (survey, Slack channel, or SuiteDash form)
- Review feedback at the end of the beta period before proceeding to a broader rollout
- Document beta findings and any changes made based on feedback
Implementation Guidelines
Server-Side vs. Client-Side
| Evaluation Location | When to Use | How |
|---|---|---|
| Client-side | UI changes, frontend features, non-sensitive gating | posthog.isFeatureEnabled('flag_name') in React/JS |
| Server-side | API behavior, data processing logic, security-sensitive features | posthog.isFeatureEnabled('flag_name', distinctId) via posthog-node |
Default Behavior
Always define a sensible default for when a flag evaluation fails (e.g., PostHog is unreachable):
const showNewFeature = posthog.isFeatureEnabled('dashboard_new_chart_view') ?? false
The default should be the safe, existing behavior (typically false / feature off).
Avoiding Flag Nesting
Do not nest feature flags (checking one flag inside another). Nested flags create complex state combinations that are difficult to reason about and test. If you need compound logic, create a single flag with multivariate values instead.
Cleanup Policy
Feature flags are temporary by design. Leaving stale flags in the codebase increases complexity and makes the code harder to maintain.
Cleanup Timeline
- 30 days after full rollout (100%): The flag must be removed from the codebase
- The developer who created the flag is responsible for cleanup
- Cleanup is tracked as a chore ticket created at the time the flag reaches 100% rollout
Cleanup Process
- Confirm the flag has been at 100% for at least 30 days with no issues
- Remove all conditional logic in the codebase that references the flag
- Remove the fallback/legacy code path that is no longer used
- Delete or archive the flag in PostHog
- Submit a PR with the cleanup changes, referencing the original flag and feature
Tracking Stale Flags
During the quarterly documentation review, audit all active feature flags:
- Identify any flags that have been at 100% rollout for more than 30 days without cleanup
- Identify any flags that have been active for more than 90 days total (may indicate a flag being used as permanent configuration)
- Create cleanup tickets for any stale flags found
Best Practices Summary
- Keep flag lifespans short. Flags are temporary; plan for removal from the start.
- Test both states. Always test the feature with the flag on and off before merging.
- Monitor after each rollout stage. Do not advance rollout percentages without checking metrics.
- Document the flag. Add a brief description in PostHog when creating the flag so others understand its purpose.
- One flag per feature. Do not reuse a flag for multiple unrelated features.
- Default to off. New flags should default to disabled and be explicitly enabled through PostHog.