Skip to main content

Feature Flags & Pricing Tiers

This document describes the Feature Flag system used to enable/disable capabilities per tenant, control beta access, and manage pricing-tier defaults.

Goals​

  • Pricing tiers: enable features by default based on a tenant’s tier (tier1/tier2/tier3).
  • Tenant overrides: force a feature on/off for a specific tenant.
  • Lifecycle safety:
    • dev features are never tenant-visible.
    • beta features are off in production unless the tenant is configured for latest access.
  • Single source of truth: API is authoritative; clients read the resolved feature flags from tenant config.

Definitions​

  • Tenant / parentCompany: the parent company identifier enforced by API middleware (verifyParent). In practice this is the Customer document’s _id and is frequently passed as a string.
  • Feature key: a stable string like dispatch.v2Board.
  • Lifecycle:
    • dev: in-development, not tenant-visible.
    • beta: preview capability (tenant-visible only when allowed).
    • ga: generally available.

High-level flow​

sequenceDiagram
participant Client
participant API
participant VerifyParent
participant ConfigSvc
participant Mongo
participant Flags

Client->>API: Request with x-parent-company header
API->>VerifyParent: validate tenant header matches token
VerifyParent->>ConfigSvc: retrieveCustomerConfig(parentCompanyId)
ConfigSvc->>Mongo: load Customer + Config(type=parent) + Config(type=system)
ConfigSvc->>Flags: resolveFeatureFlags(lifecycle+tier+overrides)
Flags-->>ConfigSvc: resolved featureFlags (tenant-visible) + meta (admin-only)
ConfigSvc-->>API: merged customerConfig
API-->>Client: config includes featureFlags

Data model​

Tenant settings (Customer / parent company)​

Stored on the Customer model:

  • planTier: tier1 | tier2 | tier3
  • releaseChannel: stable | latest
  • betaAllowlist: string[] of beta feature keys

Tenant overrides (Config: parent)​

Stored in Mongo in Config:

  • type: parent
  • relativeId: <parentCompanyId>
  • configs.featureFlagOverrides: { [featureKey: string]: boolean }

This is the persistent per-tenant kill-switch / enablement mechanism.

Tier defaults (Config: system)​

Stored in Mongo in Config:

  • type: system
  • relativeId: system
  • configs.featureTiers:
{
"tier1": { "some.flag": true },
"tier2": { "some.flag": true, "another.flag": true },
"tier3": { "some.flag": true, "another.flag": true, "pro.flag": true }
}

Resolution rules (authoritative)​

Lifecycle enforcement (highest precedence)​

  • dev:
    • Always resolves false in production.
    • Never included in tenant-visible featureFlags output.
    • Visible only in superAdmin admin tooling.
  • beta in production:
    • Resolves false unless:
      • tenant releaseChannel === 'latest', and
      • feature key is present in tenant betaAllowlist

Precedence order (after lifecycle rules)​

  1. Tenant override (Config.configs.featureFlagOverrides)
  2. Tier default (system tier defaults)
  3. Registry default (code-level default for the feature key)

API endpoints​

Tenant-facing config (includes resolved featureFlags)​

  • GET /api/v1/config/:id?type=parent
    • Returns effective tenant config, including:
      • config.configs.featureFlags
    • For superAdmins, includes _featureFlagsMeta (sources/tier/channel details).

SuperAdmin: tenant feature flags​

  • GET /api/v1/admin/feature-flags/:parentCompanyId
    • Returns tenant settings, overrides, resolved flags, and the registry.
  • PATCH /api/v1/admin/feature-flags/:parentCompanyId
    • Updates:
      • planTier, releaseChannel, betaAllowlist
      • featureFlagOverrides

SuperAdmin: global tier defaults​

  • GET /api/v1/admin/feature-flags/tiers
    • Returns tier defaults (non-dev features) and registry.
  • PATCH /api/v1/admin/feature-flags/tiers
    • Updates tier defaults and clears caches so changes apply immediately.

Web admin UI (superAdmin)​

The Service (web app) includes a superAdmin page:

  • Route: /admin/feature-flags
  • Tabs:
    • Tenant Flags: per-tenant overrides, channel, allowlist
    • Tier Defaults: global tier default toggles

Operational notes​

Cache behavior​

  • Tenant configs are cached server-side.
  • Updating tier defaults clears cache so effective configs re-resolve immediately.

Safety defaults​

  • All new flags should default to off unless you explicitly want them on.
  • Use beta for preview/early access features; keep dev for internal-only work.

Adding a new feature flag (developer workflow)​

  1. Add a new entry to the registry (feature key, lifecycle, defaultEnabled, description).
  2. Decide if it should be enabled by default in any tier.
  3. If beta, decide which tenants get access via:
    • releaseChannel=latest
    • betaAllowlist includes the feature key
  4. Gate API behavior and UI rendering using the resolved featureFlags from config.