> ## Documentation Index
> Fetch the complete documentation index at: https://docs.authforge.cc/llms.txt
> Use this file to discover all available pages before exploring further.

# Feature Flags with Variables

> Use app variables as a simple remote feature flag system; toggle features without pushing an update.

App variables let you control your application's behavior remotely. By setting boolean or string values in the dashboard, you can toggle features on or off for all users without deploying a new build.

## How it works

1. Set variables in the dashboard or via the API.
2. The SDK receives them during authentication.
3. Your app reads the variables and enables or disables features accordingly.

```mermaid theme={null}
flowchart LR
    A["Set variable in Dashboard"] --> B["User authenticates"]
    B --> C["SDK receives appVariables"]
    C --> D["App checks variables"]
    D --> E["Feature enabled/disabled"]
```

## Setup

### 1. Define your flags

In the dashboard, go to your app's **Settings → Variables** and set your flags:

```json theme={null}
{
  "newDashboard": false,
  "betaFeatures": true,
  "maxUploadSizeMb": 50,
  "maintenanceMode": false,
  "motd": ""
}
```

Or via the API:

```bash theme={null}
curl -X PUT https://api.authforge.cc/v1/apps/YOUR_APP_ID/variables \
  -H "Authorization: Bearer af_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "newDashboard": false,
    "betaFeatures": true,
    "maxUploadSizeMb": 50,
    "maintenanceMode": false,
    "motd": ""
  }'
```

### 2. Read flags in your app

<CodeGroup>
  ```python Python theme={null}
  if client.login(license_key):
      flags = client.app_variables

      # Kill switch
      if flags.get("maintenanceMode"):
          print("Application is under maintenance. Please try again later.")
          exit(0)

      # Message of the day
      motd = flags.get("motd", "")
      if motd:
          print(f"Notice: {motd}")

      # Feature toggle
      if flags.get("newDashboard"):
          show_new_dashboard()
      else:
          show_classic_dashboard()

      # Config value
      max_upload = int(flags.get("maxUploadSizeMb", 25))
      configure_upload_limit(max_upload)
  ```

  ```csharp C# theme={null}
  if (client.Login(licenseKey))
  {
      var flags = client.AppVariables;

      // Kill switch
      if (flags.TryGetValue("maintenanceMode", out var maint) && maint is true)
      {
          Console.WriteLine("Application is under maintenance.");
          Environment.Exit(0);
      }

      // Feature toggle
      var useNewDashboard = flags.TryGetValue("newDashboard", out var nd) && nd is true;
      if (useNewDashboard)
          ShowNewDashboard();
      else
          ShowClassicDashboard();
  }
  ```
</CodeGroup>

### 3. Toggle remotely

When you're ready to enable a feature, update the variable in the dashboard or via the API:

```bash theme={null}
curl -X PUT https://api.authforge.cc/v1/apps/YOUR_APP_ID/variables \
  -H "Authorization: Bearer af_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "newDashboard": true,
    "betaFeatures": true,
    "maxUploadSizeMb": 50,
    "maintenanceMode": false,
    "motd": "New dashboard is live!"
  }'
```

Users pick up the change the next time they authenticate (restart the app or the SDK re-validates in LOCAL mode).

## Practical patterns

### Kill switch / maintenance mode

Disable your app remotely without revoking licenses:

```python theme={null}
if flags.get("maintenanceMode"):
    show_maintenance_screen()
    exit(0)
```

### Minimum version enforcement

Block outdated clients:

```python theme={null}
import packaging.version

min_ver = flags.get("minVersion")
if min_ver and packaging.version.parse(APP_VERSION) < packaging.version.parse(min_ver):
    print(f"Please update to version {min_ver} or later.")
    show_update_dialog()
    exit(0)
```

### Gradual rollout

Use a percentage-based approach with the license key as a seed:

```python theme={null}
import hashlib

rollout_pct = int(flags.get("newFeatureRolloutPct", 0))
user_hash = int(hashlib.md5(license_key.encode()).hexdigest(), 16) % 100

if user_hash < rollout_pct:
    enable_new_feature()
```

### A/B testing

Assign users to groups based on their license key hash and configure behavior per group:

```python theme={null}
group = "A" if int(hashlib.md5(license_key.encode()).hexdigest(), 16) % 2 == 0 else "B"
theme = flags.get(f"theme_{group}", "default")
```

## Limitations

* Variables are delivered at authentication time, not real-time. Changes take effect on next login.
* Max 50 keys, 4 KB total. For complex configuration, use a URL variable pointing to your own config endpoint.
* Values are flat (string/number/boolean). No nested objects or arrays.

## Next steps

* [App & License Variables](/features/variables); Full variable documentation
* [Variables API](/api/variables); API reference
