Xircuit Blog

Produkt-Updates, Entwickler-Logs und Neuigkeiten aus der Entwicklung von Xircuit.

Funktionen zur Laufzeit schalten: datenbankgestützte Feature-Flags cover image

Funktionen zur Laufzeit schalten: datenbankgestützte Feature-Flags


Funktionen zur Laufzeit schalten: datenbankgestützte Feature-Flags

Eine Reihe von Schaltern auf einem Bedienfeld Foto: Museums Victoria (BY 4.0), via Openverse

Es gibt einen Moment, den jeder kennt, der ernsthaft Software betreibt: Eine neue Funktion ist ausgerollt, alles sah in der Testumgebung gut aus, und dann meldet die Produktion, dass irgendetwas nicht stimmt. In diesem Moment zählt nur eine Frage: Wie schnell bekomme ich das wieder aus? Wenn die Antwort "ein neues Deployment, in zwanzig Minuten" lautet, ist das für ein Gesundheitsprodukt schlicht zu langsam.

Diese Woche geht es deshalb um etwas, das nach außen unsichtbar ist und trotzdem eine der wichtigsten Sicherheitsvorkehrungen in Xircuit darstellt: ein Feature-Flag-System, mit dem sich Funktionen zur Laufzeit ein- und ausschalten lassen, ohne dass ein einziges Deployment nötig ist. Ich erkläre, warum wir es gebaut haben, wie es technisch funktioniert und welche Rolle es beim vorsichtigen Ausrollen neuer Integrationen spielt.

Warum ein Deployment als Notbremse nicht reicht

Der klassische Weg, eine Funktion abzuschalten, ist ein Konfigurationswert in der appsettings.json, kombiniert mit einem Neustart. Das funktioniert, ist aber langsam und grob. Ein Deployment berührt den gesamten Dienst, dauert seine Zeit und will gut überlegt sein. Als Notbremse taugt es nicht, denn eine Notbremse muss man ziehen können, während der Zug fährt.

Wir wollten die Entscheidung, ob eine Funktion aktiv ist, aus dem Build herauslösen und in den laufenden Betrieb verlagern. Ein Flag sollte sich umlegen lassen wie ein physischer Schalter auf einem Bedienpult: sofort, sichtbar und ohne dass dafür jemand eine Pipeline anstoßen muss. Das ist kein Luxus, sondern eine Frage der Betriebssicherheit — gerade dann, wenn im Hintergrund Dienste laufen, die kontinuierlich fremde Systeme abfragen.

Die Datenbank als Wahrheit, die Konfiguration als Netz

Der Kern der Umsetzung ist eine bewusste Zweiteilung. Die Feature-Flags liegen in der Datenbank und lassen sich dort zur Laufzeit umschalten. Die statische Konfiguration aus den appsettings bleibt als Fallback bestehen. Das klingt zunächst nach doppelter Buchführung, hat aber einen konkreten Grund.

Fragt der Code, ob ein Flag aktiv ist, schaut das System zuerst in die Datenbank. Existiert dort ein Eintrag, gewinnt er. Fehlt er — etwa weil ein Flag ganz neu ist oder die Tabelle beim ersten Start noch nicht befüllt wurde — greift der konfigurierte Standardwert. So gibt es immer eine definierte Antwort, auch wenn die Datenbank einmal nicht erreichbar sein sollte oder ein Flag schlicht vergessen wurde. Die Datenbank ist die Quelle der Wahrheit für das, was gerade gilt; die Konfiguration ist das Netz, das darunter gespannt ist.

Praktisch bedeutet das auch, dass ein Flag zwei Leben hat. Es wird mit einem sicheren Standard im Code geboren und kann später im laufenden Betrieb übersteuert werden, ohne dass dieser Standard je verlorengeht. Setzt man den Datenbankeintrag zurück, fällt das Verhalten wieder auf die Konfiguration zurück — ein berechenbarer Ausgangszustand, auf den man sich verlassen kann.

Sichtbar und nachvollziehbar: die Verwaltungsseite

Ein Schalter, den nur ein Entwickler über ein SQL-Statement kennt, ist keine Notbremse, sondern eine Falle. Deshalb gehört zu diesem System eine eigene Verwaltungsseite unter /platform/feature-flags. Dort sind alle Flags aufgelistet, mit ihrem aktuellen Zustand, und lassen sich direkt umlegen.

