Zruck zum Blog, du Zniachtl
Juni 2026·4 Min. zum LesnVo da KI gmocht

Feature Toggling mit umgebungsbasierter Config

#backend#devops#architecture

Die einfachste Art, a halbfertiges Feature in Produktion zu bringen, ohne es zum Offenlegn, is a die am häufigsten schlecht neu erfundene: a Boolean, aus da Config glesn, in am if gprüft. Bevor du zu am Feature-Flag-Service mit Dashboard und SDK greifst, zahlt si's aus zu wissn, wia weit a einfacher umgebungsbasierter Toggle dich tatsächlich bringt - und des is weiter, ois de meisten Teams annehmen.

Da Kerngedanke

A Feature Toggle is a Laufzeit-Check, der entscheidet, ob a Codepfad ausgführt wird. Der Wert vom Flag kummt von außerhalb vom Code - Umgebungsvariablen, a Config-Datei, a Datenbankzeile -, sodass du's Verhalten ändern kannst, ohne neichn Deploy.

const features = {
  newCheckoutFlow: process.env.FEATURE_NEW_CHECKOUT === 'true',
  betaExportApi: process.env.FEATURE_EXPORT_API === 'true',
};

function handleCheckout(req, res) {
  if (features.newCheckoutFlow) {
    return handleCheckoutV2(req, res);
  }
  return handleCheckoutV1(req, res);
}

Des is der gesamte Mechanismus. Olles andere - prozentuale Rollouts, Targeting pro Nutzer, Notausschalter - is Verfeinerung obendrauf auf "an Wert lesn und drauf verzweigen".

Warum der Aufwand, statt einfach das Feature zu deployn

  • Deploy vom Release entkoppeln. Code hinter ana Flag auf false mergen und deployn, dann separat einschaltn - ohne Deploy -, wennst wirklich bereit bist. Des macht aus Releasen a Config-Änderung statt a Code-Änderung, wos schneller zum Machn und schneller zum Rückgängigmachn is.
  • Notausschalter. Wenn a neicher Codepfad in Produktion spinnt, is a Flag ausschaltn sofort wirksam. Einen Deploy zurückrollen dauert länger und macht olles in dem Deploy rückgängig, ned nur des kaputte Feature.
  • Umgebungsspezifisches Verhalten. A Feature im Staging wochenlang vor da Produktion einschaltn, ohne an eigenen Branch zu pflegen.

A Config-Schicht, de über a Handvoll Booleans hinaus skaliert

process.env.FEATURE_X === 'true'-Checks quer durch die Codebasis zu streun funktioniert für zwoa Flags und wird bei zehn unwartbar. Zentralisier's:

// config/features.js
function bool(name, fallback = false) {
  const value = process.env[name];
  if (value === undefined) return fallback;
  return value === 'true' || value === '1';
}

module.exports = {
  newCheckoutFlow: bool('FEATURE_NEW_CHECKOUT'),
  betaExportApi: bool('FEATURE_EXPORT_API'),
  strictRateLimit: bool('FEATURE_STRICT_RATE_LIMIT', true), // defaults on
};

Jetzt importiert jede Aufrufstelle von oam Ort, jedes Flag hot oane Zeiln, de seinen Default dokumentiert, und a Flag hinzuzufügen is a Einzeiler-Änderung.

const features = require('./config/features');

if (features.betaExportApi) {
  app.use('/api/export', exportRouter);
}

Flags behandeln, de Targeting pro Nutzer brauchen

Umgebungsvariablen sand global - jeder Request auf dem Prozess sieht den söbn Wert. Des passt für "is des Feature überhaupt in Produktion live", aber ned für "zeig des 5 % der Nutzer" oda "zeig des nur internen Accounts". Dafür braucht der Flag-Check a Stückl Request-Kontext:

function isEnabledForUser(flagName, user) {
  if (!features[flagName]) return false;

  // internal accounts always see flags that are otherwise off for everyone
  if (user?.isInternal) return true;

  // deterministic percentage rollout: same user always gets the same bucket
  const bucket = hashToPercent(`${flagName}:${user.id}`);
  return bucket < rolloutPercent(flagName);
}

function hashToPercent(input) {
  let hash = 0;
  for (let i = 0; i < input.length; i++) {
    hash = (hash * 31 + input.charCodeAt(i)) >>> 0;
  }
  return hash % 100;
}

Das wichtige Detail is, dass hashToPercent pro Nutzer deterministisch is, ned zufällig pro Request - a Nutzer in den 5 % soit bei jedem Request drin bleibn, sonst kriagst a inkonsistente Erfahrung (neiche UI bei oam Seitnaufruf, oide beim nächsten), de Nutzer verwirrt und aus am Bug-Report unmöglich zum Debuggn is.

Wo Flags zum Sterben hingehn

Der Fehlermodus von Feature Flags is ned das Hinzufügen - es is, sie nie zum Entfernen. A Flag, des seit sechs Monaten in jeder Umgebung auf true steht, is totes Gewicht: a Branch, dessen false-Seitn niemand mehr testet, a Bedingung, de jeder künftige Leser im Kopf auswerten muass, und a Quelle für "wart, is der Code überhaupt erreichbar?" beim Debuggn.

Behandl a Flag ois temporäres Konstrukt mit erwarteter Lebensdauer:

  • Nenn's nach dem Feature, ned nach da Ticketnummer (newCheckoutFlow, ned PROJ-4821) - es soit nach am Joar noch selbsterklärend sei.
  • Wenn a Flag a Weile ohne Zwischenfälle in Produktion auf 100 % steht, is des a Ticket zum Löschen vom Flag und vom oidn Codepfad, ka Dauerzustand.
  • Flags, de wirklich dauerhaft gmeint sand (a Ops-Notausschalter, a Pro-Umgebung-Toggle), sand a andere Kategorie - benenn und dokumentier sie anders, damit niemand versucht, sie "aufzuräumen".

Wenn Umgebungsvariablen nimma reichen

Reine umgebungsbasierte Flags stoßen an a echte Decke: Eins zu ändern verlangt immer no, die Deploy-Umgebung anzufassn (a Redeploy, oda zumindest an Prozess-Neustart, um den neichn Wert zu übernehmen), und es gibt ka Audit-Log, wer wos wann umgschaltet hot. Do verdient a dedizierter Flag-Service (LaunchDarkly, Unleash, oda a einfache Flags-Tabelle in deiner eigenen Datenbank mit Admin-UI) seine Komplexität - sofortiges Umschoitn ohne Deploy, Regeln pro Nutzer ohne selbstgbautes Hashing, und a Änderungshistorie.

Greif aber ned schon am ersten Tag dazu. A Dutzend Umgebungsvariablen, über a klans Config-Modul glesn, tragen a Projekt bequem a lange Zeit, und das Konzept vom Flag (a Name, a Boolean, Aufrufstellen, de's prüfen) später auf an echten Flag-Service zu migriern, is a mechanische Änderung, ka Neugestaltung.

Fazit

A Feature Flag is nur a if, dessen Bedingung außerhalb vom Code lebt. Zentralisier die Checks, mach prozentuale Rollouts pro Nutzer deterministisch, und - der Teil, den jeder überspringt - lösch Flags tatsächlich, sobois sie sich bei 100 % eingspielt hom. Die Infrastruktur, um Flags im großen Stil zu verwalten, is optional; die Disziplin, sie zu entfernen, ned.

NeicherBig-O-Notation, erklärt mit echtem CodeElterA Rate-Limiter-Middleware in Express bauen