Feature Flags

Lesezeit: 7 Minuten

Feature Flags, auch unter anderen Bezeichnungen wie etwa Feature Toggles bekannt, sind Software-Schalter, die Code aktivieren oder deaktivieren.

Ich habe Feature Flags in der Kategorie Architektur untergebracht, da ein Entschluss zur Verwendung von Feature Flags sich durch die gesamte Architektur ziehen und eine bedeutsame Entscheidung in der Entwicklung einer Software darstellen kann. Gleichzeitig ist der Einsatz aber eng an Methodiken wie Trunk Based Development und die Durchführung von Experimenten gekoppelt, so dass ich ihn auch hätte in dieser Kategorie veröffentlichen können. Über einfache Entwurfsmuster gehen Feature Flags meiner Meinung nach hinaus, weil die Intention hier viel mehr im Vordergrund steht als die programmatische Umsetzung.

Intention

Es gibt verschiedene Anwendungsfälle für Feature Flags. Die aus meiner Sicht wesentlichsten sind der Einsatz im Rahmen von Trunk Based Development und die Durchführung von A/B-Tests.

Große Änderungen können hinter Feature Flags versteckt und damit frühzeitig in Produktion gebracht werden. Da sie keinen Effekt im produktiven Betrieb haben, solange das entsprechende Feature Flag deaktiviert ist, können Sie dabei unvollständig oder auch fehlerhaft bleiben. Für Trunk Based Development ist dies essentiell, da hier nur auf einem einzelnen Entwicklungszweig, dem sogenannten Trunk, gearbeitet wird. Aber auch beim Einsatz von Feature Branches können Feature Flags verwendet werden, um diese kurzlebig zu halten und dadurch weniger Merge-Konflikte zu haben. Martin Fowler nennt diese Anwendung von Feature Flags auch Release Toggles.

A/B-Tests bezeichnen die Evaluierung von Änderungen: Wie wirkt es sich zum Beispiel auf das Kaufverhalten aus, wenn der Artikeltext in einem Webshop nicht mehr in schwarzer Schriftfarbe, sondern in grüner dargestellt wird, oder der Warenkorb-Button links statt rechts platziert wird? Feature Flags ermöglichen es, beide Varianten zur Laufzeit in der gleichen Software abzubilden. Bei dieser Art von Feature Flags spricht Martin Fowler von Experiment Toggles.

Es gibt viele weitere Einsatzmöglichkeiten von Feature Flags. Martin Fowler erwähnt etwa Ops Toggles für administrative Funktionen und Permission Toggles für rollenbezogene Funktionen. Weitere vorstellbare Szenarien sind der Einsatz von Feature Flags, um (Entwickler-)Tests in Produktion durchzuführen oder als Kill Switches / Circuit Breaker.

Umsetzung

Ein Feature Flag ist nichts weiter als eine Bedingung in einer Fallunterscheidung:

if (featureIsEnabled) {
    useNewLogic()
} else {
    usePreviousLogic()
}

Features können als Teil der Konfiguration aktiviert oder deaktiviert werden. Die Konfiguration kann sich in einer lokalen Textdatei, einem externen Konfigurationsdienst, einer Datenbanktabelle oder sonstwo befinden. Anstelle einer einfachen Fallunterscheidung im Code können auch Entwurfsmuster wie Dependency Injection verwendet werden.

Im Falle von Release Toggles kann die Konfiguration ein fester Bestandteil des Artefaktes sein. In anderen Fällen möchte man die Konfiguration zur Laufzeit ändern können, oder andere Kriterien heranziehen, wie den Benutzer, seine Rollen, oder technische Merkmale wie gezielt gesetzte HTTP-Header.

Feature Flags können kurz- oder langlebig sein. Release Toggles sollten nur solange vorhanden sein, wie sich eine Änderung in Entwicklung befindet. Experiment Toggles sind nur für die Dauer des Experimentes relevant. Ops Toggles können hingegen permanent sein.

Feature Flags vs. Konfiguration/Parameter

