Docs/Core Concepts/Feature Flags

Feature Flags

Control feature rollouts, run A/B tests, and manage game configuration with powerful feature flags.

10 min read

What Are Feature Flags?

Feature flags are toggles that control feature availability without code deployment. They enable:

  • Safe Releases: Roll out to small percentages first
  • Kill Switches: Instantly disable broken features
  • A/B Testing: Compare variants with real users
  • Targeting: Enable features for specific segments
  • Scheduled Launches: Time-based feature activation
Performance
Flag evaluation takes <50ms with local caching. Flags are evaluated server-side for consistent targeting.

Flag Types

TypeValuesUse Case
Booleantrue / falseSimple on/off toggles
StringAny text valueConfiguration values, variants
NumberInteger or floatThresholds, limits, multipliers
JSONComplex objectsStructured configuration
MultivariateMultiple variantsA/B/n testing

Creating Flags

Dashboard

Create flags in Dashboard > Feature Flags > Create Flag:

  1. Enter a unique flag key (e.g., "new_checkout_flow")
  2. Select the flag type
  3. Set the default value (when no rules match)
  4. Configure targeting rules (optional)
  5. Save and enable

Evaluating Flags

Boolean Flags
csharp
class=class="code-string">"code-comment">// Simple boolean check
if (IlaraClient.Instance.IsFlagEnabled(class="code-string">"new_tutorial"))
{
ShowNewTutorial();
}
else
{
ShowClassicTutorial();
}
 
class=class="code-string">"code-comment">// With explicit default
bool doubleXP = IlaraClient.Instance.IsFlagEnabled(class="code-string">"double_xp", false);
Typed Flag Values
csharp
class=class="code-string">"code-comment">// String flag
string welcomeMessage = IlaraClient.Instance.GetFlag(class="code-string">"welcome_message", class="code-string">"Hello!");
 
class=class="code-string">"code-comment">// Number flag
int maxInventorySlots = IlaraClient.Instance.GetFlag(class="code-string">"max_inventory", 20);
float xpMultiplier = IlaraClient.Instance.GetFlag(class="code-string">"xp_multiplier", 1.0f);
 
class=class="code-string">"code-comment">// JSON flag
var shopConfig = IlaraClient.Instance.GetFlag(class="code-string">"shop_config", new ShopConfig());
Multivariate Flags
csharp
class=class="code-string">"code-comment">// Get variant key for A/B tests
var evaluation = await IlaraClient.Instance.EvaluateFlag(class="code-string">"checkout_flow");
 
switch (evaluation.VariantKey)
{
case class="code-string">"control":
ShowOriginalCheckout();
break;
case class="code-string">"variant_a":
ShowSimplifiedCheckout();
break;
case class="code-string">"variant_b":
ShowOneClickCheckout();
break;
}
 
class=class="code-string">"code-comment">// Track conversion for analysis
IlaraClient.Instance.TrackEvent(class="code-string">"checkout_complete", new {
variant = evaluation.VariantKey,
flag_key = class="code-string">"checkout_flow"
});

Targeting Rules

Control who sees which flag value with targeting rules:

Segment Targeting

Target by Segment
json
{
class="code-string">"targeting_rules": [
{
class="code-string">"segment_id": class="code-string">"vip-players",
class="code-string">"value": true,
class="code-string">"percentage": 100
},
{
class="code-string">"segment_id": class="code-string">"beta-testers",
class="code-string">"value": true,
class="code-string">"percentage": 100
}
],
class="code-string">"default_value": false
}
 
class=class="code-string">"code-comment">// VIP and Beta testers get true, everyone else gets false

Percentage Rollout

Gradual Rollout
json
{
class="code-string">"targeting_rules": [
{
class="code-string">"segment_id": null, class=class="code-string">"code-comment">// All players
class="code-string">"value": true,
class="code-string">"percentage": 25 class=class="code-string">"code-comment">// 25% of players
}
],
class="code-string">"default_value": false
}
 
