Shipping a new feature to everyone at once is risky. What if it breaks something? Feature flags in PostHog let you control who sees what, enabling you to test with a subset of users, run A/B tests, or gradually roll out features—all without redeploying. They're the safest way to move fast.
What Feature Flags Actually Are
Feature flags are conditions in your code that control feature visibility. PostHog makes this dead simple.
Understand the Basic Concept
A feature flag is a key-value pair stored in PostHog. You ask PostHog "should user X see feature Y?" and it responds with true or false (or a variant). This decouples code deployment from feature release.
import posthog from 'posthog-js';
// Check if a flag is enabled for the current user
if (posthog.isFeatureEnabled('new_dashboard')) {
// Show the new dashboard
} else {
// Show the old dashboard
}Know When to Use Flags
Use flags for new features, risky changes, A/B tests, or gradual rollouts. You define the flag once in the PostHog UI, then your code checks it at runtime. No redeployment needed to toggle it on or off.
// Get all flags for the current user
const allFlags = posthog.getFeatureFlags();
console.log('Enabled flags:', allFlags);
// Or get a specific flag with its payload (for variants)
const variantValue = posthog.getFeatureFlagPayload('pricing_test');
if (variantValue === 'expensive') {
showPricingVariant('expensive');
} else if (variantValue === 'cheap') {
showPricingVariant('cheap');
}Creating and Configuring Flags
In PostHog, you create flags in the dashboard, not in code.
Create a Flag in PostHog
Go to Feature Flags in the PostHog sidebar. Click New feature flag. Give it a Key (like new_dashboard) and a description. The key is what you'll reference in your code.
// Once the flag 'new_dashboard' exists in PostHog, use this key in your code
if (posthog.isFeatureEnabled('new_dashboard')) {
return <NewDashboard />;
}
return <OldDashboard />;Set Up Targeting Rules
Define who sees the flag: All users, a percentage (10%, 50%), specific users (by property like email or ID), or cohorts. You can layer multiple conditions with AND/OR logic. PostHog evaluates these at request time.
// Ensure the user is identified before checking flags
posthog.identify('user_123', {
email: '[email protected]',
role: 'admin',
company: 'acme'
});
// Now when you check the flag, PostHog evaluates targeting rules
if (posthog.isFeatureEnabled('admin_dashboard')) {
return <AdminPanel />;
}Create Multivariate Tests
Instead of just true/false, flags can have variants. Create one for each test group (e.g., control, variant_a, variant_b). PostHog assigns each user to a variant consistently, and you render based on that.
// Get the variant assigned to this user
const variant = posthog.getFeatureFlagPayload('pricing_experiment');
const pricingMap = {
'control': '$99/month',
'discount': '$49/month',
'tiered': '$29-99/month'
};
const price = pricingMap[variant] || '$99/month';
return <PricingCard price={price} variant={variant} />;Practical Patterns in Real Apps
Gradually Roll Out a Feature
Start with 0% of users, then bump it to 5%, 25%, 50%, 100% over days or weeks. PostHog tracks error rates and performance metrics automatically. No redeployment needed.
// In your component
if (posthog.isFeatureEnabled('new_checkout')) {
return <CheckoutV2 />;
}
// In PostHog UI:
// Day 1: Roll out to 5% of users
// Day 2: Roll out to 25% of users
// Day 3: Roll out to 100% of users (or revert if issues)A/B Test Two Designs
Create a multivariate flag with two variants: control and test. Assign 50% of traffic to each. PostHog measures funnels, conversion, and retention—you can see which variant wins.
// Check which variant this user got
const variant = posthog.getFeatureFlagPayload('button_color_test');
if (variant === 'blue') {
return <Button color="blue">Buy Now</Button>;
} else {
return <Button color="green">Buy Now</Button>;
}
// PostHog shows conversion rate for each variant in the dashboardSafely Remove Old Code
Once a flag reaches 100% and runs stable for a week, remove the flag check from your code and deploy. Then delete the flag in PostHog. This keeps your codebase clean and avoids dead code branches.
// Before: flag is at 100%, so everyone uses this
if (posthog.isFeatureEnabled('new_dashboard')) {
return <NewDashboard />;
}
return <OldDashboard />;
// After: remove the flag entirely, keep the new code
return <NewDashboard />;Common Pitfalls
- Not identifying users first —
posthog.isFeatureEnabled()needs the current user's identity to evaluate targeting rules. Callposthog.identify()on login. - Expecting instant propagation — flag changes take ~5 seconds to reach users. If you toggle a flag and your app doesn't reflect it immediately, refresh the page.
- Forgetting to remove old code — flags are temporary. Once you reach 100% and deploy, delete the old code path. Leaving both alive creates technical debt.
- Overloading targeting rules — if you stack 20 conditions on a flag, debugging becomes impossible. Start simple, add complexity only if needed.
Wrapping Up
Feature flags in PostHog give you fine-grained control over releases. You can test safely, roll out gradually, and roll back instantly—all without redeploying. This is how modern teams move fast without breaking production. If you want to track this automatically across tools, Product Analyst can help.