Feature Flags mit Claude Code: sichere Rollouts, Experimente und Kill Switches
Praxisguide für Feature Flags mit Claude Code: Rollout, Experimente, Kill Switches, Targeting, Metriken und Cleanup.
Beginne mit der Betriebsregel, nicht mit dem Toggle
Ein Feature Flag ist ein Laufzeit-Schalter: Code kann deployt werden, während eine Funktion aus bleibt, schrittweise ausgerollt wird oder im Notfall schnell deaktiviert werden kann. Der Anfängerfehler ist nicht das if (flag). Der teure Fehler ist, Release Flag, Experiment Flag und Kill Switch gleich zu behandeln, obwohl sie unterschiedliche Lebensdauer, Owner, Metriken und Cleanup-Regeln brauchen.
Claude Code erzeugt eine UI-Abzweigung sehr schnell. Für Produktion brauchst du mehr: sicheren Default, Targeting Context, klare Grenze zwischen Server- und Client-Auswertung, Exposure-Logs, Guardrail-Metriken, Rollback-Schritte und ein Datum, an dem temporäre Flags gelöscht werden. In Masas Workflows für Content-Seiten und kleine SaaS-Produkte war der beste Prompt nie “baue Feature Flags”, sondern “was kann brechen, was schalten wir ab und woran erkennen wir einen gesunden Rollout”.
Stütze das Design auf Primärquellen. OpenFeature trennt die Evaluation API der Anwendung vom Provider dahinter und nutzt Evaluation Context für Nutzer-, App- und Umgebungsdaten. LaunchDarkly dokumentiert Use Cases wie Release Flags, Experiment Flags und Kill Switches. Unleash beschreibt den Lebenszyklus Define, Develop, Production, Cleanup, Archived, damit alte Flags nicht im Code liegen bleiben. Claude Code Best Practices betonen ebenfalls eine klare Verifikationsroute.
Verwendete Referenzen:
- OpenFeature introduction
- OpenFeature evaluation context
- LaunchDarkly creating flags
- LaunchDarkly targeting rules
- LaunchDarkly guarded rollouts
- Unleash feature flag lifecycle
- Claude Code best practices
Release, Experiment und Kill Switch trennen
Klassifiziere Flags nach Lebensdauer, bevor du Code schreibst. Ein Release Flag versteckt unfertige Arbeit, öffnet sie schrittweise und verschwindet nach 100% Rollout. Ein Experiment Flag prüft eine Hypothese und muss Exposure sowie Ergebnis messen. Ein Kill Switch ist ein längerlebiger Sicherheitshebel für externe API-Ausfälle, Kostenspitzen, langsame Empfehlungen oder riskante Automatisierung.
| Produktfall | Typ | Erfolgsmessung | Aktion bei Fehler |
|---|---|---|---|
| Neuer Checkout für 25% der Pro-Konten | Release | Checkout-Abschluss, Zahlungsfehler | checkout_v2_release ausschalten |
| CTA-Text auf Pricing-Seite testen | Experiment | Registrierungsstarts, Kaufabsicht-Klicks | Experiment stoppen, control ausliefern |
| Affiliate-Block in den Artikeltext verschieben | Experiment | Produktklicks, Lesefortschritt | Block zurück ans Artikelende |
| Empfehlungen bei Provider-Störung deaktivieren | Kill switch | p95-Latenz, 5xx-Rate | recommendations_enabled ausschalten |
Ohne Messung ist ein Flag nur Bauchgefühl. Lies dazu A/B Testing mit Claude Code und Analytics-Implementierung mit Claude Code. Auf monetarisierten Seiten schützt eine CTA nicht nur Klicks, sondern auch AdSense-Qualität, Lesefortschritt, Affiliate-Umsatz und Beratungsabsicht. Für den Einstieg eignet sich die kostenlose Ressource; für Teams ist die englische Beratung der nächste Schritt.
Minimale Config und Evaluator
Binde die Geschäftslogik am Anfang nicht zu hart an einen Anbieter. Die App sollte per Key, Default und Context auswerten; der Provider dahinter kann später LaunchDarkly, Unleash, OpenFeature, JSON oder ein interner Service sein. Das folgende Beispiel passt in flag-demo.ts und läuft mit npx tsx flag-demo.ts.
type FlagValue = boolean | string | number;
type FlagKind = "release" | "experiment" | "kill_switch";
type Plan = "free" | "pro" | "enterprise";
type Role = "user" | "admin";
type Operator = "equals" | "in";
type FlagContext = {
targetingKey: string;
plan: Plan;
country: string;
role: Role;
appVersion: string;
};
type FlagRule = {
attribute: keyof Omit<FlagContext, "targetingKey">;
operator: Operator;
values: string[];
value: FlagValue;
percentage?: number;
};
type FlagConfig = {
key: string;
kind: FlagKind;
enabled: boolean;
defaultValue: FlagValue;
offValue: FlagValue;
owner: string;
removeAfter?: string;
rules: FlagRule[];
};
const registry: Record<string, FlagConfig> = {
checkout_v2_release: {
key: "checkout_v2_release",
kind: "release",
enabled: true,
defaultValue: false,
offValue: false,
owner: "growth-platform",
removeAfter: "2026-07-15",
rules: [
{
attribute: "role",
operator: "equals",
values: ["admin"],
value: true,
},
{
attribute: "plan",
operator: "in",
values: ["pro", "enterprise"],
value: true,
percentage: 25,
},
],
},
pricing_copy_2026_06: {
key: "pricing_copy_2026_06",
kind: "experiment",
enabled: true,
defaultValue: "control",
offValue: "control",
owner: "monetization",
removeAfter: "2026-06-30",
rules: [
{
attribute: "country",
operator: "in",
values: ["JP", "US", "DE"],
value: "simple",
percentage: 50,
},
],
},
recommendations_enabled: {
key: "recommendations_enabled",
kind: "kill_switch",
enabled: true,
defaultValue: true,
offValue: false,
owner: "sre",
rules: [],
},
};
function bucketFor(flagKey: string, targetingKey: string): number {
const input = `${flagKey}:${targetingKey}`;
let hash = 0;
for (const char of input) {
hash = (hash * 31 + char.charCodeAt(0)) >>> 0;
}
return hash % 100;
}
function ruleMatches(
flagKey: string,
rule: FlagRule,
context: FlagContext,
): boolean {
const actual = String(context[rule.attribute]);
const matched =
rule.operator === "equals"
? actual === rule.values[0]
: rule.values.includes(actual);
if (!matched) return false;
if (rule.percentage === undefined) return true;
return bucketFor(flagKey, context.targetingKey) < rule.percentage;
}
export function evaluateFlag<T extends FlagValue = FlagValue>(
key: string,
context: FlagContext,
): T {
const flag = registry[key];
if (!flag) return false as T;
if (!flag.enabled) return flag.offValue as T;
for (const rule of flag.rules) {
if (ruleMatches(flag.key, rule, context)) {
return rule.value as T;
}
}
return flag.defaultValue as T;
}
const demoContexts: FlagContext[] = [
{
targetingKey: "user_001",
plan: "pro",
country: "JP",
role: "user",
appVersion: "1.8.0",
},
{
targetingKey: "user_002",
plan: "free",
country: "BR",
role: "admin",
appVersion: "1.8.0",
},
];
for (const context of demoContexts) {
console.log(context.targetingKey, {
checkout: evaluateFlag<boolean>("checkout_v2_release", context),
pricingCopy: evaluateFlag<string>("pricing_copy_2026_06", context),
recommendations: evaluateFlag<boolean>(
"recommendations_enabled",
context,
),
});
}
Die wichtigen Details sind absichtlich schlicht. Unbekannte Flags fallen auf einen sicheren Fallback. Prozent-Rollout nutzt einen stabilen targetingKey, nicht Math.random(). Temporäre Flags haben Owner und removeAfter. Das Registry kann später in eine Control Plane wandern.
Auf dem Server auswerten, im Client anzeigen
Alles rund um Billing, Berechtigungen, Quotas, Bestand oder Backend-Kosten gehört in die Server-Auswertung. Client-Flags eignen sich für freigegebene UI-Texte, Layouts, Onboarding-Hinweise oder risikoarme visuelle Varianten. Schicke keine geheimen Targeting-Regeln an den Browser und ersetze Autorisierung nie durch versteckte Buttons.
type User = {
id: string;
plan: "free" | "pro" | "enterprise";
role: "user" | "admin";
};
type RequestLike = {
headers: {
get(name: string): string | null;
};
};
export function buildFlagContext(
user: User,
request: RequestLike,
): FlagContext {
return {
targetingKey: user.id,
plan: user.plan,
role: user.role,
country: request.headers.get("x-country") ?? "US",
appVersion: process.env.NEXT_PUBLIC_APP_VERSION ?? "dev",
};
}
export function getServerFlagSnapshot(context: FlagContext) {
return {
checkoutV2: evaluateFlag<boolean>("checkout_v2_release", context),
pricingCopy: evaluateFlag<string>("pricing_copy_2026_06", context),
};
}
type PricingFlags = {
pricingCopy: string;
};
export function PricingCta({ flags }: { flags: PricingFlags }) {
const label =
flags.pricingCopy === "simple"
? "Mit dem kostenlosen Plan starten"
: "Kostenlose Testversion starten";
return <a href="/signup">{label}</a>;
}
Die React-Komponente rendert nur ein bereits ausgewertetes Snapshot. Im Claude-Code-Prompt sollte stehen: Berechtigungen und Billing bleiben serverseitig, der Client konsumiert nur das Ergebnis.
Rollout mit Observability
Ein sicherer Rollout heißt nicht nur “bei 1% anfangen”. Du brauchst Ramp-Plan, Metriken und Rollback-Schwellen. Unleash kombiniert Prozent, Stickiness und Constraints. LaunchDarkly Guarded Rollouts verbinden Rollouts mit Metriken und können bei Regression pausieren oder zurückrollen. Dieses Betriebsmodell lohnt sich auch bei einem kleinen internen Evaluator.
Tracke drei Ebenen: Exposure, primäre Metrik und Guardrails. Exposure sagt, wer welchen Flag-Wert gesehen hat. Die primäre Metrik zeigt, ob das gewünschte Verhalten steigt. Guardrails zeigen, ob Performance, Fehler, Umsatzqualität, Supportlast oder Vertrauen leiden.
type FlagExposure = {
flagKey: string;
value: FlagValue;
targetingKey: string;
route: string;
evaluatedAt: string;
};
export function trackFlagExposure(event: FlagExposure) {
console.log(
JSON.stringify({
event_name: "feature_flag_exposure",
...event,
}),
);
}
Beim Checkout beobachtest du 5xx, Zahlungsfehler und Supporttickets. Beim monetarisierten Blog zählen nicht nur Affiliate-Klicks, sondern auch Lesefortschritt, Bounce, Core Web Vitals und Kauf- oder Beratungsabsicht. Bei KI-Funktionen kommen Tokenkosten, p95-Latenz und Nutzerquotas dazu. Mehr Klicks bei schlechterer Käuferqualität sind kein Erfolg.
Konkrete Fehlerbilder
Erstens: zufällige Zuweisung bei jedem Laden. Wenn ein Refresh von A zu B wechselt, sind Exposure und Conversion kaputt. Nutze einen stabilen Targeting Key.
Zweitens: Premium nur im Client verstecken. Ein fehlender React-Button schützt keine API. Feature Flags steuern UX, ersetzen aber keine Autorisierung.
Drittens: unsicherer Default. Ein unbekanntes Release Flag sollte normalerweise false liefern. Wenn ein Tippfehler true ausliefert, hast du versehentlich gelauncht.
Viertens: temporäre Flags nie löschen. Monate später ist checkout_v2_release rätselhafte Logik. Nach Entscheidung gehört ein Cleanup-PR dazu.
Fünftens: zu viele verschachtelte Regeln. Parent Flags, Child Flags und überlappende Prozent-Rollouts machen unklar, welche Nutzer die Funktion wirklich sehen.
Sichere Prompts für Claude Code
Claude Code kann Dateien lesen, Code ändern und Tests ausführen. Gib Grenzen und Verifikation direkt vor.
Füge diesem Repository einen Feature-Flag-Workflow hinzu.
Das erste Flag ist checkout_v2_release für staged rollout.
Constraints:
- Billing und Autorisierung werden serverseitig ausgewertet.
- Unbekannte Release Flags geben false zurück.
- Prozent-Rollout nutzt einen stabilen targetingKey.
- Das Registry enthält owner und removeAfter.
- Ändere keine unrelated files.
Erwartete Ausgabe:
- Minimales Flag Registry und evaluateFlag-Funktion
- Typ für Exposure-Event
- Mindestens 3 Produktfälle
- Fehlerbeispiele und Rollback-Schritte
- Ausgeführte Testbefehle
Vor dem Merge nutzt du einen Review-Prompt:
Reviewe diese Feature-Flag-Implementierung.
Prüfe Defaults, Server/Client-Grenze, stabiles Bucketing,
fehlende Exposure Events, Cleanup-Daten und Rollback-Verhalten.
Liste Findings nach Schweregrad mit konkreten Dateien.
So bekommt Claude Code eher ein wartbares Betriebssystem als einen dekorativen Toggle.
Cleanup gehört zum Release
Jedes Flag altert ab dem Tag seiner Erstellung. Release Flags verschwinden nach vollem Rollout. Experiment Flags verschwinden nach Wahl des Gewinners. Kill Switches dürfen bleiben, brauchen aber Owner, Runbook und Alerts. Nimm owner, removeAfter, Metriken und geplanten Removal-PR in dein Pull-Request-Template auf.
Ich habe den Evaluator in diesem Artikel als ausführbare TypeScript-Demo geprüft: derselbe targetingKey landet im selben Bucket, unbekannte Flags geben den sicheren Fallback zurück und der Kill Switch hat einen expliziten off value. Masas Praxisnotiz für monetarisierte Inhalte: Qualität zusätzlich zu Klicks messen. Starte mit einem Release Flag, einem Experiment Flag und einem Kill Switch, bevor du eine vollständige Plattform einführst.
Kostenloses PDF: Claude-Code-Cheatsheet
E-Mail eintragen und eine Seite mit Befehlen, Review-Gewohnheiten und sicheren Workflows herunterladen.
Wir schützen Ihre Daten und senden keinen Spam.
Über den Autor
Masa
Engineer für praktische Claude-Code-Workflows und Team-Einführung.
Ähnliche Artikel
Claude Code Permission Safety Ladder: Zugriff kontrolliert erweitern
Von read-only zu begrenzten Änderungen, Prüfbefehlen und Deploy-Checks mit klarer Kontrolle.
Claude Code Small PR Proof Pack: kleine Änderungen reviewbar machen
Ein Proof Pack für Claude-Code-PRs: Diff, Checks, öffentliche URL, CTA-Pfad und Rollback.
Claude-Code-Review-Gate vor dem Commit
Vor dem Commit mit Claude Code prüfen: Diff, Build, öffentliche URL, Gumroad-Links, Beratung-CTA, fehlende Tests und fremde Dateien.