Skip to content

SDK decide() Method Reference

intermediate

The decide method evaluates a feature flag for a specific user and returns a decision object containing the enabled state, variation key, flag variables, and optional reasoning. You call decide on a user context — never on the client directly.

Every flag evaluation flows through decide. It replaces the legacy isFeatureEnabled and getFeatureVariable* methods with a single, unified call.

decide() method signatures
javascript
// On an OptimizelyUserContext instance
const decision = user.decide(
  flagKey,   // string — the feature flag key
  options    // OptimizelyDecideOption[] (optional)
);

// Decide multiple flags at once
const decisions = user.decideForKeys(
  flagKeys,  // string[] — array of flag keys
  options    // OptimizelyDecideOption[] (optional)
);

// Decide all flags in the project
const allDecisions = user.decideAll(
  options    // OptimizelyDecideOption[] (optional)
);
csharp
// On an OptimizelyUserContext instance
OptimizelyDecision decision = user.Decide(
    string flagKey,
    OptimizelyDecideOption[] options = null
);

// Decide multiple flags at once
Dictionary<string, OptimizelyDecision> decisions = user.DecideForKeys(
    string[] flagKeys,
    OptimizelyDecideOption[] options = null
);

// Decide all flags in the project
Dictionary<string, OptimizelyDecision> allDecisions = user.DecideAll(
    OptimizelyDecideOption[] options = null
);
python
# On an OptimizelyUserContext instance
decision = user.decide(
    flag_key,   # str — the feature flag key
    options     # list[str] (optional)
)

# Decide multiple flags at once
decisions = user.decide_for_keys(
    flag_keys,  # list[str] — list of flag keys
    options     # list[str] (optional)
)

# Decide all flags in the project
all_decisions = user.decide_all(
    options     # list[str] (optional)
)
ParameterTypeRequiredDescription
flagKeystringYesThe key of the feature flag to evaluate. Must match a flag key in your Optimizely project.
optionsOptimizelyDecideOption[]NoAn array of decision options that modify evaluation behavior. See the options table below.

The decide method returns an OptimizelyDecision object with the following fields.

FieldTypeDescription
variationKeystringThe key of the variation the user bucketed into. null if the flag is not running or the user is not in the experiment.
enabledbooleanWhether the feature is enabled for this user. This is the primary field you check.
variablesobject / DictionaryA map of variable keys to their values for this user’s variation. Variable types are preserved (string, integer, double, boolean, JSON).
ruleKeystringThe key of the rule (delivery or experiment) that determined this decision. null if no rule matched.
flagKeystringThe flag key that was evaluated. Echoes back the input parameter.
userContextOptimizelyUserContextThe user context that was used to make this decision.
reasonsstring[]An array of human-readable strings explaining how the decision was made. Only populated when INCLUDE_REASONS is set.

Pass these options to control how decide evaluates the flag.

OptionDescription
DISABLE_DECISION_EVENTPrevents the SDK from sending an impression event for this decision. Use this when you evaluate flags outside of experiment contexts (for example, during pre-rendering) and do not want to pollute experiment results.
ENABLED_FLAGS_ONLYWhen used with decideForKeys or decideAll, returns only flags where enabled is true. Reduces payload size when you only care about active features.
IGNORE_USER_PROFILE_SERVICEBypasses the user profile service for this decision. The user may be bucketed into a different variation than what was previously stored. Use with caution — this breaks sticky bucketing.
INCLUDE_REASONSPopulates the reasons field on the returned decision object with human-readable strings explaining each step of the evaluation. Use for debugging only — the reasons array adds overhead.
EXCLUDE_VARIABLESOmits the variables field from the returned decision. Use when you only need the enabled state and want to reduce object size.
Using decision options
javascript
import { OptimizelyDecideOption } from '@optimizely/optimizely-sdk';

// Debug a decision with full reasoning
const decision = user.decide('checkout_redesign', [
  OptimizelyDecideOption.INCLUDE_REASONS,
]);

console.log('Enabled:', decision.enabled);
console.log('Reasons:', decision.reasons);

// Evaluate without triggering an impression
const preRenderDecision = user.decide('hero_banner', [
  OptimizelyDecideOption.DISABLE_DECISION_EVENT,
]);
csharp
using OptimizelySDK;

// Debug a decision with full reasoning
var decision = user.Decide("checkout_redesign", new[]
{
    OptimizelyDecideOption.INCLUDE_REASONS,
});

Console.WriteLine($"Enabled: {decision.Enabled}");
foreach (var reason in decision.Reasons)
{
    Console.WriteLine($"Reason: {reason}");
}

// Evaluate without triggering an impression
var preRenderDecision = user.Decide("hero_banner", new[]
{
    OptimizelyDecideOption.DISABLE_DECISION_EVENT,
});
python
from optimizely.decision.optimizely_decide_option import OptimizelyDecideOption

# Debug a decision with full reasoning
decision = user.decide('checkout_redesign', [
    OptimizelyDecideOption.INCLUDE_REASONS,
])

print(f'Enabled: {decision.enabled}')
for reason in decision.reasons:
    print(f'Reason: {reason}')

# Evaluate without triggering an impression
pre_render_decision = user.decide('hero_banner', [
    OptimizelyDecideOption.DISABLE_DECISION_EVENT,
])

When INCLUDE_REASONS is enabled, the reasons array contains strings describing each evaluation step. Common reason values include:

ReasonWhen it appears
"User \"{userId}\" is in variation \"{variationKey}\" of experiment \"{experimentKey}\"."The user was bucketed into an experiment variation.
"User \"{userId}\" meets audience conditions for rule \"{ruleKey}\"."The user matched the audience conditions on a delivery or experiment rule.
"User \"{userId}\" does not meet audience conditions for rule \"{ruleKey}\"."The user did not match any audience condition on the rule.
"Feature \"{flagKey}\" is not enabled for user \"{userId}\"."No rule matched and the flag’s default state is off.
"Forced decision found for flag \"{flagKey}\", rule \"{ruleKey}\"."A forced decision was set on the user context, overriding normal evaluation.
"User \"{userId}\" is excluded from rollout \"{ruleKey}\" due to traffic allocation."The user matched the audience but fell outside the traffic percentage.

The SDK evaluates rules in this order:

  1. Forced decisions — If setForcedDecision was called for this flag, that variation is returned immediately.
  2. Experiment rules — A/B tests and multi-armed bandit experiments, in the order they appear in the Optimizely app.
  3. Delivery rules — Targeted deliveries (rollouts), evaluated top to bottom.
  4. Default (“Everyone else”) — The flag’s default enabled state and default variable values.

The first matching rule wins. Once a user matches a rule’s audience and falls within its traffic allocation, that rule’s variation is returned.

If flagKey does not exist in the project configuration, decide returns a decision object with:

  • enabled set to false
  • variationKey set to null
  • variables set to an empty object
  • reasons containing an error message (if INCLUDE_REASONS is enabled)

The SDK does not throw exceptions for invalid flag keys. Always check enabled before acting on the decision.