Kontrolliertes Ausrollen von Features ohne Release-Angst
Feature Flags trennen das Deployment von Code von der Aktivierung eines Features für Nutzer. In Vue-Apps entsteht daraus ein mächtiges Werkzeug für schrittweise Rollouts, A/B-Tests und schnelles Zurückschalten im Fehlerfall, sofern die Composable-Architektur, Typsicherheit und Aufräumdisziplin von Anfang an mitgedacht werden.
Inhaltsverzeichnis
- 1. Warum Feature Flags in Vue-Apps mehr sind als if-Bedingungen
- 2. Eine Composable-API für Feature Flags entwerfen
- 3. Typsicherheit: Flags nicht als beliebige Strings
- 4. Remote-Konfiguration statt Rebuild pro Flag-Änderung
- 5. Targeting: Rollout-Prozente und Nutzersegmente
- 6. A/B-Tests auf Basis von Feature Flags
- 7. Feature Flags in SSR- und Nuxt-Kontexten
- 8. Aufräumen: Flags entfernen, bevor sie zu Legacy werden
- 9. Feature-Flag-Ansätze im Vergleich
- 10. Zusammenfassung
- 11. FAQ
1. Warum Feature Flags in Vue-Apps mehr sind als if-Bedingungen
Ein Feature Flag in einer Vue-App ist im Kern eine bedingte Anweisung, die entscheidet, ob ein Codepfad für einen bestimmten Nutzer aktiv ist. Der eigentliche Wert entsteht aber erst durch die Entkopplung von Deployment und Aktivierung: Code für ein neues Feature kann in Produktion deployt werden, ohne dass ein einziger Nutzer es sieht, bis das Flag explizit umgelegt wird. Das reduziert das Risiko großer Releases erheblich, weil Deployment und Feature-Aktivierung zu zwei getrennten, unabhängig steuerbaren Ereignissen werden.
Viele Vue-Teams beginnen mit naiven if-Bedingungen, die direkt auf eine Umgebungsvariable prüfen. Das funktioniert für einzelne, kurzlebige Flags, skaliert aber nicht: Ohne zentrale Verwaltung entstehen verstreute Prüfungen über Dutzende Komponenten, unklare Namenskonventionen und Flags, die niemand mehr sicher entfernen kann, weil ihre Abhängigkeiten nicht mehr überschaubar sind. Ein durchdachtes Feature-Flag-System für Vue-Apps löst genau diese organisatorischen Probleme, nicht nur die technische Bedingungsprüfung selbst.
Der zweite wichtige Nutzen von Feature Flags in Vue-Apps ist die Möglichkeit des sofortigen Zurückschaltens im Fehlerfall. Ein Feature, das nach dem Rollout unerwartete Fehler produziert, kann über das Flag-System innerhalb von Sekunden deaktiviert werden, ohne ein Rollback-Deployment durchzuführen. Diese Reaktionszeit ist bei kritischen Anwendungen, etwa im Checkout, oft der entscheidende Unterschied zwischen einem kleinen Vorfall und einem größeren Umsatzausfall.
2. Eine Composable-API für Feature Flags entwerfen
Die naheliegende Vue-3-Lösung für Feature Flags ist ein Composable, das den Zustand aller Flags zentral hält und über eine einheitliche Schnittstelle abfragbar macht. Statt in jeder Komponente einzeln zu prüfen, wo die Flag-Daten herkommen, kapselt useFeatureFlag(flagName) die gesamte Logik: Laden der Konfiguration, Caching, Fallback-Verhalten bei Netzwerkfehlern und reaktive Aktualisierung, falls sich ein Flag zur Laufzeit ändert.
Wichtig ist, dass das Composable reaktiv bleibt, also ein ref oder computed zurückgibt, keinen statischen Boolean. Das erlaubt es, ein Feature Flag zur Laufzeit umzuschalten, etwa über einen Admin-Panel-Trigger, und die betroffene Vue-Komponente aktualisiert sich automatisch, ohne einen Seiten-Reload zu benötigen. Für Server-Side-Rendering mit Nuxt muss das Composable zusätzlich zwischen Server- und Client-Kontext synchronisiert werden, damit Hydration-Mismatches vermieden werden.
// composables/useFeatureFlag.js — Central, reactive feature flag access
import { computed } from 'vue';
import { useFeatureFlagStore } from '@/stores/featureFlags';
export function useFeatureFlag(flagName) {
const store = useFeatureFlagStore();
const isEnabled = computed(() => {
// Falls back to false if the flag is unknown — never throws in production
return store.flags[flagName]?.enabled ?? false;
});
const variant = computed(() => {
return store.flags[flagName]?.variant ?? 'control';
});
return { isEnabled, variant };
}
// Usage inside a Vue component
import { useFeatureFlag } from '@/composables/useFeatureFlag';
const { isEnabled: showNewCheckout } = useFeatureFlag('new-checkout-flow');
3. Typsicherheit: Flags nicht als beliebige Strings
Ein häufiges Problem bei Feature Flags in Vue-Apps mit vielen Teams ist der Tippfehler im Flag-Namen: useFeatureFlag('new-checkot-flow') statt 'new-checkout-flow' kompiliert klaglos, das Feature bleibt aber dauerhaft deaktiviert, ohne dass ein Fehler sichtbar wird. TypeScript löst dieses Problem, indem alle bekannten Flag-Namen als Union-Type oder als Enum definiert werden, sodass der Compiler bei jedem falschen Flag-Namen sofort einen Fehler meldet.
Für größere Vue-Codebasen empfiehlt sich zusätzlich, die Flag-Definitionen zentral in einer einzigen Datei zu pflegen, idealerweise generiert aus der Konfiguration des Feature-Flag-Providers selbst, damit Frontend-Typen und Backend-Konfiguration nie auseinanderlaufen. Ein CI-Schritt, der prüft, ob alle im Code verwendeten Flag-Namen tatsächlich im Provider existieren, fängt zusätzlich verwaiste oder falsch geschriebene Flags ab, bevor sie in Produktion unbemerkt bleiben.
// types/featureFlags.ts — Central, typed registry of all known flags
export type FeatureFlagName =
| 'new-checkout-flow'
| 'dark-mode-toggle'
| 'ai-product-recommendations'
| 'express-shipping-banner';
export interface FeatureFlagState {
enabled: boolean;
variant?: string;
}
// Typed composable signature — a typo in the flag name fails at compile time
export function useFeatureFlag(flagName: FeatureFlagName): {
isEnabled: import('vue').ComputedRef<boolean>;
variant: import('vue').ComputedRef<string>;
};
4. Remote-Konfiguration statt Rebuild pro Flag-Änderung
Feature Flags, die nur über Build-Time-Umgebungsvariablen gesteuert werden, verlangen für jede Änderung einen neuen Deployment-Zyklus, was den größten Vorteil von Feature Flags, die Entkopplung von Deployment und Aktivierung, wieder aufhebt. Die robustere Architektur lädt die Flag-Konfiguration von einem Remote-Service, entweder einem dedizierten Feature-Flag-Provider wie LaunchDarkly und Unleash, oder einem einfachen, selbst gehosteten JSON-Endpunkt, der beim Start der Vue-Anwendung abgefragt wird.
Wichtig für die Nutzererfahrung ist, dass diese Remote-Abfrage nicht das initiale Rendering blockiert. Ein bewährtes Muster: Flags werden asynchron geladen, während die Anwendung mit sinnvollen Standardwerten rendert, und aktualisiert sich reaktiv, sobald die tatsächliche Konfiguration eintrifft. Für kritische Flags, die das initiale Layout beeinflussen, etwa die Sichtbarkeit eines neuen Headers, kann ein kurzes Preloading über einen synchronen Server-Aufruf in Nuxt sinnvoll sein, um Layout-Shifts zu vermeiden.
// stores/featureFlags.js — Loading remote flag configuration with sane fallbacks
import { defineStore } from 'pinia';
export const useFeatureFlagStore = defineStore('featureFlags', {
state: () => ({
flags: {},
isLoaded: false,
}),
actions: {
async loadFlags(userId) {
try {
const response = await fetch(`/api/feature-flags?userId=${userId}`, {
signal: AbortSignal.timeout(2000), // never block the app for long
});
this.flags = await response.json();
} catch {
// Network failure — keep default flags (all disabled) rather than crashing
console.warn('[feature-flags] Falling back to defaults');
} finally {
this.isLoaded = true;
}
},
},
});
5. Targeting: Rollout-Prozente und Nutzersegmente
Ein einfaches An/Aus-Flag reicht selten für einen kontrollierten Rollout. In der Praxis benötigt Feature-Flag-Targeting mindestens zwei Dimensionen: Prozentuale Rollouts, bei denen ein Feature zunächst für 5 Prozent der Nutzer aktiv ist und schrittweise erhöht wird, und Segment-Targeting, bei dem bestimmte Nutzergruppen, etwa interne Mitarbeiter oder Beta-Tester, das Feature unabhängig vom prozentualen Rollout sehen.
Die Zuordnung eines Nutzers zu einem Rollout-Prozentsatz muss deterministisch und stabil sein, sonst springt ein Nutzer bei jedem Seitenaufruf zwischen aktiviertem und deaktiviertem Zustand. Ein bewährtes Feature-Flag-Pattern ist ein Hash der Nutzer-ID modulo 100, verglichen mit dem Rollout-Prozentsatz. Das garantiert, dass derselbe Nutzer bei gleichbleibendem Rollout-Prozentsatz immer denselben Zustand sieht, während sich die Nutzergruppe bei einer Erhöhung des Prozentsatzes nur erweitert, nie verändert.
// utils/rolloutBucket.js — Deterministic, stable user assignment for percentage rollouts
export function isInRollout(userId, flagName, rolloutPercentage) {
// Combine userId and flagName so the same user gets independent buckets per flag
const key = `${userId}:${flagName}`;
let hash = 0;
for (let i = 0; i < key.length; i++) {
hash = (hash << 5) - hash + key.charCodeAt(i);
hash |= 0; // force 32-bit integer
}
const bucket = Math.abs(hash) % 100;
return bucket < rolloutPercentage; // stable: same userId + flagName -> same bucket
}
// Segment targeting takes priority over percentage rollout
export function resolveFlag(user, flagConfig) {
if (flagConfig.segments?.includes(user.segment)) return true;
return isInRollout(user.id, flagConfig.name, flagConfig.rolloutPercentage ?? 0);
}
6. A/B-Tests auf Basis von Feature Flags
Feature Flags und A/B-Tests teilen dieselbe technische Grundlage, unterscheiden sich aber im Ziel: Ein Feature Flag steuert, ob ein Feature sichtbar ist, ein A/B-Test misst, welche von mehreren Varianten besser performt. In Vue-Apps lässt sich das mit demselben Composable abbilden, indem ein Flag nicht nur enabled, sondern zusätzlich variant zurückgibt, etwa 'control' oder 'treatment'.
Entscheidend für belastbare A/B-Test-Ergebnisse ist, dass die Variantenzuordnung erst nach der Zuordnung geloggt wird, nicht schon bei der Flag-Abfrage. Würde jede Flag-Abfrage automatisch ein Analytics-Event auslösen, würden Komponenten, die ein Flag mehrfach abfragen, etwa bei jedem Re-Render, die Metriken verfälschen. Die korrekte Reihenfolge: Variante einmalig beim ersten sichtbaren Rendern des betroffenen UI-Elements bestimmen und genau einmal an das Analytics-System melden.
// composables/useAbTestExposure.js — Log the variant exactly once, on first visible render
import { onMounted } from 'vue';
import { useFeatureFlag } from '@/composables/useFeatureFlag';
export function useAbTestExposure(flagName) {
const { isEnabled, variant } = useFeatureFlag(flagName);
onMounted(() => {
// Fires once per component mount, not on every reactive re-evaluation
analytics.track('experiment_exposure', {
experiment: flagName,
variant: variant.value,
});
});
return { isEnabled, variant };
}
7. Feature Flags in SSR- und Nuxt-Kontexten
In Nuxt-Anwendungen mit Server-Side-Rendering müssen Feature Flags konsistent zwischen Server und Client aufgelöst werden, sonst entstehen Hydration-Mismatches: Der Server rendert eine Variante, der Client hydratisiert mit einer anderen, weil die Flag-Abfrage clientseitig ein anderes Ergebnis liefert. Die Lösung ist, die Flag-Auflösung serverseitig einmalig durchzuführen, etwa in einem Nuxt-Plugin oder Middleware, und das Ergebnis über den State-Transfer-Mechanismus von Nuxt an den Client zu übergeben.
Für nutzerspezifisches Targeting, etwa basierend auf einer Session-Cookie, muss diese Auflösung bei jedem Server-Request neu erfolgen, darf aber niemals zwischengespeichert und für andere Nutzer wiederverwendet werden. Ein Cache auf Edge-Ebene für Feature-Flag-Antworten ist deshalb nur zulässig, wenn der Cache-Key die relevanten Targeting-Dimensionen, etwa Nutzersegment, korrekt mit einbezieht.
8. Aufräumen: Flags entfernen, bevor sie zu Legacy werden
Der größte langfristige Risikofaktor bei Feature Flags in Vue-Apps ist nicht die Einführung, sondern das Vergessen der Entfernung. Ein Flag, das seit Monaten für 100 Prozent der Nutzer aktiv ist, sollte entfernt werden, sowohl aus dem Provider als auch aus dem Vue-Code, weil jedes verbleibende Flag eine zusätzliche, ungetestete Code-Verzweigung darstellt. Ohne Disziplin sammeln sich über die Zeit Dutzende toter Flags an, die die Codebasis unnötig komplex machen und Refactorings erschweren.
Ein pragmatischer Prozess definiert für jedes Feature Flag von Anfang an ein Ablaufdatum, das im Ticket-System erfasst wird. Nach vollständigem Rollout auf 100 Prozent und einer Beobachtungsphase von ein bis zwei Wochen wird das Flag entfernt: die if-Bedingung im Vue-Code aufgelöst, der nicht mehr benötigte Codepfad gelöscht, und der Flag-Eintrag im Provider archiviert. Manche Teams automatisieren diese Erinnerung sogar über ein Linting-Tool, das Flags meldet, die älter als ein definiertes Zeitfenster sind.
9. Feature-Flag-Ansätze im Vergleich
Für die technische Umsetzung von Feature Flags in Vue-Apps stehen verschiedene Ansätze zur Verfügung, von einfachen Umgebungsvariablen bis zu dedizierten SaaS-Plattformen mit vollständigem Targeting und Analytics.
| Ansatz | Änderung ohne Rebuild | Targeting | Aufwand |
|---|---|---|---|
| Build-Time-Umgebungsvariable | Nein | Keins | Minimal |
| Eigener JSON-Endpunkt | Ja | Manuell umsetzbar | Mittel |
| Unleash (Open Source) | Ja | Umfangreich | Mittel, Self-Hosting |
| LaunchDarkly / Split (SaaS) | Ja | Sehr umfangreich | Kosten, Vendor-Bindung |
Für kleinere Vue-Projekte mit wenigen aktiven Flags reicht ein selbst gehosteter JSON-Endpunkt oft aus. Sobald Rollout-Prozente, Nutzersegmente und A/B-Test-Auswertung gleichzeitig benötigt werden, zahlt sich die Investition in Unleash oder einen SaaS-Anbieter durch geringeren Eigenbau-Aufwand meist schnell aus.
Mironsoft
Feature-Flag-Architektur, kontrollierte Rollouts und Vue-Release-Strategie
Features risikofrei ausrollen, ohne Big-Bang-Releases?
Wir bauen eine typsichere Feature-Flag-Architektur für eure Vue-Apps, inklusive Remote-Konfiguration, Rollout-Targeting und einem Aufräumprozess, der verhindert, dass Flags zu Legacy-Code werden.
Architektur
Composable-basierte, typsichere Feature-Flag-Integration in Vue und Nuxt
Rollout-Strategie
Prozentuale Rollouts, Segment-Targeting und A/B-Test-Auswertung
Aufräumprozess
Ablaufdaten und Linting, damit Flags nicht dauerhaft im Code bleiben
10. Zusammenfassung
Feature Flags in Vue-Apps entkoppeln Deployment und Feature-Aktivierung, was schrittweise Rollouts, sofortiges Zurückschalten im Fehlerfall und datengetriebene A/B-Tests ermöglicht. Eine zentrale Composable-API mit reaktiven Rückgabewerten hält die Nutzung im Code konsistent, während TypeScript-Typen für Flag-Namen Tippfehler bereits zur Compile-Zeit abfangen. Remote-Konfiguration statt Build-Time-Variablen ist Voraussetzung dafür, dass Flags tatsächlich ohne Rebuild geändert werden können.
Deterministisches Rollout-Targeting über Hash-basierte Nutzerzuordnung sorgt für stabile Nutzererfahrung während eines schrittweisen Rollouts. In SSR-Kontexten mit Nuxt muss die Flag-Auflösung zwischen Server und Client konsistent gehalten werden, um Hydration-Mismatches zu vermeiden. Der oft unterschätzte, aber entscheidende letzte Schritt ist die disziplinierte Entfernung ausgerollter Flags, ohne die jede Feature-Flag-Einführung langfristig neue technische Schulden erzeugt.
Feature Flags in Vue-Apps — Das Wichtigste auf einen Blick
Composable-API
Zentrales, reaktives useFeatureFlag statt verstreuter if-Bedingungen in Komponenten.
Typsicherheit
Flag-Namen als Union-Type, damit Tippfehler zur Compile-Zeit auffallen, nicht erst in Produktion.
Targeting
Hash-basierte, deterministische Rollout-Prozente plus Segment-Targeting für Beta-Nutzer.
Aufräumen
Festes Ablaufdatum pro Flag, sonst sammeln sich dauerhaft tote Code-Verzweigungen an.