Ich tue mich schwer damit, Ops Toggles und Permission Toggles als Feature Flags zu bezeichnen. Jede Implementierung einer Access Control List (ACL) könnte man damit als eine Sammlung von Feature Flags (Permission Toggles) auffassen. Jeder parametrisierter Aufruf eines Kommandozeilenwerkzeugs würde die Anwendung von Feature Flags (Ops Toggles) darstellen. Wenn man den Begriff so weit fasst, wird er zu beliebig um sinnvoll über Vor- und Nachteile, Fallstricke und Best Practices zu diskutieren.

Feature Flags haben für mich einen temporären Charakter und dienen dazu, Änderungen zu verstecken oder im Rahmen von Canary Releases oder A/B-Tests nur einem Teil der Endanwender anzubieten.

Zusätzliche Komplexität

Feature Flags stellen eine technische Schuld dar. Wer immer weiter neue Feature Flags einführt, sie aber nicht mehr aus dem Code ausbaut, hat irgendwann ein Problem. Je mehr Feature Flags sich zur gleichen Zeit in der Codebase befinden, desto komplizierter wird die Software. Alle möglichen Kombinationen von Feature-Flag-Schaltungen müssen bei der Weiterentwicklung der Software berücksichtigt und getestet werden, damit man nicht in unvorhergesehene Situationen läuft. Im Falle von Fehlern und Betriebsstörungen ist zu evaluieren, welche Feature Flags im Kontext des Problems relevant sein könnten und ob diese ein- oder ausgeschaltet waren. Feature Flags bedeuten also zusätzliche Aufwände in der Planung, der Integration, dem Rückbau und Analysen im Betrieb.

Übersichtlichkeit

Wer von Feature Flags intensiv Gebrauch macht, sollte Maßnahmen ergreifen, um den Überblick nicht zu verlieren. Folgende Informationen würde ich, pro Feature Flag, mindestens festhalten:

  • Ist das Feature Flag an- oder ausgeschaltet?
  • Wann wurde es in der Vergangenheit an- und ausgeschaltet?
  • Unter welchen Umständen wird es ggf. eingeschaltet? (z.B. für bestimmte Benutzergruppen, für jeden x-ten Aufruf etc.)
  • Wie oft wird es evaluiert / kommt es zum Tragen?
  • Wie groß ist die Auswirkung? Wie viel Code wird hinter dem Feature Flag versteckt?
  • Lassen sich Erfolg/Misserfolg messen oder bewerten?
  • Wann wird es wieder entfernt? Wer ist dafür zuständig?

Fazit

Ich finde Feature Flags in ihren Funktionen als Release Toggles und Experiment Toggles interessant. Beim Einsatz sollte man sich der zukünftigen Komplexität bewusst sein und Feature Flags sparsam und über möglichst kurze Zeiträume einsetzen. Ich ziehe Feature Flags gegenüber langlebigen Branches vor, an erster Stelle steht für mich aber der Versuch, eine große Änderung in viele kleine runterzubrechen, die unabhängig voneinander deployed werden können. Wird zum Beispiel eine Entität um weitere Pflichtfelder ergänzt, so muss sich dies nicht von Anfang an durch das ganze System ziehen. Im ersten Schritt können die neuen Felder einen Default-Wert erhalten, der sich nicht ändern lässt. Im nächsten Schritt kann dieser Wert änderbar gemacht werden. Erst im letzten Schritt, wenn die neuen Felder im Backend vollends unterstützt werden, kann das Feld in der UI eingebaut und die Default-Funktionalität zurückgebaut werden. Viele große Änderungen lassen sich so runterbrechen, ohne dass von langlebigen Branches oder Feature Flags Gebrauch gemacht werden muss.

Für Experimente finde ich Feature Flags grundsätzlich sinnvoll und sehe auch nicht viele gute Alternativen. Viele Teams, die Experimente einsetzen, werden dabei Feature Flags verwenden, wenn vielleicht in einigen Fällen auch unwissentlich.

- Martin Fowler über Feature Flags