Skip to main content

Feature Flags Strategy - Hybrid Approach

Comprehensive strategy for managing feature flags using both custom API and PostHog.

Last Updated: February 2, 2026


Overview

We use a hybrid approach for feature flags:

  1. Custom API System - For admin-controlled platform features and provider-controlled premium features
  2. PostHog - For gradual percentage-based rollouts and A/B testing
  3. Unified Admin UI - Manage all flags from one place
  4. User Self-Service - Providers control their own premium features

Feature Flag Categories

1. Admin-Controlled Features (Custom API)

System: Custom API (juniro-api/src/config/feature-flags.ts)

Characteristics:

  • Admin-controlled (Juniro admins enable/disable platform-wide)
  • Can be provider-controlled (premium features)
  • Requires database persistence
  • Needs admin override capability
  • Platform-wide or provider-level settings

Admin-Controlled (Platform-Wide):

  • REVIEWS_ENABLED - Admin enables/disables reviews feature platform-wide
  • ATTENDANCE_ENABLED - Admin enables/disables attendance tracking platform-wide
  • ASSIGNMENTS_ENABLED - Admin enables/disables assignments feature platform-wide
  • AI_SEARCH_ENABLED - Admin enables/disables AI search platform-wide
  • BOOKING_FLOW_ENABLED - Admin enables/disables booking flow platform-wide (master switch)
  • PAYMENT_ENABLED - Admin enables/disables payment collection platform-wide (default: ON)
  • STAFF_PORTAL_ENABLED - Admin enables/disables staff portal platform-wide

Provider-Controlled (Premium Features):

  • PAYMENT_ENABLED - Provider can enable/disable online payments for their account (freemium)
  • MESSAGING_ENABLED - Provider can enable/disable messaging (premium)
  • AI_RECOMMENDATIONS_ENABLED - Provider can enable/disable AI recommendations (premium)
  • Future: ADVANCED_ANALYTICS_ENABLED, CUSTOM_BRANDING_ENABLED, etc.

Storage:

  • Global flags: FeatureFlag table (admin-controlled platform-wide features)
  • Provider flags: ProviderAccount.featureFlags JSON column (provider-controlled premium features)
  • User flags: User.featureFlags JSON column (future)

API Endpoints:

  • GET /config/feature-flags - Get flags for current user/provider (includes global + provider flags)
  • GET /me/provider/feature-flags - Get my provider's flags (provider-controlled only)
  • PATCH /me/provider/feature-flags - Update my provider's flags (provider-controlled only)
  • GET /config/feature-flags/:providerId - Admin: Get provider flags
  • PATCH /config/feature-flags/:providerId - Admin: Override provider flags
  • GET /config/feature-flags/global - Admin: Get all global flags (future)
  • PATCH /config/feature-flags/global/:key - Admin: Update global flag (future)

Naming Convention: UPPER_SNAKE_CASE with _ENABLED suffix (e.g., REVIEWS_ENABLED, PAYMENT_ENABLED)


2. Rollout/A/B Testing Features (PostHog)

System: PostHog Feature Flags

Characteristics:

  • Platform-controlled (admin only)
  • Gradual rollout (10% → 50% → 100%)
  • A/B testing variants
  • Analytics and conversion tracking
  • Temporary (removed after stable)
  • Percentage-based user targeting

Examples:

  • admin-v2 - Gradual rollout of new admin UI (10% → 50% → 100%)
  • parent-headline-variant - A/B test landing page headlines
  • parent-cta-variant - A/B test CTA buttons
  • booking-flow-v2 - A/B test new booking flow vs old
  • checkout-variant-a - A/B test checkout experience

Note: Platform features like reviews, attendance, assignments, ai-search, booking-flow are controlled via Custom API (admin on/off toggle), not PostHog (gradual rollout).

Storage:

  • PostHog dashboard
  • Evaluated client-side and server-side via PostHog SDK

API Integration:

  • Frontend: useFeatureFlag('booking-flow') from posthog-js/react
  • Backend: posthog.isFeatureEnabled('booking-flow', userId)

