Feature Flags im kleinen Team: Nützlich, aber nicht umsonst

Feature Flags entkoppeln Deployment und Release. Für kleine Teams lohnen sie sich, aber nur mit Aufräumregeln. Wann du sie brauchst und wann nicht.

DeploymentArchitekturTeamarbeit

Thema: DevOps & Hosting · Web-Entwicklung

Feature Flags im kleinen Team: Nützlich, aber nicht umsonst

Feature Flags lösen ein echtes Problem: Du kannst Code ausliefern, ohne ihn gleich für alle einzuschalten. Für kleine Teams reicht dafür meistens eine simple Tabelle oder Konfigurationsdatei statt einer SaaS-Plattform. Die wahren Kosten entstehen aber nicht beim Einbauen, sondern wenn niemand die Flags wieder entfernt.

Worum es eigentlich geht

Ohne Flags sind zwei Dinge fest miteinander verknüpft: das Deployment (Code landet auf dem Server) und das Release (Nutzer sehen die Funktion). Wenn das Feature halb fertig ist, darf es nicht deployed werden. Also lebt es in einem Branch, der wochenlang vom Hauptzweig wegdriftet, bis der Merge zur Qual wird.

Ein Flag trennt beides. Der Code geht in kleinen Schritten auf main und in Produktion, bleibt aber hinter einer Abfrage verborgen:

if (flags.isEnabled("neuer-checkout", { userId })) {
  return renderNewCheckout();
}
return renderLegacyCheckout();

Freigeschaltet wird später – erst für dich, dann für ein paar Testkunden, dann für alle. Und falls etwas schiefgeht, schaltest du zurück, ohne ein Rollback deployen zu müssen.

Nicht jedes Flag ist gleich

Ein Grund für die Verwirrung rund ums Thema: Unter „Feature Flag“ werden ganz unterschiedliche Dinge zusammengefasst. Pete Hodgson hat in seinem Artikel auf martinfowler.com eine Einteilung vorgeschlagen, die sich in der Praxis bewährt hat. Vereinfacht:

Diese Unterscheidung ist nicht akademisch. Sie entscheidet darüber, wann ein Flag gelöscht werden muss. Wer Release-Flags und Tarif-Freischaltungen im selben Topf verwaltet, weiß nach einem Jahr nicht mehr, welche 40 Einträge man gefahrlos entfernen kann.

Brauchst du eine Plattform?

Der Markt für Feature-Flag-Dienste ist groß. LaunchDarkly ist der bekannteste kommerzielle Anbieter, dazu kommen Open-Source-Projekte wie Unleash, Flagsmith und GrowthBook, die sich auch selbst hosten lassen. Mit OpenFeature gibt es inzwischen außerdem einen herstellerneutralen Standard für die Client-Schnittstelle, der ein späteres Wechseln erleichtern soll.

Für ein kleines Team ist die ehrliche Antwort trotzdem oft: noch nicht.

Wenn du eine Handvoll Release-Flags hast, reicht eine Tabelle in deiner bestehenden Datenbank:

CREATE TABLE feature_flags (
  key         text PRIMARY KEY,
  enabled     boolean NOT NULL DEFAULT false,
  allow_users text[]  NOT NULL DEFAULT '{}',
  created_at  timestamptz NOT NULL DEFAULT now(),
  owner       text NOT NULL,
  remove_by   date
);

Dazu eine kleine Funktion, die das Flag liest und kurz cached, und eine Admin-Seite oder notfalls ein SQL-Befehl zum Umschalten. Das ist in einem Nachmittag gebaut, kostet keine zusätzliche Abhängigkeit und keine Daten verlassen deinen Server – was bei Kundenprojekten mit Datenschutzanforderungen ein echtes Argument ist.

Eine Plattform lohnt sich, wenn einer dieser Punkte zutrifft:

Trifft nichts davon zu, baust du dir mit einer Plattform vor allem eine weitere externe Abhängigkeit ein.

Die Kosten, über die selten jemand spricht

Jedes Flag verdoppelt mindestens einen Codepfad. Zwei Flags, die sich berühren, ergeben vier mögliche Zustände. Theoretisch müsste deine Testsuite alle abdecken – praktisch testet sie meistens nur den, der gerade in Produktion aktiv ist.

Daraus entstehen die typischen Probleme:

Vergessene Flags. Das Feature ist seit Monaten für alle aktiv, aber der alte Pfad ist noch im Code. Niemand traut sich, ihn zu löschen, weil unklar ist, ob irgendwo noch jemand das Flag auf false hat.

Toter Code, der gewartet wird. Beim nächsten Refactoring passt jemand gewissenhaft auch den Legacy-Checkout an, der seit einem halben Jahr nicht mehr ausgeführt wird.

Falsche Sicherheit beim Zurückschalten. Der Notschalter funktioniert nur, wenn der alte Pfad noch mit dem aktuellen Datenmodell kompatibel ist. Nach einer Datenbankmigration ist er das oft nicht mehr. Ein Flag ersetzt keine durchdachte Migrationsstrategie.

Flags als Konfigurationsersatz. Irgendwann steuert ein „temporäres“ Flag, welcher Zahlungsanbieter verwendet wird. Dann ist es kein Flag mehr, sondern Konfiguration ohne Versionierung und Review.

Aufräumregeln, die funktionieren

Das Einzige, was gegen Flag-Wildwuchs hilft, sind Regeln, die du beim Anlegen festlegst – nicht beim Aufräumen.

  1. Jedes Release-Flag bekommt ein Ablaufdatum und eine verantwortliche Person. Deshalb die Spalten owner und remove_by in der Tabelle oben.
  2. Das Entfernen ist Teil der Aufgabe. Ein Feature gilt erst als erledigt, wenn das Flag und der alte Codepfad raus sind. Leg das Ticket dafür gleich beim Einbauen an.
  3. Eine Prüfung in der CI, die abgelaufene Flags meldet, ist schnell geschrieben und wirksamer als jede Erinnerung im Kalender.
  4. Flag-Namen müssen durchsuchbar sein. Keine dynamisch zusammengesetzten Keys, damit ein grep jede Verwendung findet.

Wann du ganz darauf verzichten solltest

Nicht jede Änderung braucht ein Flag. Kleine Anpassungen, die in einem Tag fertig sind, gehen einfach durch den normalen Review und ins Deployment. Ein Flag für jede Button-Farbe erzeugt nur Verwaltungsaufwand.

Und wenn du allein an einem Projekt arbeitest und ohnehin direkt auf main entwickelst, sind Flags vor allem für zwei Situationen interessant: größere Umbauten, die du schrittweise ausliefern willst, und Funktionen, die du erst mit einzelnen Kunden testen möchtest. Für alles andere ist ein sauberes, schnelles Deployment mit einfachem Rollback die bessere Investition.

Wie ihr Flags in euren Projekten verwaltet – Tabelle, Plattform oder gar nicht –, interessiert uns im Discord der Community. Gerade die Frage, wie man vergessene Flags wieder loswird, hat dort schon einige gute Ansätze hervorgebracht.