Feature flags let you control feature releases without redeploying code — critical when you want to test with real users before going live. PostHog makes this simple with built-in flag creation, targeting rules, and release tracking. If you're not using flags, you're deploying blind or waiting for full rollouts.
Create a Feature Flag
Start by creating a flag in PostHog's dashboard, then configure who sees it.
Navigate to Feature Flags
In the PostHog dashboard, go to Feature Flags in the left sidebar. You'll see a list of existing flags (empty if this is your first time).
Create a New Flag
Click Create feature flag to open the flag creation form. Enter a flag key — this is what you'll reference in code. Use snake_case like new-checkout-flow or premium-dashboard. Optionally add a description for your team.
Configure Targeting Rules
Under Release conditions, choose how to roll out the flag. You can release to a percentage of users, specific user properties (e.g., is_admin = true), or segments you've created. Leave it at 0% for now if you're testing — you'll enable it after verifying in code.
// Example flag structure via PostHog API
const flagData = {
key: 'new-checkout-flow',
name: 'New Checkout Flow',
filters: {
groups: [
{
properties: [
{
key: 'email',
value: ['@acme.com'],
operator: 'icontains'
}
]
}
]
}
};
// This targets users with @acme.com email addressesCheck the Flag in Your Code
Once the flag is created, integrate it into your application with PostHog's JavaScript SDK.
Initialize PostHog
If you haven't already, install the PostHog JavaScript SDK: npm install posthog-js. Then initialize it early in your app — usually in your main entry point or app root component.
import posthog from 'posthog-js';
posthog.init('phc_YOUR_PROJECT_KEY', {
api_host: 'https://app.posthog.com',
loaded: (ph) => {
// PostHog is ready
}
});Check the Flag Before Rendering
Use posthog.isFeatureEnabled() to check if a flag is on for the current user. This returns a boolean, so you can gate features with conditional logic.
// Check if flag is enabled for the current user
if (posthog.isFeatureEnabled('new-checkout-flow')) {
return <NewCheckout />;
} else {
return <LegacyCheckout />;
}Identify Users for Personalized Flags
If your targeting rules depend on user properties (like subscription tier), call posthog.identify() to send user context to PostHog. This ensures the flag logic evaluates correctly.
// Identify the user so PostHog can apply targeting rules
posthog.identify('user_123', {
email: '[email protected]',
subscription_tier: 'premium',
created_at: '2024-01-15'
});
// Now isFeatureEnabled() will use these properties
if (posthog.isFeatureEnabled('premium-dashboard')) {
showPremiumDashboard();
}isFeatureEnabled() is synchronous but relies on data sent from previous calls. If you're unsure the user is identified, pass a second parameter: posthog.isFeatureEnabled('flag-key', { email: '[email protected]' }).Roll Out and Monitor
Start small, track usage, then scale your rollout.
Enable the Flag for a Test Group
Go back to the flag in PostHog and set Release conditions to a small percentage (5–10%). Save the changes. PostHog will immediately start evaluating the flag for that percentage of users — no code redeploy needed.
// Once the flag is enabled, it takes effect immediately
// No need to redeploy — just restart the user session or check in real-time
// Verify in your browser console or logs
console.log(posthog.isFeatureEnabled('new-checkout-flow'));
// Should return true or false based on flag stateTrack Feature Usage with Events
Log an event when users interact with the flagged feature. This helps you measure adoption and compare old vs. new. PostHog automatically tracks which flag variant each user saw.
// Track when someone uses the new checkout
if (posthog.isFeatureEnabled('new-checkout-flow')) {
posthog.capture('checkout_started', {
checkout_version: 'new',
cart_value: total
});
} else {
posthog.capture('checkout_started', {
checkout_version: 'legacy',
cart_value: total
});
}Increase Rollout or Remove the Flag
Monitor your metrics in PostHog — check conversion rates, error rates, or custom events to compare versions. If the new feature is solid, increase the percentage to 50%, then 100%. Once fully rolled out, you can remove the flag from your code and archive it in PostHog.
// After a flag is fully rolled out, simplify your code
// Before: conditional logic
// if (posthog.isFeatureEnabled('new-checkout-flow')) { ... }
// After: remove the flag and keep only the new code
return <NewCheckout />;
// Archive the flag in PostHog to clean up the UICommon Pitfalls
- Forgetting to call
posthog.identify()before checking flags — if you don't send user properties, targeting rules based on email or subscription tier won't work as expected. - Leaving dead flag code in production after the flag is rolled out — archive flags in PostHog and remove the conditionals from your codebase so you're not evaluating stale flags.
- Setting the release percentage too high on first enable — start at 1–5% to catch unexpected bugs or UX issues before they affect your user base.
- Not tracking separate events for flag variants — without event tracking, you have no way to compare performance between old and new features.
Wrapping Up
You now have feature flags running in PostHog and can control rollouts without redeploying. Start with a small percentage, track your metrics, then scale. If you want to track this automatically across tools, Product Analyst can help.