Naming Convention: kebab-case with consistent patterns:

  • Feature rollouts: {feature-name} (e.g., booking-flow, reviews, staff-portal, attendance, assignments)
  • A/B tests: {page}-{element}-variant (e.g., parent-headline-variant, parent-cta-variant)
  • Regional: {feature}-{region} (e.g., payments-stripe, payments-razorpay)
  • Versions: {feature}-v{number} (e.g., admin-v2)

Standardization Rule:

  • DO: Use descriptive feature names (reviews, attendance, assignments)
  • DON'T: Add -enabled suffix (redundant - flags are toggles by nature)
  • DON'T: Use underscores (use hyphens for kebab-case consistency)

3. Regional Features (Hybrid)

System: Custom API + PostHog (depending on use case)

Characteristics:

  • Region-specific features
  • Can be user-controlled or platform-controlled

Examples:

  • payments-stripe - US payment provider (PostHog - platform-controlled)
  • payments-razorpay - India payment provider (PostHog - platform-controlled)
  • whatsapp-notifications - India messaging (Custom API - provider-controlled)

Decision Rule:

  • If user can enable/disable → Custom API
  • If platform controls rollout → PostHog

Booking & Payment Flag Hierarchy

The booking and payment features use a three-tier hierarchy:

Hierarchy Diagram

User clicks "Book Now"


┌────────────────────────────────────┐
│ Check BOOKING_FLOW_ENABLED (Global)│ Admin controlled
│ Default: ON (core feature) │
└────────────────────────────────────┘

│ OFF → Show "Booking coming soon" (rare, maintenance mode)

▼ ON
┌────────────────────────────────────┐
│ Proceed to Booking Flow │
│ (Select session, child, etc.) │
└────────────────────────────────────┘


┌────────────────────────────────────┐
│ Check PAYMENT_ENABLED (Global) │ Admin controlled
│ Default: ON │
└────────────────────────────────────┘

│ OFF → Skip payment for ALL bookings
│ Providers don't see payment option in settings
│ Show "Payment will be collected offline"
│ Complete booking as "pending_payment"

▼ ON
┌────────────────────────────────────┐
│ Check PAYMENT_ENABLED (Provider) │ Provider controlled (opt-in)
│ Default: OFF (freemium feature) │ Only visible if Global=ON
└────────────────────────────────────┘

│ OFF → Skip payment for this provider
│ Show "Payment will be collected offline"
│ Complete booking as "pending_payment"

▼ ON
┌────────────────────────────────────┐
│ Show Payment Form │
│ (Stripe US / Razorpay India) │
└────────────────────────────────────┘


┌────────────────────────────────────┐
│ Complete Booking │
│ Status: "confirmed" │
└────────────────────────────────────┘

Use Cases

BOOKING_FLOW (G)PAYMENT (G)PAYMENT (P)ResultProvider Settings
❌ OFFN/AN/A"Booking coming soon"N/A
✅ ON❌ OFFN/ABook without payment (all)Payment option hidden
✅ ON✅ ON❌ OFFBook without payment (this provider)Payment option visible, provider opted out
✅ ON✅ ON✅ ONFull booking with paymentPayment option visible, provider opted in

Key Points

  • BOOKING_FLOW_ENABLED (Global, Default: ON) = Core feature, always available unless maintenance
  • PAYMENT_ENABLED (Global, Default: ON) = Master switch for payment feature
    • If ON: Providers can see and control their payment settings
    • If OFF: Payment option hidden from all providers, all bookings are offline
  • PAYMENT_ENABLED (Provider, Default: OFF) = Provider opt-in for online payment (freemium)
    • Only relevant when Global is ON

They work hierarchically: Global flags are checked first, then provider flags.


Flag Classification Matrix

