Flagsmith Feature Flags Configuration
This guide explains how to configure and use feature flags in the ERP-Unlocked platform using Flagsmith.
Overview
Section titled βOverviewβERP-Unlocked uses Flagsmith for feature flag management. This enables:
- Gradual rollouts: Roll out features to a percentage of users
- Targeting: Enable features for specific organizations, users, or segments
- A/B testing: Test different feature variants
- Kill switches: Quickly disable features in production
Architecture
Section titled βArchitectureβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ Flagsmith Server ββ (Self-hosted or Flagsmith Cloud) ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β βΌββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ @repo/feature-flags Package ββ βββ server.ts - Server-side SDK (SSR, API routes) ββ βββ client.ts - Client-side SDK (Browser) ββ βββ hooks.tsx - React hooks for components ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β βββββββββββββ΄ββββββββββββ βΌ βΌ ββββββββββββββββ ββββββββββββββββ β Webapp β β Python APIs β β (Astro/React)β β (via headers)β ββββββββββββββββ ββββββββββββββββEnvironment Variables
Section titled βEnvironment VariablesβRequired
Section titled βRequiredβ# Flagsmith environment key (server-side key)FLAGSMITH_ENVIRONMENT_KEY=ser.xxxxx
# Flagsmith API URL (self-hosted or cloud)FLAGSMITH_API_URL=https://flagsmith.yourdomain.com/api/v1Optional
Section titled βOptionalβ# Enable local evaluation (caches flags, reduces API calls)FLAGSMITH_LOCAL_EVALUATION=true
# Cache refresh interval in seconds (default: 60)FLAGSMITH_REFRESH_INTERVAL=60Using Feature Flags
Section titled βUsing Feature FlagsβIn Astro Pages (Server-Side)
Section titled βIn Astro Pages (Server-Side)β---import { getFeatureFlag } from '@repo/feature-flags';
// Check if feature is enabled for current userconst isNewDashboardEnabled = await getFeatureFlag('new_dashboard', { identifier: Astro.locals.user?.id, traits: { organizationId: Astro.locals.organization?.id, email: Astro.locals.user?.email, }});---
{isNewDashboardEnabled ? ( <NewDashboard />) : ( <LegacyDashboard />)}In API Routes
Section titled βIn API Routesβimport { getFeatureFlag } from '@repo/feature-flags';
export const GET: APIRoute = async ({ locals }) => { const useNewAlgorithm = await getFeatureFlag('new_matching_algorithm', { identifier: locals.user?.id, traits: { organizationId: locals.organization?.id, }, });
if (useNewAlgorithm) { // Use new implementation } else { // Use existing implementation }};In React Components
Section titled βIn React Componentsβimport { useFeatureFlag } from '@repo/feature-flags/hooks';
export function OrderEditor() { const showAdvancedOptions = useFeatureFlag('order_editor_advanced');
return ( <div> <BasicOptions /> {showAdvancedOptions && <AdvancedOptions />} </div> );}Using Feature Gates
Section titled βUsing Feature Gatesβimport { useFeatureGate } from '@repo/feature-flags/hooks';
export function FeaturePreview() { const { Gate } = useFeatureGate('beta_features');
return ( <Gate fallback={<UpgradeBanner />}> <BetaFeaturePanel /> </Gate> );}Current Feature Flags
Section titled βCurrent Feature Flagsβ| Flag Name | Description | Default |
|---|---|---|
email_enabled | Enable email processing for orders | false |
dagster_enabled | Enable Dagster-based data sync | false |
typesense_search | Use Typesense for product search | false |
new_order_editor | New React-based order editor | false |
matching_shipto_resolver_v1 | Outer gate for the CK ship-to customer resolver (Temporal worker). See rollout doc below. | false |
email_triage_trusted_sender_auth_required_v1 | Temporal pull path only (Gmail/Graph β not webapp/Cloudflare email intake). Requires a dmarc=pass + provider marker in Authentication-Results before a trusted-sender domain match skips email triage (CWE-290 hardening; shadow-logs when off). No-op unless email_triage_trusted_senders_v1 is also on. See docs/PR-2849-CodeRabbit-trusted-sender-auth-gap.md. | false |
email_triage_internal_sender_v1 | Temporal pull path only. Skips mail sent by the organizationβs own staff before content triage, so an org forwarding its own sales orders into its connected mailbox stops producing order rows. Matches the bare From address exactly (never by domain) against email_aliases rows with alias_type='user'. Evaluated per-connection, before the trusted-sender allowlist. Do not enable for any connection yet β the staff roster counts Ordermatic staff who join a customer org and never drops leavers; both blockers are tracked as P0 in TODOS.md. | false |
Segments
Section titled βSegmentsβFlagsmith segments allow targeting users based on traits:
| Segment | Targeting Rule |
|---|---|
internal_team | email CONTAINS @boonetek.com |
beta_users | betaEnabled = true |
enterprise_orgs | subscriptionTier = enterprise |
staging_environment | environment = staging |
Python Services Integration
Section titled βPython Services IntegrationβPython services (pdf-api, pdf-worker) receive feature flag values via HTTP headers from the webapp:
from app.utils.feature_flags import get_feature_flags
@router.post("/process")async def process_pdf( features: FeatureFlags = Depends(get_feature_flags),): if features.is_enabled("pdf_extraction_v2"): # Use new extraction pipeline passThe webapp passes flags via X-Feature-* headers when calling Python services.
Adding New Flags
Section titled βAdding New Flagsβ-
Create the flag in Flagsmith UI
- Go to your Flagsmith project
- Create a new feature flag with a descriptive name (snake_case)
- Set default state (enabled/disabled)
- Add any targeting rules or segments
-
Use the flag in code
const isEnabled = await getFeatureFlag('your_new_flag', identity); -
Update this documentation
- Add the flag to the βCurrent Feature Flagsβ table above
Best Practices
Section titled βBest Practicesβ- Use descriptive names:
order_processing_v2notflag1 - Default to disabled: New features should be off by default
- Remove stale flags: After 100% rollout, remove flag checks from code
- Document flags: Keep this guide updated with current flags
- Use segments: Target internal team first, then beta users, then gradual rollout
Troubleshooting
Section titled βTroubleshootingβFlags not updating
Section titled βFlags not updatingβ- Check
FLAGSMITH_REFRESH_INTERVALsetting - Verify
FLAGSMITH_API_URLis correct - Check Flagsmith server health
Flag always returns default value
Section titled βFlag always returns default valueβ- Verify
FLAGSMITH_ENVIRONMENT_KEYis correct - Check flag exists in Flagsmith for the correct environment
- Verify identity traits match targeting rules
Performance issues
Section titled βPerformance issuesβ- Enable local evaluation:
FLAGSMITH_LOCAL_EVALUATION=true - Increase refresh interval for stable flags
- Use caching for high-traffic routes
Related Documentation
Section titled βRelated Documentationβ- Flagsmith Integration Playbook - Implementation details
- Organization Settings Guide - Per-org configuration
- Deployment Guide - Environment setup