Server-side local evaluation

Last updated:

|Edit this page

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 can enable full access to your account, like logging in with your email and password. You can create multiple, give them different scopes, and each can be invalidated individually. This improves the security of your PostHog account. We recommend keeping them private and only using them in your server-side code.

How to obtain a personal API key

  1. Go to the Personal API keys section in your account settings

  2. Click + Create a personal API Key.

  3. Give your key a label - this is just for you, usually to describe the key's purpose.

  4. 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.

  5. 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.

How to create an api key

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 flag
personProperties: {
'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:

  1. Have experience continuity enabled, which is set when you check 'persist flag across authentication steps' on your feature flag.
  2. Are linked to an early access feature
  3. 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:

  1. There is a variant override on the condition with the cohort.
  2. They have non-person properties.
  3. There's more than one cohort in the feature flag definition.
  4. The cohort in the feature flag is in the same group as another condition.
  5. 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.

Questions?

Was this page useful?

Next article

Client-side bootstrapping

Note: Bootstrapping feature flags is only available in our JavaScript web and React Native SDKs. To bootstrap PostHog with feature flags, use the bootstrap key in the initialization config and add feature flag values to it: Setting the correct flag values To ensure you are bootstrapping PostHog with the correct flag values, we recommend fetching the flags values from your server alongside the page load request, and then passing them to your frontend. You can do this by: When receiving a…

Read next article