Note: Local evaluation is only available in the Node, Ruby, Go, Python, and PHP SDKs.
Note: Do not use local evaluation in an edge / lambda environment, as this can slow down performance, and also raise your bill drastically. It's best to use regular flag evaluation instead.
Evaluating feature flags requires making a request to PostHog for each flag. However, you can improve performance by evaluating flags locally. Instead of making a request for each flag, PostHog will periodically request and store feature flag definitions locally, enabling you to evaluate flags without making additional requests.
It is best practice to use local evaluation flags when possible, since this enables you to resolve flags faster and with fewer API calls.
There are 3 steps to enable local evaluation:
Step 1: Obtain a personal API key
Personal API keys enable full access to your account, like an email address and password. You can create multiple, give them different scopes, and each can be invalidated individually. This improves the security of your PostHog account.
How to obtain a personal API key
Go to the Personal API keys section in your account settings
Click "+ Create a personal API Key".
Give your key a label - this is just for you, usually to describe the key's purpose.
Choose the scopes for your key. We recommended selecting only the scopes required for the API endpoints you really need. This is a security best practice. You can always modify the scopes later if you need to.
At the top of the list, you should see your brand new key. Immediately copy its value, as you'll never see it again after refreshing the page.
You can create as many keys as you like.
Step 2: Initialize PostHog with your personal API key
When you initialize PostHog with your personal API key, PostHog will use your the key to automatically fetch feature flag definitions. These definitions are then used to evaluate feature flags locally.
By default, PostHog fetches these definitions every 30 seconds (or 5 minutes in the Go SDK). However, you can change this frequency by specifying a different value in the polling interval argument.
Note: For billing purposes, we count the request to fetch the feature flag definitions as being equivalent to
10 decide
requests.This is because one of these requests can compute feature flags for hundreds or thousands of users. It ensures local evaluation is priced fairly while remaining the most cost-effective option (by far!).
const client = new PostHog('<ph_project_api_key>',{host: https://us.i.posthog.com,personalApiKey: 'your personal API key from step 1',featureFlagsPollingInterval: 30000 // Optional. Measured in milliseconds. Defaults to 30000 (30 seconds)})
Step 3: Evaluate your feature flag
To evaluate the feature flag, call any of the flag related methods, like getFeatureFlag
or getAllFlags
, as you normally would. The only difference is that you must provide any person properties
, groups
or group properties
used to evaluate the release conditions of the flag.
Then, by default, PostHog attempts to evaluate the flag locally using definitions it loads on initialization and at the poll interval
. If this fails, PostHog then makes a server request fetch the flag value.
You can disable this behavior by setting onlyEvaluateLocally
to true
. In this case, PostHog will only attempt to evaluate the flag locally, and return undefined
/ None
/ nil
if it was unable to.
await client.getFeatureFlag('flag-key','distinct_id_of_the_user',{// include any person properties, groups, or group properties required to evaluate the flagpersonProperties: {'property_name': 'value'},groups: {"your_group_type": "your_group_id","another_group_type": "your_group_id",},groupProperties: {'your_group_type': {'group_property_name': 'value'},'another_group_type': {'group_property_name': 'value'}},onlyEvaluateLocally: false, // Optional. Defaults to false. Set to true if you don't want PostHog to make a server request if it can't evaluate locally})
Reloading flags
As mentioned in step 2, PostHog periodically fetches feature flag definitions. However, you can also force a reload by calling reloadFeatureFlags()
:
await client.reloadFeatureFlags()
Restriction on local evaluation
General restrictions
Local evaluation is not possible for flags that:
- Have experience continuity enabled, which is set when you check 'persist flag across authentication steps' on your feature flag.
- Are linked to an early access feature
- Depend on static cohorts
Dynamic cohort restrictions
Note: This restriction does not apply to our Go SDK, v2.6.0 and above of our Node SDK, and to v2.4.0 and above of our Python SDK.
To enable local evaluation of feature flags that depend on dynamic cohorts, we translate the cohort definition into person properties.
However, there are a few constraints, and cohorts cannot be evaluated locally if:
- There is a variant override on the condition with the cohort.
- They have non-person properties.
- There's more than one cohort in the feature flag definition.
- The cohort in the feature flag is in the same group as another condition.
- The cohort has nested AND-OR filters. Only simple cohorts that have a top level OR group, and inner level ANDs will be evaluated locally.