Hallo Welt
Hallo Welt
Original Lingva Deutsch
Übersetzung wird vorbereitet...
Dieser Vorgang kann bis zu 60 Sekunden dauern.
Diese Seite wird erstmalig übersetzt und dann für alle Besucher gespeichert.
0%
DE Zurück zu Deutsch
Übersetzung durch Lingva Translate

234 Dokumentationen verfügbar

Wissensdatenbank

Feature Flags Implementierung

Zuletzt aktualisiert: 20.01.2026 um 10:05 Uhr

Feature Flags: Kontrolliertes Ausrollen

Feature Flags ermöglichen sichere Deployments und graduelle Rollouts. Lernen Sie, wie Sie Features kontrolliert aktivieren.

Was sind Feature Flags?

// Ohne Feature Flag
function checkout() {
    processPayment();
}

// Mit Feature Flag
function checkout() {
    if (featureFlags.isEnabled('new_payment_flow')) {
        processNewPayment();
    } else {
        processPayment();
    }
}

// Vorteile:
// - Deployment ≠ Release
// - Schnelles Rollback (Flag aus)
// - A/B Testing
// - Canary Releases

Flag-Typen

Typ Beschreibung Lebensdauer
Release Flag Feature ein/ausschalten Kurz (nach Rollout löschen)
Experiment Flag A/B Tests Mittel (bis Entscheidung)
Ops Flag Circuit Breaker, Kill Switch Lang/permanent
Permission Flag Feature für User-Gruppen Lang/permanent

Einfache Implementierung

// featureFlags.js
class FeatureFlags {
    constructor() {
        this.flags = new Map();
    }

    // Flag definieren
    define(name, options = {}) {
        this.flags.set(name, {
            enabled: options.enabled ?? false,
            percentage: options.percentage ?? 100,
            users: options.users ?? [],
            groups: options.groups ?? []
        });
    }

    // Flag prüfen
    isEnabled(name, context = {}) {
        const flag = this.flags.get(name);
        if (!flag) return false;

        // Komplett deaktiviert
        if (!flag.enabled) return false;

        // Spezifische User
        if (flag.users.length && context.userId) {
            if (flag.users.includes(context.userId)) return true;
        }

        // User-Gruppen
        if (flag.groups.length && context.userGroup) {
            if (flag.groups.includes(context.userGroup)) return true;
        }

        // Prozentuale Ausrollung
        if (flag.percentage < 100 && context.userId) {
            const hash = this.hashString(name + context.userId);
            return (hash % 100) < flag.percentage;
        }

        return flag.enabled;
    }

    hashString(str) {
        let hash = 0;
        for (let i = 0; i < str.length; i++) {
            hash = ((hash << 5) - hash) + str.charCodeAt(i);
            hash |= 0;
        }
        return Math.abs(hash);
    }
}

// Verwendung
const flags = new FeatureFlags();

flags.define('new_checkout', {
    enabled: true,
    percentage: 10  // 10% der User
});

flags.define('beta_features', {
    enabled: true,
    groups: ['beta_testers', 'internal']
});

// In Code
if (flags.isEnabled('new_checkout', { userId: user.id })) {
    // Neuer Checkout
}

Konfiguration über Umgebung

// Config aus Environment
const featureConfig = {
    new_checkout: {
        enabled: process.env.FF_NEW_CHECKOUT === 'true',
        percentage: parseInt(process.env.FF_NEW_CHECKOUT_PERCENT) || 0
    },
    dark_mode: {
        enabled: process.env.FF_DARK_MODE === 'true'
    }
};

// JSON Config Datei
// features.json
{
    "new_checkout": {
        "enabled": true,
        "percentage": 25,
        "groups": ["beta"]
    },
    "experimental_search": {
        "enabled": true,
        "users": ["user_123", "user_456"]
    }
}

Feature Flag Service (LaunchDarkly-Style)

// Server
class FeatureFlagService {
    constructor(config) {
        this.flags = new Map(Object.entries(config));
        this.overrides = new Map();
    }

    evaluate(flagKey, context) {
        // Override prüfen
        const overrideKey = `${flagKey}:${context.userId}`;
        if (this.overrides.has(overrideKey)) {
            return this.overrides.get(overrideKey);
        }

        const flag = this.flags.get(flagKey);
        if (!flag) return { value: false, reason: 'FLAG_NOT_FOUND' };

        // Evaluierung
        if (!flag.enabled) {
            return { value: false, reason: 'DISABLED' };
        }

        // Targeting Rules
        for (const rule of flag.rules || []) {
            if (this.matchesRule(rule, context)) {
                return { value: rule.value, reason: 'RULE_MATCH' };
            }
        }

        // Percentage Rollout
        if (flag.percentage < 100) {
            const bucket = this.getBucket(flagKey, context.userId);
            if (bucket >= flag.percentage) {
                return { value: false, reason: 'PERCENTAGE_ROLLOUT' };
            }
        }

        return { value: true, reason: 'DEFAULT' };
    }

    // Override für Testing
    setOverride(flagKey, userId, value) {
        this.overrides.set(`${flagKey}:${userId}`, { value, reason: 'OVERRIDE' });
    }

    getBucket(flagKey, userId) {
        const hash = crypto.createHash('md5')
            .update(`${flagKey}:${userId}`)
            .digest('hex');
        return parseInt(hash.substring(0, 8), 16) % 100;
    }
}

React Integration

// FeatureFlagProvider.jsx
import { createContext, useContext } from 'react';

const FeatureFlagContext = createContext();

export function FeatureFlagProvider({ flags, children }) {
    const isEnabled = (flagName) => {
        return flags[flagName]?.enabled ?? false;
    };

    return (
        <FeatureFlagContext.Provider value={{ isEnabled, flags }}>
            {children}
        </FeatureFlagContext.Provider>
    );
}

export function useFeatureFlag(flagName) {
    const { isEnabled } = useContext(FeatureFlagContext);
    return isEnabled(flagName);
}

// Verwendung
function CheckoutButton() {
    const newCheckout = useFeatureFlag('new_checkout');

    if (newCheckout) {
        return <NewCheckoutButton />;
    }
    return <LegacyCheckoutButton />;
}

// Oder als Component
function FeatureFlag({ name, children, fallback = null }) {
    const enabled = useFeatureFlag(name);
    return enabled ? children : fallback;
}

<FeatureFlag name="new_dashboard" fallback={<OldDashboard />}>
    <NewDashboard />
</FeatureFlag>

Graduelle Rollouts

# Canary Release Plan
Tag 1:  1% der User  → Monitoring
Tag 2:  5% der User  → Monitoring
Tag 3:  25% der User → Monitoring
Tag 4:  50% der User → Monitoring
Tag 5:  100% aller User

# Bei Problemen: Sofort auf 0% zurück

Best Practices

✅ Do:
  • Flags nach Rollout entfernen (Tech Debt!)
  • Konsistente Naming-Convention
  • Dokumentieren wofür jeder Flag ist
  • Default immer "aus" (sicher)
❌ Don't:
  • Flags ewig behalten
  • Verschachtelte Flag-Logik
  • Flags in kritischen Pfaden ohne Fallback

Weitere Informationen