Feature flags
The feature_flags table is a key → value store for runtime configuration. Anything you want to flip without a deploy lives here.
System → Settings (/system/settings): flags live under the “Feature flags” section.
The public_ prefix rule
Section titled “The public_ prefix rule”- Flags with a key beginning with
public_are exposed on the public endpointGET /v1/flags(unauthenticated). The mobile app polls this at startup. - Flags without the prefix are admin-only (server-side reads, admin config).
Examples:
| Key | Where visible | Purpose |
|---|---|---|
public_vas_enabled_eg | Mobile | Show VAS entry in EG checkout. |
public_new_home_v2 | Mobile | New For You layout gate. |
admin_seed_debug | Admin only | Server-only toggle. |
push_apns_enabled | Server | Turn push provider on/off. |
Values
Section titled “Values”Each flag has a JSON value. Common shapes:
- Boolean:
true/false - String:
"variant_a" - Number:
100 - Object:
{ "enabled": true, "percentage": 25, "markets": ["EG", "PH"] }
The mobile client should treat missing keys as their default (usually false). Do not rely on flags to be atomically consistent across users at the exact same moment: the mobile app caches for a short TTL.
Setting a flag
Section titled “Setting a flag”System → Settings → Feature flags → Set flag:
- Key: string, unique.
- Value: JSON.
Or via API:
curl -X PUT https://api.twistcue.local/v1/admin/flags \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "key": "public_vas_enabled_eg", "value": true }'Deleting a flag
Section titled “Deleting a flag”curl -X DELETE https://api.twistcue.local/v1/admin/flags/public_vas_enabled_eg \ -H "Authorization: Bearer $ADMIN_TOKEN"Deleting = value becomes undefined. The mobile app should fall back to the default.
Every flag set/delete writes an AuditLog entry: key, before value, after value, admin_id.
Gotchas
Section titled “Gotchas”- Renaming a flag: no atomic rename. Create the new, migrate the app to read it, delete the old.
- JSON values must be valid JSON, not JS. Use
"true"(string) ortrue(bool): pick and stay consistent. public_flags are cached on the mobile side. Expect ~5 min propagation.- Flag storms: don’t accumulate hundreds of flags. Retire them once fully rolled out. Audit periodically.
API calls
Section titled “API calls”| Action | Endpoint |
|---|---|
| List flags (admin) | GET /v1/admin/flags |
| Set flag | PUT /v1/admin/flags |
| Delete flag | DELETE /v1/admin/flags/:key |
| Public flags (mobile) | GET /v1/flags (unauthenticated, returns only public_* keys) |
Full details in API, Engagement (flags live in the engagement module) and API, Public endpoints.