How it works

60 seconds, end to end.

Create Product → create flag → scope to tenant → 50% rollout → approval → audit → revert. Seven steps. Zero Slack threads.

The 60-second version ... create flag → scope to tenant → 50% rollout → approval → audit → revert.

Step by step

Each step writes a row. Each row is queryable by product and tenant.

00 · Create Product
A Product is one thing you ship. A studio can have many.
argus product create billing_app --kind multi-tenant

Each Product gets its own apiKey, its own flag namespace, and (if multi-tenant) its own tenant list. A studio with three apps has three Products under one Customer. Singleton Products skip the tenant step entirely — value resolves globally.

01 · Create flag
Define the flag and its default — scoped to the active Product.
argus flag create new_billing_v2 --product billing_app --env prod --default off

The flag enters the system inside one Product, with a key, an environment, and a default value. No tenant has it yet. Flag names are unique per Product, not per Customer — two Products at the same studio can each have a new_checkout flag without colliding.

02 · Scope to tenant
One tenant gets a per-tenant override document.
argus tenant 98chimp set new_billing_v2 on

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.

03 · 50% rollout
Per-tenant percentage · deterministic per-user bucketing.
argus rollout new_billing_v2 --tenant 98chimp --pct 50

The same user inside tenant 98chimp gets the same outcome on every evaluation. No surprise drift between sessions, regions, or SDK reloads.

04 · Two-engineer approval
Production-impacting changes wait for a second reviewer.
approval requested · awaiting 1 of 2 · reviewers marco, roberto

Required, not configurable. Solo deploys to prod are not a feature; the system enforces them out of existence.

05 · Audit row written
Append-only. Tenant-scoped. Source metadata travels.
actor=shahin env=prod tenant=98chimp flag=new_billing_v2 before=off after=50% ts=2026-05-04T22:08:14Z

The row carries the source of the change (rule · override · rollout) so a compliance question two quarters later does not need archaeology.

06 · Revert · one tenant, one click
Roll back for 98chimp without touching loomi or dk_derby.
argus rollback new_billing_v2 --tenant 98chimp · blast radius = 0

The override flips. A new audit row appends. Cross-tenant blast radius is zero by construction — because there is no shared rule to edit.

Why this works

Product + tenant are required at the storage layer.

Every flag, every rule, every audit row carries a productId and (for multi-tenant Products) a tenantId at the storage layer. Bypass is impossible — not because we ask the SDK nicely, but because the row can't be written without both.

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
Layer 04SDK
evaluate() subscribe() audit()
Layer 03Rules
flag override rollout
Layer 02Tenant
tenant_id env scope
Layer 01Storage
firestore cloud functions
What this replaces

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".
What's next

See where Argus fits. We respond in writing within two business days.