PostHog offers two main ways to use feature flags.
- You can send a request to the PostHog
/decide
API endpoint to resolve a flag, or - You can use server-side local evaluation to pull flag definitions, and resolve flags using the definition data
Client-side bootstrapping
There is a delay between loading the library and feature flags becoming available to use. This can be detrimental if you want to do something like redirecting to a different page based on a feature flag.
To have your feature flags available immediately, you can bootstrap them with a distinct user ID and their values during initialization.
posthog.init('<ph_project_api_key>', {api_host: '<ph_instance_address>',bootstrap: {distinctID: 'your-anonymous-id',featureFlags: {'flag-1': true,'variant-flag': 'control','other-flag': false,},},})
To get the flag values for bootstrapping, you can call getAllFlags()
in your server-side library, then pass the values to your frontend initialization. If you don't do this, your bootstrap values might be different than the values PostHog provides.
If the distinct user ID is an identified ID (the value you called posthog.identify()
with), you can also pass the isIdentifiedID
option. This ensures this ID is treated as an identified ID in the library. This is helpful as it warns you when you try to do something wrong with this ID, like calling identify again.
posthog.init('<ph_project_api_key>', {api_host: '<ph_instance_address>',bootstrap: {distinctID: 'your-identified-id',isIdentifiedID: true,featureFlags: {'flag-1': true,'variant-flag': 'control','other-flag': false,},},})
Forcing feature flags to update
In our JavaScript web library, we store flags as a cookie to reduce the load on the server and improve the performance of your app. This prevents always needing to make an HTTP request, flag evaluation can simply refer to data stored locally in the browser.
While this makes your app faster, it means if your user does something mid-session which causes the flag to turn on for them, this does not immediately update. As such, if you expect your app to have scenarios like this and you want flags to update mid-session, you can reload them yourself, by using the reloadFeatureFlags
function.
posthog.reloadFeatureFlags()
Calling this function forces PostHog to hit the endpoint for the updated information, and ensures changes are reflected mid-session.
Server-side local evaluation
If you're using our server-side libraries, you can use local evaluation to improve performance instead of making additional API requests.
We consider it best practice to use local evaluation flags where possible because this method enables you to resolve flags faster. This is especially true if you need to evaluate flags for multiple users — instead of sending a decide
request per user and waiting for each call to resolve, you simply serve the correct flags all at once based on the definition data.
Local evaluation calls are also more efficient. Instead of calling the API for each user, you can re-use the definitions for multiple users.
For billing purposes we count a local evaluation API request as being equivalent to 10
decide
requests. One local evaluation request can compute feature flags for hundreds or thousands of users, so this ensures local evaluation is priced fairly but normally remains the most cost-effective option by far.
Server-side local evaluation requires:
- Knowing and passing in all the person or group properties the flag relies on.
- Initializing the library with your personal API key (created in your account settings).
Local evaluation, in practice, looks like this:
await client.getFeatureFlag('beta-feature','distinct id',{personProperties: {'is_authorized': True}})# returns string or None
This works for getAllFlags
as well. It evaluates all flags locally if possible, and if not, falls back to making a decide
HTTP request.
await client.getAllFlags('distinct id', {groups: {},personProperties: { is_authorized: True },groupProperties: {},})// returns dict of flag key and value pairs.
Using locally
To test feature flags locally, you can open your developer tools and override the feature flags. You will get a warning that you're manually overriding feature flags.
posthog.feature_flags.override(['feature-flag-1', 'feature-flag-2'])
This will persist until you call override again with the argument false
:
posthog.feature_flags.override(false)
To see the feature flags that are currently active for you, you can call:
posthog.feature_flags.getFlags()