Skip to content

Use Feature Variables and Remote Config

⏱ 20 minutes intermediate

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.

  1. Add variables to a feature flag
  2. Set variable values per variation
  3. Read variables in application code
  4. Use variables for remote configuration
  1. Navigate to Feature Flags and select your flag (or create a new one)
  2. In the Variables section, click Add Variable
  3. 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
  4. Add as many variables as the flag requires
  5. Save the flag
TypeUse caseExample
StringLabels, messages, color codes"#3ab533"
IntegerCounts, limits, thresholds10
DoublePercentages, ratios0.85
BooleanOn/off sub-featurestrue
JSONStructured configuration objects{"layout": "grid", "columns": 3}

When running a feature experiment, each variation can have different variable values.

  1. Open the experiment attached to your flag
  2. For each variation, set the variable values you want to test
  3. The control variation uses the flag’s default values
  4. 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

The decide method returns a decision object whose variables property contains all variable values for the assigned variation.

Read feature variables from a decision
javascript
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);
}
python
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)
csharp
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).

  1. Create a flag with variables for your configurable values
  2. Set default values that match your current production behavior
  3. Create a targeted delivery rule to roll out the flag
  4. 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.

Remote config pattern with fallbacks
javascript
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,
  };
}
python
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'),
    }
csharp
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",
    };
}
IssueCauseFix
Variable returns null or undefinedVariable key mismatch or flag is offVerify the key matches exactly and check decision.enabled
JSON variable not parsedSDK version does not auto-parse JSONParse manually with JSON.parse() if needed
Config changes not reflectedDatafile not updatedConfirm polling is enabled and check the poll interval
Wrong variable valuesUser assigned to unexpected variationLog decision.variationKey to confirm assignment