Use Feature Variables and Remote Config
Why use feature variables
Section titled “Why use feature variables”Hard-coded values require a deployment to change. Feature variables let you attach configurable values — strings, numbers, booleans, JSON — to a feature flag and update them from the Optimizely dashboard. Use them for remote configuration, gradual rollouts with different settings, or A/B testing variable values across variations.
What you will do
Section titled “What you will do”- Add variables to a feature flag
- Set variable values per variation
- Read variables in application code
- Use variables for remote configuration
Step 1: Add variables to a feature flag
Section titled “Step 1: Add variables to a feature flag”- Navigate to Feature Flags and select your flag (or create a new one)
- In the Variables section, click Add Variable
- Configure each variable:
- Key — lowercase with underscores (e.g.,
max_items,banner_text) - Type — String, Integer, Double, Boolean, or JSON
- Default value — the fallback when the flag is off
- Key — lowercase with underscores (e.g.,
- Add as many variables as the flag requires
- Save the flag
Supported variable types
Section titled “Supported variable types”| Type | Use case | Example |
|---|---|---|
| String | Labels, messages, color codes | "#3ab533" |
| Integer | Counts, limits, thresholds | 10 |
| Double | Percentages, ratios | 0.85 |
| Boolean | On/off sub-features | true |
| JSON | Structured configuration objects | {"layout": "grid", "columns": 3} |
Step 2: Set variable values per variation
Section titled “Step 2: Set variable values per variation”When running a feature experiment, each variation can have different variable values.
- Open the experiment attached to your flag
- For each variation, set the variable values you want to test
- The control variation uses the flag’s default values
- Treatment variations override specific variables
For example, testing a search algorithm:
- Control:
algorithm = "keyword_v1",max_results = 20 - Variation A:
algorithm = "semantic_v2",max_results = 50 - Variation B:
algorithm = "hybrid_v1",max_results = 30
Step 3: Read variables in code
Section titled “Step 3: Read variables in code”The decide method returns a decision object whose variables property contains all variable values for the assigned variation.
const decision = user.decide('search_config');
if (decision.enabled) {
const algorithm = decision.variables.algorithm; // string
const maxResults = decision.variables.max_results; // integer
const boostRecent = decision.variables.boost_recent; // boolean
const layout = decision.variables.layout_config; // JSON (parsed)
applySearch({ algorithm, maxResults, boostRecent, layout });
} else {
applySearch(DEFAULT_SEARCH_CONFIG);
} decision = user.decide('search_config')
if decision.enabled:
algorithm = decision.variables['algorithm'] # string
max_results = decision.variables['max_results'] # integer
boost_recent = decision.variables['boost_recent'] # boolean
layout = decision.variables['layout_config'] # JSON (parsed dict)
apply_search(algorithm, max_results, boost_recent, layout)
else:
apply_search(**DEFAULT_SEARCH_CONFIG) var decision = user.Decide("search_config");
if (decision.Enabled)
{
var algorithm = decision.Variables.GetValue<string>("algorithm");
var maxResults = decision.Variables.GetValue<int>("max_results");
var boostRecent = decision.Variables.GetValue<bool>("boost_recent");
var layout = decision.Variables.GetValue<string>("layout_config"); // JSON string
ApplySearch(algorithm, maxResults, boostRecent, layout);
}
else
{
ApplySearch(DefaultSearchConfig);
} Always provide fallback values. If a variable key is missing or the flag is off, your code should use sensible defaults.
Step 4: Use variables for remote configuration
Section titled “Step 4: Use variables for remote configuration”Feature variables are not limited to experiments. Use them as a remote configuration system by creating a flag with a rollout (no experiment required).
- Create a flag with variables for your configurable values
- Set default values that match your current production behavior
- Create a targeted delivery rule to roll out the flag
- When you need to change a value, update it in the Optimizely dashboard
The SDK picks up changes on its next datafile poll (typically 30-60 seconds). No redeployment needed.
function getAppConfig(user) {
const decision = user.decide('app_config');
return {
maintenanceMode: decision.variables.maintenance_mode ?? false,
maxUploadSizeMb: decision.variables.max_upload_size_mb ?? 25,
supportEmail: decision.variables.support_email ?? 'support@example.com',
featureAnnouncement: decision.variables.announcement_json ?? null,
};
} def get_app_config(user):
decision = user.decide('app_config')
return {
'maintenance_mode': decision.variables.get('maintenance_mode', False),
'max_upload_size_mb': decision.variables.get('max_upload_size_mb', 25),
'support_email': decision.variables.get('support_email', 'support@example.com'),
'feature_announcement': decision.variables.get('announcement_json'),
} public AppConfig GetAppConfig(OptimizelyUserContext user)
{
var decision = user.Decide("app_config");
return new AppConfig
{
MaintenanceMode = decision.Variables.GetValue<bool?>("maintenance_mode") ?? false,
MaxUploadSizeMb = decision.Variables.GetValue<int?>("max_upload_size_mb") ?? 25,
SupportEmail = decision.Variables.GetValue<string>("support_email") ?? "support@example.com",
};
} Troubleshooting
Section titled “Troubleshooting”| Issue | Cause | Fix |
|---|---|---|
Variable returns null or undefined | Variable key mismatch or flag is off | Verify the key matches exactly and check decision.enabled |
| JSON variable not parsed | SDK version does not auto-parse JSON | Parse manually with JSON.parse() if needed |
| Config changes not reflected | Datafile not updated | Confirm polling is enabled and check the poll interval |
| Wrong variable values | User assigned to unexpected variation | Log decision.variationKey to confirm assignment |
1. Your team needs to change the maximum upload size from 25MB to 50MB in production without deploying code. You already have an Optimizely SDK integrated. What is the best approach?
Feature variables enable remote configuration. Create a flag with an integer variable, deploy code that reads the variable with a fallback default, then change the value anytime from the Optimizely dashboard. The SDK picks up changes on its next datafile poll without redeployment.
Feature variables enable remote configuration. Create a flag with an integer variable, deploy code that reads the variable with a fallback default, then change the value anytime from the Optimizely dashboard. The SDK picks up changes on its next datafile poll without redeployment.
Review this topic →2. A developer reads a feature variable but gets null instead of the expected value. The feature flag exists and the variable key matches. What should they investigate?
When a feature flag is off for a user, decision.enabled is false and variables may return null or undefined. Always check decision.enabled and provide fallback values. The code should handle the disabled state gracefully with sensible defaults.
When a feature flag is off for a user, decision.enabled is false and variables may return null or undefined. Always check decision.enabled and provide fallback values. The code should handle the disabled state gracefully with sensible defaults.
Review this topic →3. You want to A/B test a search configuration with three variations: different algorithm versions, result limits, and boost settings. How should you structure the feature flag?
A single feature flag with multiple typed variables keeps related configuration together. Each experiment variation sets its own values for the variables. The control uses defaults, and treatment variations override specific values. This is cleaner than multiple flags or hard-coded branches.
A single feature flag with multiple typed variables keeps related configuration together. Each experiment variation sets its own values for the variables. The control uses defaults, and treatment variations override specific values. This is cleaner than multiple flags or hard-coded branches.
Review this topic →