Flag NameSystemControlled ByScopeDefaultNaming
Admin-Controlled (Platform-Wide)
BOOKING_FLOW_ENABLEDCustom APIAdminGlobalONUPPER_SNAKE_CASE
PAYMENT_ENABLEDCustom APIAdminGlobalONUPPER_SNAKE_CASE
REVIEWS_ENABLEDCustom APIAdminGlobalOFFUPPER_SNAKE_CASE
ATTENDANCE_ENABLEDCustom APIAdminGlobalOFFUPPER_SNAKE_CASE
ASSIGNMENTS_ENABLEDCustom APIAdminGlobalOFFUPPER_SNAKE_CASE
AI_SEARCH_ENABLEDCustom APIAdminGlobalOFFUPPER_SNAKE_CASE
STAFF_PORTAL_ENABLEDCustom APIAdminGlobalOFFUPPER_SNAKE_CASE
Provider-Controlled (Premium)
PAYMENT_ENABLEDCustom APIProviderProviderOFFUPPER_SNAKE_CASE
MESSAGING_ENABLEDCustom APIProviderPremiumUPPER_SNAKE_CASE
AI_RECOMMENDATIONS_ENABLEDCustom APIProviderPremiumUPPER_SNAKE_CASE
PostHog (Gradual Rollout/A/B Testing)
admin-v2PostHogAdminRolloutkebab-case
payments-stripePostHogAdminRegionalkebab-case
payments-razorpayPostHogAdminRegionalkebab-case
parent-headline-variantPostHogAdminA/B Testkebab-case
parent-cta-variantPostHogAdminA/B Testkebab-case
booking-flow-v2PostHogAdminA/B Testkebab-case

Admin Feature Flags UI

Requirements

Location: Admin Portal → System → Feature Flags

Sections:

  1. Business Features (Custom API)

    • List all provider-level flags
    • Show provider count per flag (how many have it enabled)
    • Allow admin to:
      • View all providers and their flag status
      • Override provider flags (with confirmation)
      • Set default values for new providers
      • View flag usage analytics
  2. Rollout Features (PostHog)

    • List all PostHog flags
    • Show current rollout percentage
    • Allow admin to:
      • View PostHog dashboard (link)
      • See flag status (enabled/disabled)
      • See rollout percentage
      • See A/B test variants and distribution
      • View conversion analytics
  3. Unified View

    • Combined list of all flags (both systems)
    • Filter by system (Custom API / PostHog)
    • Filter by type (Premium / Rollout / A/B Test / Regional)
    • Search by flag name
    • Export flag configuration

Implementation:

  • Wire existing FeatureFlagsManagement component
  • Integrate PostHog API for PostHog flags
  • Integrate Custom API for business flags
  • Show unified dashboard

Provider Feature Flags UI

Requirements

Location: Provider Portal → Settings → Features

Sections:

  1. Premium Features

    • List all provider-controllable flags
    • Show current status (enabled/disabled)
    • Show feature description and benefits
    • Allow provider to:
      • Enable/disable features
      • See pricing (if applicable)
      • View feature documentation
    • Show admin override indicator (if admin has overridden)
  2. Platform Features (Read-Only)

    • Show platform-controlled flags (PostHog)
    • Show status (enabled/disabled for their account)
    • Show rollout percentage (if applicable)
    • Informational only (no controls)

Implementation:

  • Create SettingsFeatures component
  • Wire to GET /me/provider/feature-flags
  • Wire to PATCH /me/provider/feature-flags
  • Show PostHog flags (read-only) via PostHog SDK

Parent Feature Flags UI (Future)

Requirements

Location: Parent Portal → Settings → Features

Sections:

  1. Premium Features (Future)

    • List parent-controllable flags
    • Similar to provider UI
    • Examples: ADVANCED_CALENDAR_ENABLED, FAMILY_SHARING_ENABLED
  2. Platform Features (Read-Only)

    • Show platform-controlled flags (PostHog)
    • Informational only

Implementation:

  • Future: Add User.featureFlags column
  • Future: Add GET /me/feature-flags endpoint
  • Future: Create parent settings UI

Implementation Plan

Phase 1: Custom API System (✅ COMPLETED)

  • Custom feature flags API
  • Provider self-service endpoints
  • Admin override endpoints
  • Global flag endpoints (GET/PATCH /config/feature-flags/global)
  • Database schema (FeatureFlag table for global flags)

