Note: In edge/lambda environments and stateless PHP applications, local evaluation with the default in-memory cache causes performance issues and inflated costs due to per-request initialization. For these environments, use an external cache provider to share flag definitions across requests, or 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: Find your feature flags secure API key
The feature flags secure API key is a secret project specific token listed in the Feature Flags tab of your project settings in the "Feature Flags Secure API Key" section. It provides the SDKs with access to the feature flag definitions for your project so they can evaluate flags locally.
This key needs to be kept secret, and should not be used in the frontend or exposed to users.
Note: Existing personal API keys will continue to work for local evaluation, but we recommend switching to the feature flags secure API key for local evaluation moving forward. We will be deprecating personal API keys for local evaluation in the future.
The key should be displayed in the "Feature Flags Secure API Key" section.
Copy the key and use it to initialize the PostHog client.
Step 2: Initialize PostHog with your feature flags secure API key
When you initialize PostHog with your feature flags secure API key, PostHog will use 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 flags 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 =newPostHog(
'<ph_project_api_key>',
{
host:'https://us.i.posthog.com',
personalApiKey:'your feature flags secure API key from step 1',
featureFlagsPollingInterval:30000// Optional. Measured in milliseconds. Defaults to 30000 (30 seconds)
}
)
posthog = PostHog::Client.new({
api_key:"<ph_project_api_key>",
host:"https://us.i.posthog.com",
personal_api_key:'your feature flags secure API key from step 1',
feature_flags_polling_interval:30# Optional. Measured in seconds. Defaults to 30.
})
package main
import(
"os"
"time"
"github.com/posthog/posthog-go"
)
funcmain(){
client,_:= posthog.NewWithConfig(
os.Getenv("POSTHOG_API_KEY"),
posthog.Config{
Endpoint:"https://us.i.posthog.com",
PersonalApiKey:"your feature flags secure API key",// Optional, but much more performant. If this token is not supplied, then fetching feature flag values will be slower.
DefaultFeatureFlagsPollingInterval: time.Minute *5// time.Duration // Optional. Defaults to 5 minutes.
// NextFeatureFlagsPollingTick: func() time.Duration {} // Optional. Use this to sync polling intervals between instances. For an example see: https://github.com/PostHog/posthog-go/pull/36#issuecomment-1991734125
},
)
defer client.Close()
// run commands
}
PostHog::init("<ph_project_api_key>",
array('host'=>'https://us.i.posthog.com'),
null,// or custom http client
'your feature flags secure API key from step 1'
);
// NOTE: PHP currently doesn't support a poller, so you'll need to reload flags as and when needed, or re-initialize the posthog client
from posthog import Posthog
posthog = Posthog('<ph_project_api_key>',
host='https://us.i.posthog.com',
poll_interval=30,# Optional. Measured in seconds. Defaults to 30.
personal_api_key='your feature flags secure API key from step 1'
)
// Note: We don't recommend passing these in directly.
// Instead, rely on the config system and set the personal
// api key in a secrets manager.
var client =newPostHogClient(
newPostHogOptions{
ProjectApiKey ="<ph_project_api_key>",
PersonalApiKey ="your feature flags secure API key from step 1"
.personalApiKey("your feature flags secure API key from step 1")
.pollIntervalSeconds(30)// Optional. Measured in seconds. Defaults to 30.
.build();
PostHogInterface posthog =PostHog.with(config);
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 to 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":"another_group_id",
},
groupProperties:{
'your_group_type':{
'group_property_name':'value'
},
'another_group_type':{
'group_property_name':'another 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
}
)
posthog.get_feature_flag(
'flag-key',
'distinct_id_of_the_user',
# Include any person properties, groups, or group properties required to evaluate the flag
person_properties:{
'property_name':'value'
},
groups:{
'your_group_type':'your_group_id',
'another_group_type':'another_group_id',
},
group_properties:{
'your_group_type':{
'group_property_name':'value'
}
'another_group_type':{
'group_property_name':'another value'
}
},
only_evaluate_locally: 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
)
enabledVariant, err := client.GetFeatureFlag(
FeatureFlagPayload{
Key:"flag-key",
DistinctId:"distinct_id_of_the_user",
// Include any person properties, groups, or group properties required to evaluate the flag
false,// only_evaluate_locally, Optional. Defaults to false. Set to true if you don't want PostHog to make a server request if it can't evaluate locally