Das macht zwei Dinge auf einmal. Zum einen wird das Schalten sichtbar: Man muss nicht raten, welche Funktionen gerade aktiv sind, sondern sieht es auf einen Blick. Zum anderen wird es auditierbar. Wer etwas verändert, hinterlässt eine Spur, und in einem Umfeld, in dem Gesundheitsdaten verarbeitet werden, ist diese Nachvollziehbarkeit kein nettes Extra, sondern Pflicht. Eine Funktion abzuschalten ist eine betriebliche Entscheidung, und solche Entscheidungen sollen dokumentiert sein, nicht in einer Kommandozeile verschwinden.

Ein Einstellungs-Bildschirm Foto: Tim Sullivan · StockSnap (CC0 1.0), via Openverse

Worker, die in Sekunden stillhalten

Der interessanteste Teil betrifft die Hintergrund-Worker. Xircuit betreibt eine Reihe von Diensten, die abseits jeder Nutzerinteraktion arbeiten — sie synchronisieren Daten, fragen externe Schnittstellen ab und verarbeiten, was hereinkommt. Genau solche Dienste möchte man im Zweifel schnell stilllegen können, etwa wenn eine angebundene Integration Fehler wirft oder ein Anbieter sein API drosselt.

Deshalb prüfen die Worker die Feature-Flags regelmäßig und pausieren auf Wunsch in höchstens dreißig Sekunden. Ein Worker läuft nicht als starre Endlosschleife, sondern fragt zwischen seinen Durchläufen, ob er überhaupt noch arbeiten soll. Legt jemand über die Verwaltungsseite das entsprechende Flag um, hält der Dienst beim nächsten Prüfintervall an, ohne abzustürzen und ohne dass Arbeit halb erledigt liegen bleibt. Er schläft, bis das Flag wieder freigegeben wird.

Diese dreißig Sekunden sind ein bewusster Kompromiss. Man könnte die Worker auch bei jeder einzelnen Operation nachschauen lassen, aber das erzeugte unnötige Last auf der Datenbank. Ein kurzes, festes Prüfintervall ist schnell genug, um im Ernstfall zu reagieren, und sparsam genug, um im Normalbetrieb nicht aufzufallen.

Neue Funktionen kommen erst einmal ausgeschaltet

Feature-Flags sind bei uns nicht nur eine Notbremse, sondern auch die Standard-Art, riskante Dinge auszuliefern. Neue, heikle Funktionen werden hinter einem Off-Flag in die Produktion gebracht und erst nach einer Verifikation aktiviert. Der Code liegt dann bereits auf den Servern, ist aber schlicht noch nicht scharf geschaltet.

Das entkoppelt zwei Vorgänge, die sonst gefährlich verschmelzen: das Ausliefern von Code und das Aktivieren von Verhalten. Wir können eine Integration ruhig deployen, sie in der echten Umgebung mit echten Abhängigkeiten prüfen und sie erst dann für Nutzer freigeben, wenn wir sicher sind, dass sie sich korrekt verhält. Geht dabei etwas schief, ist der Rückweg trivial — das Flag geht zurück auf Aus, und der Zustand ist wieder der, der vor der Freigabe galt. Ein solches "noch nicht verifiziert, deshalb hinter einem Flag" ist im Dev-Log eine ehrliche und häufige Aussage, und genau dafür ist der Mechanismus gedacht.

Die Grundlage für gestaffelte Rollouts

Über die einzelne Ein-Aus-Entscheidung hinaus sind die Flags auch das Fundament für etwas Größeres: gestaffelte Rollouts über die sieben Branchen hinweg, die Xircuit bedient. Nicht jede Neuerung muss überall gleichzeitig scharf werden. Eine Funktion kann zuerst in einem Bereich aktiviert, dort beobachtet und dann Schritt für Schritt auf die übrigen ausgeweitet werden.

So wird aus einem binären Schalter ein Werkzeug für kontrolliertes Wachstum. Statt jede Änderung als großen Sprung für alle auszurollen, lässt sie sich in überschaubaren Etappen einführen, bei denen jede Stufe die nächste absichert. Das reduziert das Risiko jeder einzelnen Freigabe und gibt uns die Ruhe, Dinge sorgfältig zu beobachten, bevor sie in die Breite gehen. Der Aufwand für ein solches System zahlt sich genau an den Tagen aus, an denen sonst Hektik ausbrechen würde.

Was kommt als Nächstes?

Nächste Woche: die erste Gesundheitsintegration — kontinuierliche Glukosemessung mit dem FreeStyle Libre 3 und ein Schlüsselring für Verschlüsselung.


Kommentare

Noch keine Kommentare. Teilen Sie als Erste(r) Ihre Gedanken!

Kommentar hinterlassen