60 seconds, end to end.
Create flag → scope to tenant → 50% rollout → approval → audit → revert. Six steps. Zero Slack threads.
v1 · video · v1.5 · interactive walkthrough (navattic / arcade)
Each step writes a row. Each row is queryable by tenant.
The flag enters the system with a key, an environment, and a default value. No tenant has it yet. The default is what every tenant resolves to until you change it for one.
Override documents are first-class — not segment clauses. They have an audit stream, an owner, and a resolution lane. Touching tenant 98chimp does not touch tenant loomi.
The same user inside tenant 98chimp gets the same outcome on every evaluation. No surprise drift between sessions, regions, or SDK reloads.
Required, not configurable. Solo deploys to prod are not a feature; the system enforces them out of existence.
The row carries the source of the change (rule · override · rollout) so a compliance question two quarters later does not need archaeology.
The override flips. A new audit row appends. Cross-tenant blast radius is zero by construction — because there is no shared rule to edit.
Tenant is required at the storage layer.
Every flag, every rule, every audit row is tenant-scoped at the storage layer. Bypass is impossible — not because we ask the SDK nicely, but because the row can't be written without one.
MVP runs on Firebase: Firestore as data plane and change log via onSnapshot, Cloud Functions enforcing approvals and audit writes. A custom data plane is a post-PMF decision.
See the data model →Four artifacts that should not exist anymore.
- The "is feature X on for client Y?" Slack thread that pings three engineers.
- The custom user segment named tenant_b_only_pilot_v3 with a TODO from last quarter.
- The spreadsheet titled Brand Feature Matrix - DO NOT EDIT that everybody edits.
- The post-incident grep for "what changed for the regulated customer last quarter".