class=class="code-string">"code-comment">// 25% of all players get true, 75% get false
class=class="code-string">"code-comment">// Assignment is sticky - same player always gets same value

Rule Priority

Rules are evaluated top-to-bottom. First matching rule wins:

Rule Priority Example
json
{
class="code-string">"targeting_rules": [
class=class="code-string">"code-comment">// Rule 1: Highest priority - beta testers always get variant
{ class="code-string">"segment_id": class="code-string">"beta-testers", class="code-string">"value": true, class="code-string">"percentage": 100 },
 
class=class="code-string">"code-comment">// Rule 2: VIPs get 50% chance
{ class="code-string">"segment_id": class="code-string">"vip-players", class="code-string">"value": true, class="code-string">"percentage": 50 },
 
class=class="code-string">"code-comment">// Rule 3: Everyone else gets 10%
{ class="code-string">"segment_id": null, class="code-string">"value": true, class="code-string">"percentage": 10 }
],
class="code-string">"default_value": false
}

A/B Testing

Use multivariate flags to run experiments:

A/B Test Configuration
json
{
class="code-string">"key": class="code-string">"pricing_page",
class="code-string">"flag_type": class="code-string">"multivariate",
class="code-string">"variants": [
{ class="code-string">"key": class="code-string">"control", class="code-string">"value": class="code-string">"original", class="code-string">"weight": 34 },
{ class="code-string">"key": class="code-string">"variant_a", class="code-string">"value": class="code-string">"simplified", class="code-string">"weight": 33 },
{ class="code-string">"key": class="code-string">"variant_b", class="code-string">"value": class="code-string">"premium_focus", class="code-string">"weight": 33 }
],
class="code-string">"targeting_rules": [
{
class="code-string">"segment_id": class="code-string">"new-players",
class="code-string">"variants": [
{ class="code-string">"key": class="code-string">"control", class="code-string">"weight": 50 },
{ class="code-string">"key": class="code-string">"variant_a", class="code-string">"weight": 50 }
]
}
]
}
Track Experiment Events
Always track conversion events with the variant key to measure results:
csharp
IlaraClient.Instance.TrackEvent(class="code-string">"purchase_complete", new {
experiment = class="code-string">"pricing_page",
variant = evaluation.VariantKey,
revenue = 9.99
});

Flag Caching

The SDK caches flags locally for performance:

SettingDefaultDescription
cacheFlagstrueEnable local caching
flagCacheDuration300sCache TTL in seconds
Force Refresh Flags
csharp
class=class="code-string">"code-comment">// Refresh all flags from server
await IlaraClient.Instance.RefreshFlags();
 
class=class="code-string">"code-comment">// Clear cache entirely
IlaraClient.Instance.ClearFlagCache();

Kill Switches

Wrap risky features in flags for instant rollback:

Kill Switch Pattern
csharp
class=class="code-string">"code-comment">// New payment system with kill switch
if (IlaraClient.Instance.IsFlagEnabled(class="code-string">"new_payment_system", false))
{
try
{
await ProcessPaymentV2(order);
}
catch (Exception e)
{
class=class="code-string">"code-comment">// Log error - if many errors, disable flag in dashboard
Debug.LogError($class="code-string">"Payment V2 failed: {e.Message}");
class=class="code-string">"code-comment">// Fallback to old system
await ProcessPaymentV1(order);
}
}
else
{
await ProcessPaymentV1(order);
}
Instant Rollback
Disable the flag in the dashboard to instantly roll back. No deploy needed.

Best Practices

  • Name consistently: Use snake_case for keys
  • Document flags: Add descriptions explaining purpose and values
  • Clean up: Remove flags after feature is stable
  • Start small: Roll out to 1%, then 10%, then 50%, then 100%
  • Monitor: Watch error rates when rolling out
  • Test defaults: Ensure game works with default values

Next Steps