Skip to main content

Feature Flags

Flo uses database-backed feature flags to control functionality at runtime. Flags can be toggled by admins without redeployment.

Flag Catalog​

Flags are grouped by area. Default is the value seeded on a fresh install (SeederService / EF migrations). A dash means the flag row is not created until an operator (or the CLI) sets it.

Authentication & Users​

FlagControlsDefault
enable_loginPassword login. Turning it off locks everyone out.ON
enable_registrationPublic registration (password, OTP, social). Seeded by the AddEnableRegistrationFeatureFlag migration.ON
enable_email_senderSending of transactional emails (activation, OTP, booking notifications).OFF
enable_google_loginGoogle social login (FLO). Seeded by the AddSocialLogin migration.OFF
enable_apple_loginApple social login (FLO). Seeded by the AddSocialLogin migration.OFF
enable_user_managementUser administration panel.ON
enable_professionalsStaff/professional management.ON

Booking & Services​

FlagControlsDefault
enable_bookingsBooking/scheduling system.OFF
allow_admin_overbookingAdmins may book users beyond schedule capacity.OFF
enable_capacity_guardCapacity conflict detection, scheduled capacity changes, overbooking controls and excess-user tracking.ON
enable_closure_managementStudio closure/holiday management.OFF
enable_services_managementService/activity management.OFF

Content & Bounded Contexts​

FlagControlsDefault
enable_dynamic_entitiesDynamic entity management (SchemaGen) master switch.OFF
enable_galleryMedia gallery feature.OFF
enable_public_formsDynamic public forms, R2 attachments and their request archive.OFF
enable_content_historyVersion snapshots of dynamic content (history, preview, restore, per-version delete).OFF
enable_strapi_syncSynchronization with Strapi CMS for dynamic content.OFF
enable_blogsLegacy Strapi-backed blog section.OFF
enable_native_blogNative blog CMS (articles, categories, authors, comments) and its public API.OFF
enable_immobiliimmobili (real estate) bounded context.OFF
enable_catalogoProduct catalog bounded context.OFF
enable_website_statesLocalized, date-based website state content and its editor.OFF
enable_whitelabelDB-backed branding UI (theme, brand-meta, login branding).OFF
enable_multilanguageConfiguring more than one content language per tenant.OFF
enable_sidebar_v2Sidebar V2 navigation layout (server-driven menu).ON

Communication​

FlagControlsDefault
enable_communicationCommunication module master switch: contacts, newsletters, campaign sending (formerly enable_newsletter).OFF
newsletter-manualCommunication > Messages: Editor and Library tabs (manual composition).ON
newsletter-autoCommunication > Messages: Automations tab (send settings, schedule, template preview).ON

Subscriptions, Invoicing & Payments​

FlagControlsDefault
enable_subscriptionsStudio subscription plans, client entitlements and self-service check-in.OFF
enable_einvoicingItalian electronic invoicing (SDI) bounded context via the external gateway.OFF
enable_online_paymentsOnline payment checkout for bookable activities.OFF
enable_financeFinance sidebar section (payments, refunds, collections/reports).OFF
enable_organization_managementOrganization management section in the admin dashboard.OFF

Analytics​

FlagControlsDefault
enable_analyticsBusiness analytics dashboard for admins.OFF
enable_web_analyticsClient-facing GA4/GSC web analytics dashboard for admins and pros.OFF
enable_external_web_analyticsHome card with external Google Search Console / GA4 links for clients tracked outside Flo.OFF

Media​

FlagControlsDefault
enable_media_optimizationServer-side FFmpeg optimization pipeline (variants, re-encode, original replacement).—
enable_cf_image_resizingCloudflare edge resizing: backend rewrites CDN URLs to /cdn-cgi/image/.... Requires R2 storage.—

See Media Storage for the full pipeline.

System (hidden)​

Flags whose key starts with _system_ are excluded from the admin feature-flags list (AdminService filters them out) and are managed only through dedicated endpoints or the CLI. Mutating them through the admin save endpoint is rejected.

FlagControlsDefault
_system_subscriptions_cutoverMarks the RespiraStudio subscriptions cutover as committed. When ON, enable_subscriptions is force-enabled and immutable.—
_system_lock_dynamic_content_structureLocks gallery structure: create/delete/rename are rejected for everyone, content editing stays available. Toggled via the SuperAdmin galleries endpoint or CLI.—
_system_audit_retention_daysAudit-log retention. The day count lives in the flag's Description (default 730, clamped 30–3650); managed via the audit retention endpoints.ON

Defaults, Exclusions & Dependencies​

  • Seeded ON: enable_login, enable_registration, enable_user_management, enable_professionals, enable_capacity_guard, enable_sidebar_v2, newsletter-manual, newsletter-auto, _system_audit_retention_days.
  • Seeded OFF: every other visible flag listed above.
  • Not seeded: enable_media_optimization, enable_cf_image_resizing, _system_subscriptions_cutover, _system_lock_dynamic_content_structure. A missing row evaluates to OFF (FeatureFlagsHelper.IsFeatureEnabled returns false when the row does not exist).
  • Mutually exclusive group: [enable_native_blog, enable_blogs]. At most one stays on: enabling one turns the other off; when both are enabled in the same save the first listed (enable_native_blog) wins.
  • Dependency: enable_online_payments requires enable_bookings and enable_einvoicing. The admin save is rejected otherwise (errors.payment.featureDependency).
  • Cutover lock: once _system_subscriptions_cutover is ON, enable_subscriptions cannot be turned off and its value is treated as ON regardless of the stored row.
  • CLI safety: flo config flags toggle refuses enable_email_sender and enable_login; use the declarative flo config flags set <id> <flag> on|off.

How It Works​

Backend​

Flags are stored in the FeatureFlag table and checked via FeatureFlagsHelper:

if (!await FeatureFlagsHelper.IsFeatureEnabled(context, FeatureFlagsHelper.BOOKINGS_KEY))
return NotFound();

Reads are cached in memory for 60 seconds (FeatureFlagsHelper.CacheDuration); writes invalidate the affected key, and Maintenance > feature-flags/invalidate / the admin bulk save invalidate all tracked keys. A flag changed in the database takes effect within 60 seconds.

Frontend​

Flags are fetched before authentication during APP_INITIALIZER from GET /api/v1/admin/feature-flags (anonymous, no-store). Routes are protected using FeatureFlagGuard:

{
path: 'prenotazioni',
canActivate: [FeatureFlagGuard],
data: { ff: 'enable_bookings' }
}

The sidebar dynamically shows/hides menu items based on active flags.

Admin Panel & CLI​

  • Admin panel: Settings > Feature Flags. Saving posts the whole list and is Admin-gated; the service enforces exclusivity, payment dependency and protected flags.
  • CLI: flo config flags show <id>, flo config flags toggle <id> <flag>, flo config flags set <id> <flag> on|off.

Adding a New Feature Flag​

  1. Database: add the flag name via migration or let SetFeatureEnabled auto-create it on first write.
  2. Backend: check the flag in controllers/services using FeatureFlagsHelper.
  3. Frontend: add FeatureFlagGuard to routes and conditionally render UI elements; keep featureflags.helper.ts constants in sync.
  4. Sidebar: update SidebarConfigService.GetMenuDefinition() so the server-driven menu matches.

Bounded Context Flags​

For the dynamic entity system, bounded contexts have their own enable flag:

  • enable_dynamic_entities must be ON (master switch)
  • enable_<boundedContext> must also be ON (e.g. enable_immobili for real estate, enable_catalogo for the catalog)

Both must be active for a bounded context's entities to load at runtime.