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
| Flag | Controls | Default |
|---|---|---|
enable_login | Password login. Turning it off locks everyone out. | ON |
enable_registration | Public registration (password, OTP, social). Seeded by the AddEnableRegistrationFeatureFlag migration. | ON |
enable_email_sender | Sending of transactional emails (activation, OTP, booking notifications). | OFF |
enable_google_login | Google social login (FLO). Seeded by the AddSocialLogin migration. | OFF |
enable_apple_login | Apple social login (FLO). Seeded by the AddSocialLogin migration. | OFF |
enable_user_management | User administration panel. | ON |
enable_professionals | Staff/professional management. | ON |
Booking & Services
| Flag | Controls | Default |
|---|---|---|
enable_bookings | Booking/scheduling system. | OFF |
allow_admin_overbooking | Admins may book users beyond schedule capacity. | OFF |
enable_capacity_guard | Capacity conflict detection, scheduled capacity changes, overbooking controls and excess-user tracking. | ON |
enable_closure_management | Studio closure/holiday management. | OFF |
enable_services_management | Service/activity management. | OFF |
Content & Bounded Contexts
| Flag | Controls | Default |
|---|---|---|
enable_dynamic_entities | Dynamic entity management (SchemaGen) master switch. | OFF |
enable_gallery | Media gallery feature. | OFF |
enable_public_forms | Dynamic public forms, R2 attachments and their request archive. | OFF |
enable_content_history | Version snapshots of dynamic content (history, preview, restore, per-version delete). | OFF |
enable_strapi_sync | Synchronization with Strapi CMS for dynamic content. | OFF |
enable_blogs | Legacy Strapi-backed blog section. | OFF |
enable_native_blog | Native blog CMS (articles, categories, authors, comments) and its public API. | OFF |
enable_immobili | immobili (real estate) bounded context. | OFF |
enable_catalogo | Product catalog bounded context. | OFF |
enable_website_states | Localized, date-based website state content and its editor. | OFF |
enable_whitelabel | DB-backed branding UI (theme, brand-meta, login branding). | OFF |
enable_multilanguage | Configuring more than one content language per tenant. | OFF |
enable_sidebar_v2 | Sidebar V2 navigation layout (server-driven menu). | ON |
Communication
| Flag | Controls | Default |
|---|---|---|
enable_communication | Communication module master switch: contacts, newsletters, campaign sending (formerly enable_newsletter). | OFF |
newsletter-manual | Communication > Messages: Editor and Library tabs (manual composition). | ON |
newsletter-auto | Communication > Messages: Automations tab (send settings, schedule, template preview). | ON |
Subscriptions, Invoicing & Payments
| Flag | Controls | Default |
|---|---|---|
enable_subscriptions | Studio subscription plans, client entitlements and self-service check-in. | OFF |
enable_einvoicing | Italian electronic invoicing (SDI) bounded context via the external gateway. | OFF |
enable_online_payments | Online payment checkout for bookable activities. | OFF |
enable_finance | Finance sidebar section (payments, refunds, collections/reports). | OFF |
enable_organization_management | Organization management section in the admin dashboard. | OFF |
Analytics
| Flag | Controls | Default |
|---|---|---|
enable_analytics | Business analytics dashboard for admins. | OFF |
enable_web_analytics | Client-facing GA4/GSC web analytics dashboard for admins and pros. | OFF |
enable_external_web_analytics | Home card with external Google Search Console / GA4 links for clients tracked outside Flo. | OFF |
Media
| Flag | Controls | Default |
|---|---|---|
enable_media_optimization | Server-side FFmpeg optimization pipeline (variants, re-encode, original replacement). | — |
enable_cf_image_resizing | Cloudflare 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.
| Flag | Controls | Default |
|---|---|---|
_system_subscriptions_cutover | Marks the RespiraStudio subscriptions cutover as committed. When ON, enable_subscriptions is force-enabled and immutable. | — |
_system_lock_dynamic_content_structure | Locks gallery structure: create/delete/rename are rejected for everyone, content editing stays available. Toggled via the SuperAdmin galleries endpoint or CLI. | — |
_system_audit_retention_days | Audit-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.IsFeatureEnabledreturns 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_paymentsrequiresenable_bookingsandenable_einvoicing. The admin save is rejected otherwise (errors.payment.featureDependency). - Cutover lock: once
_system_subscriptions_cutoveris ON,enable_subscriptionscannot be turned off and its value is treated as ON regardless of the stored row. - CLI safety:
flo config flags togglerefusesenable_email_senderandenable_login; use the declarativeflo 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
- Database: add the flag name via migration or let
SetFeatureEnabledauto-create it on first write. - Backend: check the flag in controllers/services using
FeatureFlagsHelper. - Frontend: add
FeatureFlagGuardto routes and conditionally render UI elements; keepfeatureflags.helper.tsconstants in sync. - 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_entitiesmust be ON (master switch)enable_<boundedContext>must also be ON (e.g.enable_immobilifor real estate,enable_catalogofor the catalog)
Both must be active for a bounded context's entities to load at runtime.