Dimensions
Dimensions are the contextual attributes that Flagship uses to make intelligent decisions about feature rollouts and experiments. They represent the "who," "where," and "how" of your application's traffic.
Evaluation Context
The evaluation context is a container for arbitrary contextual data that can be used as a basis for dynamic evaluation. Static data such as the host or an identifier for the application can be configured globally. Dynamic evaluation context, such as the IP address of the client in a web application, can be implicitly propagated or explicitly passed to during flag evaluation, and can be merged with static values.
Providing Evaluation Context
In server-side SDKs, values relevant for flag evaluation can be included in the evaluation context at multiple points: globally (on the top level API), on the client, and at the point of flag evaluation (invocation).
// add a value to the global context
OpenFeature.setContext({ myGlobalKey: 'myGlobalValue' });
// add a value to the client context
const client = OpenFeature.getClient();
client.setContext({ myClientKey: 'myClientValue' });
// add a value to the invocation context
const context: EvaluationContext = {
myInvocationKey: 'myInvocationValue',
};
const boolValue = await client.getBooleanValue('boolFlag', false, context);// add a value to the global context
OpenFeatureAPI api = OpenFeatureAPI.getInstance();
api.setEvaluationContext(new MutableContext().add("myGlobalKey", "myGlobalValue"));
// add a value to the client context
Client client = api.getClient();
client.setEvaluationContext(new MutableContext().add("myClientKey", "myClientValue"));
// add a value to the invocation context
EvaluationContext context = new MutableContext();
context.addStringAttribute("myInvocationKey", "myInvocationValue")
Boolean boolValue = client.getBooleanValue("boolFlag", false, context);// add a value to the global context
Api api = Api.Instance;
api.SetContext(new EvaluationContextBuilder().Set("myGlobalKey", "myGlobalValue").Build());
// add a value to the client context
FeatureClient client = api.GetClient();
client.SetContext(new EvaluationContextBuilder().Set("myClientKey", "myClientValue").Build());
// add a value to the invocation context
var context = new EvaluationContext()
.Set("myInvocationKey", "myInvocationValue")
.Build();
var boolValue = await client.GetBooleanValue("boolFlag", false, context);// add a value to the global context
openfeature.SetEvaluationContext(openfeature.NewEvaluationContext(
"",
map[string]interface{}{
"myGlobalKey": "myGlobalValue",
},
))
// add a value to the client context
client := openfeature.NewClient("my-app")
client.SetEvaluationContext(openfeature.NewEvaluationContext(
"",
map[string]interface{}{
"myGlobalKey": "myGlobalValue",
},
))
// add a value to the invocation context
evalCtx := openfeature.NewEvaluationContext(
"",
map[string]interface{}{
"myInvocationKey": "myInvocationValue",
},
)
boolValue, err := client.BooleanValue("boolFlag", false, evalCtx)// add a value to the global context
$api = OpenFeatureAPI.getInstance();
$api->setEvaluationContext(new EvaluationContext("targetingKey", ["myGlobalKey" => "myGlobalValue"]));
// add a value to the client context
$client = $api->getClient();
$client->setEvaluationContext(new EvaluationContext("targetingKey", ["myClientKey" => "myClientValue"]));
// add a value to the invocation context
$context = new EvaluationContext("targetingKey", ["myInvocationKey" => "myInvocationValue"]);
$boolValue = $client->getBooleanValue("boolFlag", false, $context);# add a value to the global context
import openfeature.api
context = EvaluationContext("targetingKey", {"myGlobalKey": "myGlobalValue"})
openfeature.api.set_evaluation_context(context)
# add a value to the client context
client = api.get_client()
context = EvaluationContext("targetingKey", {"myClientKey": "myClientValue"})
client.set_evaluation_context(context)
# add a value to the invocation context
context = EvaluationContext("targetingKey", {"myInvocationKey": "myInvocationValue"})
bool_value = client.get_boolean_value("boolFlag", False, context)Context Merging
At the point of flag evaluation, the evaluation context is merged, and duplicate values are overwritten as defined in the specification.
Static Context (Client-side)
In client-side SDKs, values relevant for flag evaluation are set on the OpenFeature API object. In these implementations, this is an asynchronous operation associated with provider reconciliation.
// add a value to the context
await OpenFeature.setContext({ myUserData: 'myUserValue' });
// the context is used for all feature flag evaluations automatically.
const boolValue = await client.getBooleanValue('boolFlag', false);Common Examples
| Dimension | Description | Example Values |
|---|---|---|
userId | Unique identifier for the user | user_123, abc-789 |
email | User's email address | jane@example.com |
plan | Subscription level | free, pro, enterprise |
region | Geographic or cloud region | us-west, eu-central |
version | Application or SDK version | 1.2.3, v2-alpha |
device | Hardware platform | ios, android, web |
Best Practices
Circular Structures
Do not include circular structures in the evaluation context to avoid evaluation issues. Circular structures are structures that reference themselves, either directly or indirectly.
Targeting Key
Flagship requires an identifier for the subject of flag evaluation to perform fractional evaluation or percentage-based rollouts deterministically.
The evaluation context includes an optional targeting key field for this purpose. The targeting key should contain a string uniquely identifying the subject (i.e.: a UUID, a hash of some user attribute such as an email, or the hostname of an application or service).
WARNING
No Targeting Key = No Percentages Without a targeting key, Flagship cannot calculate a deterministic bucket for the user. Percentage-based rules may either fail or behave non-deterministically depending on the SDK implementation. Always provide a targeting key if you plan to use percentage rollouts.
Distribution and Percentages
Percentage rollouts (e.g., "Rollout to 50%") are implemented as a modulo operation on the hash of the targeting key: hash(targetingKey) % 100.
Flagship applies a non-identity hash function to your targeting key. This means you do not need to ensure your keys are normally distributed yourself; you only need to ensure they are unique per user.
- Good: UUIDs, User IDs, Emails (anything unique to the user).
- Bad: Shared identifiers. For example, using the string
"guest"for all anonymous users will put all guests in the same bucket (either all 0% or all 100%). - Contextual: If you are targeting a small segment (e.g., "Internal Team"), refer to the Small Target Size guidelines.
PII Considerations
Be thoughtful in your inclusion of personal data in the evaluation context. Such data is useful for targeting and dynamic evaluation.
IMPORTANT
Data Privacy Flagship performs all flag evaluations locally within your application's customized OpenFeature provider. We do not evaluate feature flags remotely, and we do not send your Evaluation Context (including any potential PII) to our backend. Your data stays with you.