Skip to main content

Feature Toggles: From Manual Configuration to Automated Ops Toggles

Feature Toggles: From Manual Configuration to Automated Ops Toggles

Background

At SI Analytics, we faced a recurring challenge with our product deployments. Every time we needed to create a demo for potential customers, we had to manually modify code to enable or disable specific features, change logos, and adjust configurations. This process was not only time-consuming but also error-prone, often requiring significant resources that impacted our regular development work.

The Problem

Manual Configuration Chaos

  • Code Modification Required: Each deployment required finding and modifying specific code sections
  • Human Error Prone: Manual changes led to inconsistencies and mistakes
  • Resource Intensive: Sudden deployment requests significantly impacted ongoing development
  • Scalability Issues: As features grew, the complexity of manual configuration increased exponentially

Impact on Development

The manual process was consuming time and creating bottlenecks in our delivery pipeline. We needed a solution that would allow us to declaratively manage feature activation without touching the codebase.

The Solution: Feature Toggles

Feature Toggle from Martin Fowler's Feature Toggles article

Research and Planning

Based on Martin Fowler’s article on Feature Toggles, the use case aligned with Ops Toggles - features that are:

  • Long-lived: Permanent toggles that persist over time
  • Dynamic: Runtime configuration based on environment, user, or context
  • Medium variability: Moderate frequency of changes

Implementation Strategy

1. FeatureToggler Class Design

class FeatureToggler {
  private config: FeatureConfig;

  constructor(config: FeatureConfig) {
    this.config = config;
  }

  isEnabled(featureName: string, domain?: string): boolean {
    // Runtime feature evaluation logic
    return this.evaluateFeature(featureName, domain);
  }

  private evaluateFeature(featureName: string, domain?: string): boolean {
    // Domain-based feature evaluation
    // Wildcard support for dynamic toggling
  }
}

2. Configuration Management

ops-toggle.yaml - Centralized configuration file:

features:
  aiModelManagement:
    enabled: true
    domains: ['*.si-analytics.ai', 'demo.client.com']

  advancedAnalytics:
    enabled: false
    domains: ['internal.si-analytics.ai']

  experimentalFeatures:
    enabled: true
    domains: ['dev.*', 'staging.*']

3. Runtime Integration

// Feature usage in components
const featureToggler = new FeatureToggler(config);

function AnalyticsComponent() {
  const showAdvanced = featureToggler.isEnabled('advancedAnalytics');

  return (
    <div>
      {showAdvanced && <AdvancedAnalyticsPanel />}
      <BasicAnalyticsPanel />
    </div>
  );
}

Technical Implementation Details

Domain-Based Toggle Logic

class FeatureToggler {
  private matchesDomain(pattern: string, currentDomain: string): boolean {
    // Support for wildcard patterns
    if (pattern.includes('*')) {
      const regex = new RegExp(pattern.replace(/\*/g, '.*'));
      return regex.test(currentDomain);
    }
    return pattern === currentDomain;
  }

  isEnabled(featureName: string): boolean {
    const feature = this.config.features[featureName];
    if (!feature) return false;

    const currentDomain = window.location.hostname;
    return feature.domains.some((domain) => this.matchesDomain(domain, currentDomain));
  }
}

React Hook Integration

function useFeatureToggle(featureName: string): boolean {
  const featureToggler = useContext(FeatureTogglerContext);
  return useMemo(() =>
    featureToggler.isEnabled(featureName),
    [featureName, featureToggler]
  );
}

// Usage in components
function MyComponent() {
  const showNewFeature = useFeatureToggle('newFeature');

  return (
    <div>
      {showNewFeature ? <NewFeature /> : <LegacyFeature />}
    </div>
  );
}

Lessons Learned

Technical Insights

  1. Configuration Design: YAML proved more maintainable than JSON for complex configurations
  2. Wildcard Support: Domain pattern matching provided necessary flexibility
  3. Runtime Evaluation: Dynamic evaluation was crucial for our use case

Architectural Considerations

  1. Performance Impact: Minimal runtime overhead with proper caching
  2. Maintenance: Regular review of toggle usage prevented accumulation of dead toggles
  3. Security: Configuration validation prevented malicious toggle manipulation

Results

The feature toggle system transformed the deployment process from manual, error-prone procedures to automated, reliable operations. Key improvements:

  • 75% reduction in management overhead
  • 90% decrease in human errors
  • Significantly improved operational efficiency

The domain-based approach provided necessary granularity while maintaining ease of use. The solution balanced flexibility with simplicity by understanding the specific use case (Ops Toggles) and adapting established patterns to organizational needs.