ADR-0011: Feature Flags Architecture

Prev Next

Context

The platform requires a controlled way to enable, disable, and gradually roll out features across environments, users, and organizations without relying on redeployments.

Previous approaches risked:

  • UI-driven toggles leaking into business logic
  • Remote feature flag tools becoming the source of truth
  • Flags accumulating indefinitely with unclear ownership
  • Feature flag infrastructure becoming a hard dependency that could break the app if misconfigured

Additionally, the backend team was not positioned to own or expose feature-flag evaluation APIs, requiring a frontend/server-side owned solution that remained safe, testable, and portable.

A clear architectural boundary was needed to ensure:

  • Code remains the authority over what features can exist
  • Remote tools remain advisory, not authoritative
  • Feature flags cannot compromise application stability or security

Decision

The platform will implement a code-owned feature flag system with the following properties:

  • All feature flags must be declared in a central registry in code
  • Remote feature flag tools (e.g. GrowthBook) are advisory only
  • Only registry-declared flags are evaluated; all others are ignored
  • Feature flags are resolved server-side
  • UI consumes derived, intent-based flags, never raw infrastructure flags
  • Feature flag infrastructure is optional and must fail safely
  • Anonymous and authenticated users use the same resolver with different available context
  • A Next.js server API (/api/platform/features) is the single delivery point for UI-facing flags.
  • For this endpoint to work correctly, there needs to be NEXT_PUBLIC_PLATFORM_BASE_URL added in the main environment variables.

The system is designed as a portable engine, independent of Next.js, GrowthBook, or OneCMS-specific concepts.

Image

Consequences

Enables

  • Safe feature rollouts without redeployments
  • Deterministic behavior with explicit defaults
  • Easy deletion of obsolete feature flags
  • Frontend-owned delivery without backend dependency
  • Portability of the feature flag engine to other projects
  • Clear separation between infrastructure concerns and UI behavior

Restricts

  • Feature flags cannot be created or consumed ad-hoc
  • All new flags require a code change (registry update)
  • UI cannot directly access or reason about infrastructure-level flags
  • Feature flags cannot be used for authorization or data integrity enforcement

Trade-offs

  • Slightly more upfront discipline when adding flags
  • Remote tools may accumulate unused flags without impact
  • Feature flag evaluation occurs per request rather than globally cached

These trade-offs were accepted to prioritize safety, clarity, and long-term maintainability.

Notes

  • Feature flags are resolved in two phases depending on context availability:

    • Anonymous (pre-auth)
    • Authenticated (post-auth)
  • Cookies are used as a read-only source of derived context after middleware validation

  • GrowthBook misconfiguration or outage results in safe fallback to defaults

  • Deleting a flag from the registry immediately removes it from the platform, regardless of remote state

  • This architecture intentionally mirrors other platform patterns (e.g. UploadEngine, Notification intent → side-effects)