Skip to content
Back to skills

Feature Flags And Configuration

ASecurity

Feature flags, features registry, and app arguments. Use when gating features behind remote flags (FeatureFlagsConfiguration), feature gating, conditional features, runtime configuration, command-line flags, launch arguments, registering features in FeaturesRegistry, checking or adding app arguments (AppArgs), or implementing feature providers.

  • 23 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added May 27, 2026
developmentgoperformance

Security analysis

A100/100

Scanned May 27, 2026

npx -y skills add decentraland/unity-explorer --skill feature-flags-and-configuration --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Feature Flags And Configuration?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Feature Flags And Configuration
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/decentraland-feature-flags-and-configuration/badge)](https://www.skillsdirectory.com/skills/decentraland-feature-flags-and-configuration)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: feature-flags-and-configuration
description: "Feature flags, features registry, and app arguments. Use when gating features behind remote flags (FeatureFlagsConfiguration), feature gating, conditional features, runtime configuration, command-line flags, launch arguments, registering features in FeaturesRegistry, checking or adding app arguments (AppArgs), or implementing feature providers."
user-invocable: false
---

# Feature Flags & Configuration

## Sources

- `docs/feature-flags.md` — Runtime feature flag system
- `docs/features-registry.md` — Centralized feature state management
- `docs/app-arguments.md` — Command-line flags and arguments

---

## When to Use Each Mechanism

| Need | Mechanism |
|------|-----------|
| Simple remote flag | `FeatureFlagsConfiguration.IsEnabled()` |
| Flag + app args combined | `FeaturesRegistry` |
| Runtime-dependent check | `IFeatureProvider` + `FeaturesRegistry` |
| Launch-time configuration only | `AppArgs.HasFlag()` / `TryGetValue()` |

---

## Feature Flags (Remote)

### Fetching

`IFeatureFlagsProvider.GetAsync()` calls the remote endpoint with:
- User address
- Debug flag
- Referer header

Default endpoint: `https://feature-flags.decentraland.org/explorer.json`

### Naming Convention

- **Server side:** `explorer-alfa-your-feature`
- **Codebase:** `alfa-your-feature` (prefix `explorer-` is stripped automatically)

### Checking Feature Flags

```csharp
// Simple check
bool enabled = featureFlagsCache.Configuration.IsEnabled("alfa-your-feature");

// Check with variant
bool enabled = featureFlagsCache.Configuration.IsEnabled("alfa-your-feature", "my-variant");

// Static shorthand (common pattern)
bool enabled = FeatureFlagsConfiguration.Instance.IsEnabled(FeatureFlagsStrings.CUSTOM_MAP_PINS_ICONS);
```

### Code Example — Feature Flag Gating

From `MapPinLoaderSystem.cs`:

```csharp
public partial class MapPinLoaderSystem : BaseUnityLoopSystem, IFinalizeWorldSystem
{
    private readonly bool useCustomMapPinIcons;

    public MapPinLoaderSystem(World world, /* ... */) : base(world)
    {
        // Cache flag value in constructor — Why: flag checks happen every frame in Update;
        // re-fetching from config every frame is wasteful
        useCustomMapPinIcons = FeatureFlagsConfiguration.Instance.IsEnabled(
            FeatureFlagsStrings.CUSTOM_MAP_PINS_ICONS);
    }

    protected override void Update(float t)
    {
        LoadMapPinQuery(World);
        UpdateMapPinQuery(World);
        HandleComponentRemovalQuery(World);
        HandleEntityDestructionQuery(World);

        // Conditionally run texture loading
        if (useCustomMapPinIcons)
            ResolveTexturePromiseQuery(World);
    }
}
```

### Variants

Feature flags can carry payload data in three formats:

```csharp
// String payload
if (config.TryGetTextPayload("alfa-feature", "variantId", out string? text))
    UseText(text);

// CSV payload (returns rows × columns)
if (config.TryGetCsvPayload("alfa-feature", "variantId", out List<List<string>>? csv))
    UseValues(csv);

// JSON payload (deserializes to DTO type)
if (config.TryGetJsonPayload<MyConfigDto>("alfa-feature", "variantId", out MyConfigDto? dto))
    UseConfig(dto);
```

### Configuration Options

```csharp
var options = new FeatureFlagOptions
{
    UserId = userAddress,
    URL = flagsEndpoint,
    AppName = "explorer",
    Hostname = hostname
};
```

Overridable via app arguments:
- `--feature-flags-url` — Custom endpoint URL
- `--feature-flags-hostname` — Custom hostname

## Features Registry (Local)

`FeaturesRegistry` is a singleton that consolidates feature enable/disable logic from multiple sources: feature flags, app arguments, editor mode, and runtime conditions.

**Why FeaturesRegistry exists alongside FeatureFlagsConfiguration:** `FeatureFlagsConfiguration` only handles remote flags. `FeaturesRegistry` consolidates all sources (remote flags, app args, editor mode, runtime checks) into a single query point, so systems don't need to check multiple sources.

### Declaring Features

```csharp
// Each feature gets a FeatureId (numbered enum)
public enum FeatureId
{
    YOUR_FEATURE = 42,
}
```

### Registering Feature States

```csharp
// In SetFeatureStates (bulk registration)
public void SetFeatureStates(FeatureFlagsCache cache, AppArgs args)
{
    SetFeatureState(FeatureId.YOUR_FEATURE,
        cache.Configuration.IsEnabled("alfa-your-feature") || args.HasFlag("--enable-feature"));
}

// Or individually
FeaturesRegistry.Instance.SetFeatureState(FeatureId.YOUR_FEATURE, true);
```

### Checking Features

```csharp
bool enabled = FeaturesRegistry.Instance.IsEnabled(FeatureId.YOUR_FEATURE);
```

### Feature Providers

For runtime-dependent features (e.g., user-specific checks):

```csharp
public class MyFeatureProvider : IFeatureProvider
{
    public FeatureId FeatureId => FeatureId.MY_FEATURE;

    public async UniTask<bool> IsFeatureEnabledAsync(CancellationToken ct)
    {
        // Runtime check (e.g., server call)
        return await CheckIfEnabledAsync(ct);
    }
}

// Register
FeaturesRegistry.Instance.RegisterFeatureProvider(new MyFeatureProvider());
```

Feature providers should cache values and reset on condition change.

## App Arguments

Command-line flags that configure application behavior. Work via command line or deep links.

### Usage

```
# Command line
--flag-name value

# Deep link
decentraland://?flag-name=value
```

### Key Flags by Category

| Category | Flag | Purpose |
|----------|------|---------|
| General | `--debug` | Enable debug mode |
| General | `--hub` | Hub mode |
| Environment | `--realm` | Target realm |
| Environment | `--local-scene` | Local scene development |
| Environment | `--position` | Starting position |
| Auth | `--skip-auth-screen` | Skip authentication |
| Performance | `--disable-disk-cache` | Disable disk cache |
| Performance | `--simulateMemory` | Simulate memory pressure |
| Development | `--use-log-matrix` | Custom log matrix JSON file |
| Development | `--launch-cdp-monitor-on-start` | Launch CDP monitor |
| Feature Flags | `--feature-flags-url` | Custom FF endpoint |
| Feature Flags | `--feature-flags-hostname` | Custom FF hostname |
| Display | `--windowed-mode` | Force windowed mode |

### Accessing in Code

```csharp
// Check flag presence
if (appArgs.HasFlag(AppArgsFlags.DEBUG))
    EnableDebugMode();

// Get flag value
if (appArgs.TryGetValue(AppArgsFlags.REALM, out var realm))
    UseRealm(realm);
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.