Android Coden
Android 4 min lesen

Feature Flags: Sicher ausliefern und Risiken kontrollieren

Feature Flags steuern, welche Funktionen zur Laufzeit aktiv sind. So lieferst du sicher aus und kannst Fehler sofort abschalten.

Eine neue Funktion ist fertig entwickelt, aber du weißt noch nicht, ob sie unter echten Bedingungen stabil bleibt. Feature Flags lösen dieses Problem: Du lieferst den Code aus, lässt die Funktion aber zunächst deaktiviert. Wann und für wen sie sichtbar wird, steuerst du unabhängig vom Release-Zyklus. Das ist kein Nischentrick, sondern gelebte Produktionspraxis bei Teams jeder Größe – von Indie-Entwicklern bis hin zu Google selbst.

Was ist das?

Ein Feature Flag – auch Feature Toggle oder Feature Switch genannt – ist ein bedingter Zweig im Code, der bestimmt, ob eine Funktion aktiv ist oder nicht. Der Schalter kann zur Compile-Zeit, zur Laufzeit oder sogar aus der Ferne über einen Konfigurationsdienst umgelegt werden.

Im einfachsten Fall ist ein Flag eine Boolean-Konstante in deiner Codebasis. In professionellen Setups liefert ein Backend-Dienst – etwa Firebase Remote Config oder ein selbst gehosteter Konfigurationsserver – den Wert in Echtzeit. Die App fragt diesen Wert beim Start oder bei bestimmten Nutzeraktionen ab und verzweigt daraufhin in den aktivierten oder deaktivierten Pfad.

Feature Flags passen nahtlos in die moderne Android-Architektur. Die offiziellen Architektur-Empfehlungen von Google fordern eine klare Schichtentrennung: Die Entscheidung, ob ein Feature angezeigt wird, gehört in die Domain- oder UI-Schicht, nicht in eine global genutzte Utility-Klasse. Nur so bleibt der Flag testbar, injizierbar und austauschbar.

Wie funktioniert es?

Das Grundprinzip ist eine einfache Fallunterscheidung: Wenn der Flag-Wert true ergibt, zeige oder führe die neue Funktion aus; andernfalls greife auf das bisherige Verhalten zurück. Die eigentliche Stärke entsteht durch die Herkunft dieses Werts.

Lokale Flags werden als Konstanten oder über BuildConfig zur Compile-Zeit gesetzt:

object FeatureFlags {
    val NEW_CHECKOUT_FLOW = BuildConfig.ENABLE_NEW_CHECKOUT
}

Das eignet sich gut für Debug-Builds und interne Varianten, lässt sich aber nach dem Release nicht mehr ändern.

Remote Flags kommen von einem Dienst wie Firebase Remote Config. Beim App-Start rufst du die aktuellen Werte ab und aktivierst sie lokal:

class RemoteFeatureFlags(
    private val remoteConfig: FirebaseRemoteConfig
) {
    suspend fun fetchAndActivate() {
        remoteConfig.fetchAndActivate().await()
    }

    fun isNewCheckoutEnabled(): Boolean =
        remoteConfig.getBoolean("new_checkout_flow")
}

Damit die Klasse in Tests austauschbar bleibt, definierst du ein Interface und injizierst die Implementierung per Hilt oder einem anderen DI-Framework. Im Test verwendest du dann eine Fake-Implementierung, die hart true oder false zurückgibt.

Zusammenspiel mit Google Play: Play bietet gestaffelte Rollouts (10 % → 25 % → 50 % → 100 %), die steuern, welche Nutzer ein Update erhalten. Feature Flags arbeiten eine Ebene darunter: Du kannst ein Feature nur für Beta-Tester oder eine bestimmte Region aktivieren, unabhängig davon, welche App-Version die Nutzer installiert haben. Beide Mechanismen ergänzen sich – Play-Tracks regeln die Verbreitung des Codes, Flags regeln die Sichtbarkeit der Funktion.

In der Praxis

Stell dir vor, du baust einen neuen Checkout-Flow in einer Shopping-App. Du mergst den Code in den Hauptzweig und lieferst ihn per Play-Release aus – aber der Flag ist deaktiviert. Nur interne Tester sehen die neue Oberfläche. Nachdem das Monitoring eine Woche lang grüne Crash-Rate- und Performance-Metriken zeigt, aktivierst du den Flag für 5 % der Nutzer. Läuft alles stabil, weiter auf 20 %, 50 % und schließlich 100 %.

@Composable
fun CheckoutScreen(
    featureFlags: FeatureFlags,
    viewModel: CheckoutViewModel = hiltViewModel()
) {
    if (featureFlags.isNewCheckoutEnabled()) {
        NewCheckoutContent(viewModel)
    } else {
        LegacyCheckoutContent(viewModel)
    }
}

Stolperfalle: Flag-Schulden

Viele Teams aktivieren ein Feature und vergessen, den alten Code-Pfad und den Flag selbst zu entfernen. Nach einigen Monaten enthält die Codebasis Dutzende toter Zweige, und niemand weiß mehr, welche Flags noch abgefragt werden. Lege deshalb zu jedem Flag ein Ablaufdatum fest – entweder als Kommentar im Code oder als Ticket im Backlog – und behandle die Entfernung als reguläre Entwicklungsaufgabe.

Stolperfalle: Fehlende Tests für beide Zustände

Ein Feature Flag verdoppelt effektiv die Anzahl der Codepfade. Schreibe Unit-Tests für den aktivierten und den deaktivierten Zustand, sonst übersehen deine Tests Regressionen im jeweils anderen Zweig. Mit einer Fake-Implementierung des Flag-Interfaces ist das in wenigen Zeilen erledigt:

class FakeFeatureFlags(private val newCheckout: Boolean) : FeatureFlags {
    override fun isNewCheckoutEnabled() = newCheckout
}

Fazit

Feature Flags sind das Sicherheitsnetz zwischen Continuous Delivery und einem stabilen Nutzererlebnis. Sie geben dir die Kontrolle, Risiken zu dosieren: Ein Problem lässt sich in Sekunden abschalten, ohne ein neues APK zu veröffentlichen. Überprüfe deine aktuelle Codebasis – gibt es Bereiche, die du schon längst schrittweise ausrollen wolltest? Wähle einen davon, implementiere einen Remote Flag hinter einem Interface, schreibe Tests für beide Zustände und verfolge die Metriken nach der Aktivierung. Den Wert dieser Investition erkennst du spätestens beim ersten Vorfall, bei dem du froh bist, einen Notschalter zu haben.

Quellen (5)
Redaktion

Geschrieben von

Redaktion

Das Redaktionsteam recherchiert und schreibt Artikel zu aktuellen Themen rund um Tech, Lifestyle und Ratgeber.