Feature flags¶
Purpose¶
Feature flags in Evospin are not managed inside ebit-admin-fe. They ride GitLab Unleash (the OSS feature-flag service hosted by GitLab). Engineering toggles flags in the Unleash UI; the api app reads them at runtime via the feature-flag.module.ts. This doc explains the integration so admin operators know where to look and where the boundary is.
Audience¶
Engineering (primary; toggles flags for staged rollouts). Operations rarely interacts directly — but during incident response, ops may be asked to confirm a flag state via engineering.
Path in admin-fe¶
| Screen | URL | Page |
|---|---|---|
| Feature flag UI inside admin-fe | (none) | {{NOT IMPLEMENTED}} |
Flags live at GitLab Unleash. The endpoint base + project ID + token are configured via env vars in ebit-api.
Backing module / config¶
| File | Role |
|---|---|
apps/api/src/system/feature-flag/feature-flag.module.ts |
Wires Unleash client; exposes FS.isEnabled('<flag-name>', user) |
apps/api/src/auth/guards/permission.guard.ts:36-38 |
One example consumer — flag disable_otp exempts a user from MFA requirement |
Search the codebase for FS.isEnabled( to see all flag consumers.
Key actions¶
There are no in-admin actions. The actions are:
| Action | Where | Who |
|---|---|---|
| Create / toggle a flag | GitLab Unleash UI (out-of-band) | Engineering |
| Read flag state for a user | runtime, via FS.isEnabled('<flag>', user) in code |
API server |
| Verify flag is on for a user | /admin-logs audit trail (look for the action that bypassed because flag was on) |
Engineering / compliance |
Common workflows¶
- Staged rollout of a new endpoint. Engineer adds
FS.isEnabled('new-bet-api', user)in code. Deploys with flag off. In Unleash, gradually enable for 5% → 25% → 100% of users. Watch metrics inobservability.md. - Disable MFA for a stuck operator. Set
disable_otpon for that admin's user ID via Unleash strategy. They can now perform OTP-required actions without MFA. Highly auditable — every bypass shows in admin-logs.md. Use sparingly. - Kill switch. A flag like
disable_promo_redemptioncan be flipped off in seconds during a promo abuse incident. - A/B test a new home grid order. {{NOT IMPLEMENTED}} as a flag pattern in code today — would require new consumers.
Edge cases / gotchas¶
- Flag-state caching. The Unleash client caches flag values for short TTL (default ~10s). A toggle takes a few seconds to propagate to all api replicas.
- No per-request override. Flags are evaluated against the user (or anonymous context). You cannot "force off" a flag via a header.
- Flags don't appear in
AdminActionLog. Their consumption is invisible — you can only infer "the flag was on" from the bypass behavior. To confirm: query Unleash audit log on the GitLab side. - Removing a flag in code requires Unleash cleanup too. Stale flags accumulate in Unleash. Engineering periodically prunes.
- No flag-state surface in admin-fe. If ops needs to know "is
feature-Xon right now?", ask engineering. Tracked as a feature gap; would require either a passthrough endpoint or admin Unleash SSO. - Per-user targeting strategies (Unleash) can collide with per-role logic in the api. Always read the flag and the role check; never replace one with the other.
Cross-links¶
- Code consumer pattern:
grep -rn "FS.isEnabled" apps/api/src/ - Recipe:
recipes/enable-feature-flag.md - Incident kill-switches:
handover/oncall-runbook.md - Stack inventory entry:
engineering/→ "Feature flags" - ADR (if exists):
adr/
Sequence — staged rollout via Unleash¶
sequenceDiagram
actor eng as Engineering
participant gitlab as GitLab Unleash
participant api as ebit-api (replicas)
participant grafana as Grafana
eng->>gitlab: toggle "new-bet-api" to 5% strategy
gitlab-->>api: pulled on next 10s tick
Note over api: FS.isEnabled('new-bet-api', user) — random 5% return true
api->>grafana: spans tagged with feature.new-bet-api=true|false
eng->>grafana: monitor error rate, p95 latency for users in test arm
eng->>gitlab: ramp to 100% (or rollback)