Phase 2: PostHog Integration (TODO)

  • Install PostHog SDK in all frontend apps
  • Install PostHog Node SDK in API
  • Create PostHog config module
  • Add PostHog flags to booking flow
  • Add PostHog flags to reviews
  • Add PostHog flags to staff portal
  • Document PostHog flag creation process

Phase 3: Admin UI (TODO)

  • Wire FeatureFlagsManagement component
  • Integrate Custom API for business flags
  • Integrate PostHog API for rollout flags
  • Create unified dashboard
  • Add provider search/filter
  • Add analytics views

Phase 4: Provider UI (TODO)

  • Create SettingsFeatures component
  • Wire to Custom API endpoints
  • Show PostHog flags (read-only)
  • Add feature descriptions
  • Add confirmation dialogs

Phase 5: Documentation (TODO)

  • Update roadmap matrix with hybrid approach
  • Document flag classification process
  • Create admin guide for managing flags
  • Create provider guide for premium features

Decision Framework

When to use Custom API:

  • ✅ Admin needs to enable/disable platform-wide (on/off toggle)
  • ✅ User (provider/parent) can control it (premium features)
  • ✅ Needs database persistence
  • ✅ Provider-level or platform-level setting
  • ✅ Needs admin override capability
  • ✅ Examples: Reviews, Attendance, Assignments, AI Search, Booking Flow, Staff Portal

When to use PostHog:

  • ✅ Gradual percentage-based rollout (10% → 50% → 100%)
  • ✅ A/B testing with variants
  • ✅ Temporary flag (will be removed after stable)
  • ✅ Needs analytics and conversion tracking
  • ✅ User targeting by percentage
  • ✅ Examples: Admin v2 rollout, A/B test variants, regional payment providers

When to use both:

  • ✅ Regional features (PostHog for platform control, Custom API if user-controlled)
  • ✅ Complex features with multiple aspects

Flag Lifecycle

Custom API Flags (Business Features)

┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│ Create │ ──► │ Available │ ──► │ Deprecated│
│ Flag │ │ (Active) │ │ (Keep) │
└─────────────┘ └─────────────┘ └─────────────┘
│ │ │
▼ ▼ ▼
Add to DB Users enable/ Keep for backward
Add to API disable compatibility

Lifecycle: Flags persist indefinitely (premium features don't expire)

PostHog Flags (Rollout Features)

┌─────────────┐     ┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│ Create │ ──► │ Rollout │ ──► │ 100% │ ──► │ Remove │
│ Flag │ │ Gradual │ │ Stable │ │ Flag │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
│ │ │ │
▼ ▼ ▼ ▼
Feature in 10% → 50% Monitor for Delete flag
development → 100% 2 weeks from code

Lifecycle: Flags removed after 2 weeks at 100% with no issues


Migration Notes

Existing Custom API Flags

  • MESSAGING_ENABLED (Provider) - Keep in Custom API (provider-controlled premium)
  • PAYMENT_ENABLED (Provider) - Keep in Custom API (provider-controlled freemium)
  • AI_RECOMMENDATIONS_ENABLED (Provider) - Keep in Custom API (provider-controlled premium)

New Flags to Add (Custom API - Admin-Controlled)

  • REVIEWS_ENABLED (Global) - Admin enables/disables reviews platform-wide
  • ATTENDANCE_ENABLED (Global) - Admin enables/disables attendance platform-wide
  • ASSIGNMENTS_ENABLED (Global) - Admin enables/disables assignments platform-wide
  • AI_SEARCH_ENABLED (Global) - Admin enables/disables AI search platform-wide
  • BOOKING_FLOW_ENABLED (Global) - Admin enables/disables booking flow platform-wide
  • PAYMENT_ENABLED (Global) - Admin enables/disables payment collection platform-wide (default: ON)
  • STAFF_PORTAL_ENABLED (Global) - Admin enables/disables staff portal platform-wide

PostHog Flags (Gradual Rollout/A/B Testing)

  • admin-v2 - Gradual rollout of new admin UI
  • parent-headline-variant - A/B test landing page
  • parent-cta-variant - A/B test CTA buttons
  • payments-stripe - Regional payment provider (US)
  • payments-razorpay - Regional payment provider (India)


Last Updated: February 2, 2026