Feature Toggles
Funktionen per Schalter freigeben
Die Idee und ihr Nutzen
Ein Team einer Versicherung baut eine neue Schadenmeldung, die Fotos vom Schaden automatisch auswertet. Der Programmcode dafür wird schon auf die Server gebracht, während Kunden noch die bisherige Schadenmeldung sehen. Ein Schalter legt fest, wer die neue Funktion nutzt: zuerst Mitarbeiter, dann ein kleiner Teil der Kunden, schließlich alle. Der Schalter ist eine Einstellung wie neue_schadenmeldung = aus, die das Programm bei jedem Aufruf abfragt und die das Team während des Betriebs umstellen kann. Hat die neue Funktion Fehler, schaltet das Team sie in Minuten wieder aus, ohne eine neue Programmversion einzuspielen. Solche Schalter heißen Feature Toggles, auf Deutsch Funktionsschalter.
Wie funktioniert es?
Kunden melden ihre Schäden über das Schadenportal der Versicherung. Das Team des Schadenportals liefert jeden Tag eine neue Programmversion auf die Server aus. Den Code der neuen Fotoauswertung liefert das Team schon mit, während der Schalter neue_schadenmeldung auf „aus“ steht. Den Zustand des Schalters verwaltet der Schalterdienst, ein eigenes Programm, in dem das Team den Zustand jederzeit ändern kann. Das Schadenportal läuft auf mehreren Servern, auf jedem ein Exemplar desselben Programms. Alle Exemplare fragen denselben Schalterdienst ab, deshalb wirkt eine Umstellung des Schalters auf allen Servern zugleich. Nach vier Wochen ist die Funktion fertig, und das Team schaltet sie für die 50 Mitarbeiter der Schadenabteilung ein. Diese Mitarbeiter können beurteilen, ob die Fotoauswertung Schäden richtig einordnet, und erproben die Funktion eine Woche lang im Echtbetrieb. Danach schaltet das Team die Funktion zusätzlich für fünf Prozent der Kunden ein, die fest zugeordnet werden und deshalb bei jedem Besuch dieselbe Variante sehen. Fünf Prozent der Kunden melden so viele Schäden, dass ein Fehler innerhalb weniger Tage auffällt, und ein Fehler trifft nur einen kleinen Teil der Kunden. Bei jedem Aufruf fragt das Schadenportal den Schalter im Schalterdienst ab. Meldet ein Kunde aus diesen fünf Prozent einen Schaden, erhält das Schadenportal „an“ und zeigt dem Kunden die neue Fotoauswertung. Nach drei Tagen fällt auf, dass die Fotoauswertung bei Aufnahmen im Dunkeln Schäden falsch einordnet. Das Team stellt den Schalter in zwei Minuten auf „aus“, ohne eine neue Programmversion einzuspielen. Beim nächsten Aufruf fragt das Schadenportal erneut, erhält „aus“, und alle Kunden sehen wieder die bisherige Schadenmeldung. Nach der Korrektur schaltet das Team die Funktion erneut schrittweise ein, bis alle Kunden sie nutzen. Einen Monat später entfernt das Team den Schalter und den alten Code der bisherigen Schadenmeldung.
Am Schadenportal arbeiten mehrere Entwickler gleichzeitig. Ihre Änderungen führen sie in einem gemeinsamen Hauptzweig zusammen (englisch main branch). Der Hauptzweig ist die Fassung des Programmcodes in der Versionsverwaltung, aus der jede neue Programmversion gebaut wird; die Versionsverwaltung ist ein Programm wie Git, das alle Fassungen des Codes aufbewahrt. Der Schalter trennt die Entscheidung, wann der Code auf die Server kommt, von der Entscheidung, wann Nutzer die Funktion sehen. Dafür wirken drei Teile zusammen:
- Im Code des Schadenportals steht eine Abfrage: „Wenn der Schalter
neue_schadenmeldungfür diesen Nutzer an ist, zeige den neuen Ablauf, sonst den bisherigen.“ - Der Zustand des Schalters legt fest, für wen die Funktion an ist: für alle, für niemanden oder für die Nutzer, auf die eine Regel zutrifft. Mögliche Regeln sind „nur Mitarbeiter“, „fünf Prozent der Kunden“ oder „eine Region“.
- Der Zustand steht nicht im Code, sondern im Schalterdienst. Statt eines Schalterdienstes genügt auch eine Einstellung, die sich ebenso jederzeit ändern lässt, etwa ein Eintrag in einer Konfigurationsdatei, die das Schadenportal regelmäßig neu einliest.
Schalter dienen verschiedenen Zwecken und bleiben unterschiedlich lange im Code:
- Freigabeschalter verbergen unfertige Funktionen für Tage bis Wochen. Der Schalter
neue_schadenmeldungist ein Freigabeschalter. - Versuchsschalter dienen dazu, zwei Varianten einige Wochen lang zu vergleichen, etwa zwei Fassungen der Schadenmeldung, um zu sehen, mit welcher Fassung Kunden ihre Meldung häufiger abschließen.
- Betriebsschalter schalten bei Überlast eine Funktion ab, die die Server stark belastet, etwa die Fotoauswertung, und bleiben dauerhaft.
- Berechtigungsschalter geben Funktionen nur für bestimmte Kunden frei, etwa nur für Firmenkunden, und bleiben ebenfalls dauerhaft.
Ein Schalter blendet Code nur ein oder aus. Fehlerhaften Code macht er nicht richtig. Eine ausgeschaltete Funktion ist außerdem nur so lange unerreichbar, wie jeder Programmteil, der die Funktion aufruft, den Schalter abfragt. Ist der Schalterdienst nicht erreichbar, muss das Schadenportal einen festgelegten Standardwert verwenden, meist „aus“.
Feature Toggles: neue Fotoauswertung ohne neue Version abschalten
Wann ist es sinnvoll und wann nicht?
Feature Toggles lohnen sich
- Teams liefern häufig aus und wollen unfertigen Code trotzdem im gemeinsamen Hauptzweig halten. Halten die Entwickler den neuen Code wochenlang getrennt vom Hauptzweig, haben andere Entwickler inzwischen viele Stellen im Hauptzweig geändert. Beim späteren Zusammenführen müssen die Entwickler dann jeden Widerspruch zwischen ihrem Code und diesen Änderungen von Hand auflösen, und dabei entstehen leicht Fehler. Führen sie den neuen Code dagegen früh ohne Schalter zusammen, sehen Kunden eine halbfertige Funktion.
- Eine Funktion soll schrittweise freigegeben werden, zuerst für Mitarbeiter und dann für einen Teil der Kunden. Ohne Schalter erreicht die neue Funktion mit der Auslieferung sofort alle Kunden. Den Fehler bei Aufnahmen im Dunkeln bemerken so nur die fünf Prozent der Kunden.
- Eine riskante Funktion soll sich innerhalb von Minuten abschalten lassen. Eine neue Programmversion zu bauen und auszuliefern dauert dafür zu lange. Mit dem Schalter ändert das Team nur den Zustand des Schalters.
- Zwei Varianten sollen eine Zeit lang verglichen werden. Mit einem Versuchsschalter sieht die eine Hälfte der Kunden die eine Fassung der Schadenmeldung, die andere Hälfte die andere, und beide Fassungen laufen in derselben Programmversion. Ohne Versuchsschalter müsste das Team zwei Programmversionen nebeneinander betreiben und die Kunden auf beide verteilen.
Feature Toggles sind nicht das Richtige
- Unterschiedliche Varianten für verschiedene Kunden sollen auf Dauer bestehen bleiben. Ein Freigabeschalter wie
neue_schadenmeldungist dafür nicht gedacht, denn das Team entfernt ihn nach der Einführung zusammen mit dem alten Code. Dann legt das Team die Varianten als dauerhafte Berechtigung je Kunde an, etwa als Berechtigungsschalter „nur Firmenkunden“ oder als Angabe in den Kundendaten. Ein Freigabeschalter, der entfernt werden soll und doch bleiben muss, entsteht so nicht. - Die Änderung betrifft den Aufbau der Datenbank. Ein Schalter kann eine neue Tabelle oder Spalte nicht ausblenden, denn alter und neuer Code greifen auf dieselbe Datenbank zu. Dann gestaltet das Team die neue Tabelle oder Spalte so, dass alter und neuer Code damit arbeiten, und legt sie vor dem Einschalten an. So kann das Team den Schalter ein- und ausschalten, ohne die Datenbank jedes Mal umzubauen.
- Die Änderung ist klein und in wenigen Stunden fertig. Der Code liegt dann nur wenige Stunden getrennt vom Hauptzweig, und einen Fehler darin behebt das Team mit der nächsten täglichen Auslieferung. Dann führt das Team die Änderung ohne Schalter zusammen und liefert sie aus. Die Abfrage im Code, der Eintrag im Schalterdienst und das spätere Entfernen des Schalters entfallen.
- Nicht eine einzelne Funktion, sondern eine ganze neue Programmversion soll zuerst an wenigen Nutzern erprobt werden. Ein Schalter schaltet nur die Funktionen um, für die eine Abfrage im Code steht; alle übrigen Änderungen der neuen Programmversion erreichen mit der Auslieferung alle Nutzer zugleich. Dann liefert das Team die neue Programmversion als Canary Release zuerst auf einen kleinen Teil der Server aus. Jede Anfrage geht zuerst an einen Lastverteiler, ein Programm, das Anfragen auf die Server verteilt, und der Lastverteiler schickt nur einen kleinen Teil der Anfragen an diese Server. Abfragen im Code und ein Schalterdienst entfallen.
Nachteile und typische Fehler
Jeder Schalter verdoppelt die Zahl möglicher Programmzustände. Zehn frei kombinierbare Schalter ergeben rechnerisch 1.024 Kombinationen. Nicht alle kommen in der Praxis vor, aber die wichtigen muss das Team gezielt testen. Dazu gehören mindestens der Zustand, der im Echtbetrieb gilt, und der Zustand, auf den das Schadenportal zurückfällt. Der Schalterdienst ist ein zusätzliches Programm, das betrieben werden muss. Jeder Freigabeschalter verursacht außerdem Nacharbeit: Nach der Einführung müssen Schalter und alter Code wieder entfernt werden, damit die Entwickler nicht zwei Abläufe pflegen, von denen einer nie mehr genutzt wird.
Typische Fehler und woran man sie erkennt:
- Vergessener Schalter: Nach der vollständigen Einführung entfernt niemand den Schalter und den alten Code. Nach Jahren weiß niemand mehr, ob der alte Code noch gebraucht wird, und jede Änderung am Schadenportal muss beide Abläufe berücksichtigen. Erkennbar ist das an Schaltern, die seit Monaten für alle auf „an“ stehen.
- Falsch gesetzter Schalter: Jemand setzt einen Schalter im Schalterdienst versehentlich für alle auf „an“. Beim nächsten Aufruf erhält das Schadenportal „an“ und zeigt allen Kunden die unfertige Funktion. Erkennbar ist das an Kundenmeldungen zu einer Funktion, die offiziell noch nicht freigegeben ist.
- Wechselnde Zuordnung: Ob ein Kunde zu den fünf Prozent gehört, wird bei jedem Aufruf neu ausgelost, statt einmal fest zugeordnet zu werden. Derselbe Kunde sieht dann abwechselnd alte und neue Schadenmeldung. Erkennbar ist das an Kunden, die eine Meldung im neuen Ablauf beginnen und im alten wiederfinden.
- Kein Standardwert: Das Schadenportal fragt den Schalterdienst, erhält keine Antwort und hat keinen festgelegten Standardwert. Je nach Programmierung bricht die Seite ab oder zeigt die neue Funktion allen. Erkennbar ist das an Fehlern im Schadenportal, die mit Störungen des Schalterdienstes zusammenfallen.
- Ungetestete Kombination: Ein zweiter Schalter schaltet eine neue Fotoablage ein, die Fotos in einem anderen Format speichert, als die neue Fotoauswertung erwartet. Getestet hat das Team beide Funktionen nur einzeln. Bei Kunden, für die beide Schalter an sind, kann die Fotoauswertung die Fotos nicht lesen. Erkennbar ist das an Fehlern, die nur bei Kunden auftreten, für die beide Schalter an sind.
Weiterführend
Verwandte Ansätze
- Blue Green Deployment und Rolling Deployment: beschreiben, wie neue Versionen auf die Server kommen. Schalter trennen davon die Entscheidung, wann eine Funktion sichtbar wird.
- Configuration Server: ein zentraler Dienst für Einstellungen, der auch die Zustände der Schalter liefern kann.
- Graceful Degradation: beschreibt, wie ein System bei Überlast mit eingeschränktem Umfang weiterläuft. Betriebsschalter sind ein Mittel dafür, etwa ein Schalter, der bei Überlast die Fotoauswertung abschaltet.
Werkzeuge und Umsetzungen
- Unleash: Schalterdienst mit Regeln für Nutzergruppen und schrittweise Freigaben. Die Grundversion ist Open Source, weitere Funktionen gibt es in kostenpflichtigen Ausgaben.
- Flagsmith: Schalterdienst mit Bedienoberfläche und Regeln.
- flagd: Schalterdienst, der den offenen Standard OpenFeature für Funktionsschalter umsetzt.
- GrowthBook: Plattform für Schalter und Versuche mit Auswertung, welche Variante besser abschneidet.
Quellen
- Pete Hodgson: Feature Toggles (aka Feature Flags): ausführlicher Artikel auf martinfowler.com über Freigabe-, Versuchs-, Betriebs- und Berechtigungsschalter, ihre unterschiedliche Lebensdauer, das Testen von Schalterkombinationen und das Entfernen alter Schalter.
- Martin Fowler: Feature Flag: kurzer Grundlagentext, der Freigabeschalter als Mittel beschreibt, unfertigen Code im Hauptzweig zu halten, und betont, dass Freigabeschalter nach der Einführung wieder entfernt werden müssen.