Konfigurationsmuster für Dev-, Staging- und Prod‑Umgebungen
Muster zur Umgebungs‑Konfiguration, die URLs, Keys und Feature‑Flags aus dem Code fernhalten — für Web, Backend und Mobile in Dev, Staging und Prod.

Warum hartkodierte Konfiguration immer wieder Probleme macht
Hartkodierte Konfiguration wirkt am ersten Tag unproblematisch. Dann braucht man eine Staging‑Umgebung, eine zweite API oder einen schnellen Feature‑Schalter, und die „einfache“ Änderung wird zum Release‑Risiko. Die Lösung ist einfach: Halte Umgebungswerte aus den Quell‑Dateien fern und lege sie in einem vorhersehbaren Setup ab.
Die üblichen Übeltäter sind leicht zu erkennen:
- API‑Basis‑URLs im App‑Code (ruft versehentlich Prod beim Testen an oder Dev nach dem Release)
- API‑Keys im Repo (Lecks, überraschende Kosten, Notfallrotationen)
- Feature‑Schalter als Konstanten (du musst Code ausliefern, um etwas abzuschalten)
- Analytics‑ und Error‑Reporting‑IDs hartkodiert (Daten landen am falschen Ort)
„Ändere es einfach für Prod“ erzeugt die Gewohnheit von Last‑Minute‑Edits. Diese Änderungen umgehen oft Review, Tests und Wiederholbarkeit. Eine Person ändert eine URL, eine andere einen Key – und plötzlich kannst du eine einfache Frage nicht beantworten: Welche exakte Konfiguration wurde mit diesem Build ausgeliefert?
Ein typisches Szenario: Du baust eine neue Mobile‑Version gegen Staging, dann ändert jemand kurz vor dem Release die URL auf Prod. Das Backend ändert sich am nächsten Tag erneut, und du musst zurückrollen. Wenn die URL hartkodiert ist, bedeutet Zurückrollen ein weiteres App‑Update. Nutzer warten, und die Support‑Tickets häufen sich.
Das Ziel ist ein einfaches Schema, das über Web, Go‑Backend und Flutter‑Mobile funktioniert:
- klare Regeln, was in Code gehört und was in die Konfiguration
- sichere Defaults für Dev, Staging und Prod
- Feature‑Schalter, die sich ohne vollständigen Rebuild ändern lassen
- Secrets außerhalb des Codes, mit Möglichkeit zur Rotation
Was sich zwischen Dev, Staging und Prod wirklich ändert
Dev, Staging und Prod sollten sich wie dieselbe App an drei verschiedenen Orten anfühlen. Es geht darum, Werte zu ändern, nicht Verhalten.
Geändert werden sollten alles, was an den Ort oder die Nutzer gebunden ist: Basis‑URLs und Hostnamen, Zugangsdaten, Sandbox‑ vs. Echt‑Integrationen und Sicherheitskontrollen wie Loglevel oder strengere Einstellungen in Prod.
Gleich bleiben sollte die Logik und das Contract‑Verhalten zwischen Komponenten. API‑Routen, Request/Response‑Formate, Feature‑Namen und Geschäftsregeln sollten nicht je nach Umgebung variieren. Wenn Staging anders funktioniert, ist es keine verlässliche Generalprobe für Production mehr.
Eine praktische Regel für „neue Umgebung“ vs. „neuer Konfigwert“: Erstelle eine neue Umgebung nur, wenn du ein isoliertes System brauchst (separate Daten, Zugriff und Risiko). Wenn du nur andere Endpunkte oder andere Zahlen brauchst, füge einen Konfigwert hinzu.
Beispiel: Du willst einen neuen Suchanbieter testen. Wenn er sicher für eine kleine Gruppe aktiviert werden kann, behalte eine Staging‑Umgebung und füge ein Feature‑Flag hinzu. Wenn er jedoch eine separate Datenbank und strikte Zugriffsregeln erfordert, dann ist eine neue Umgebung angebracht.
Ein praktisches Konfigurationsmodell, das überall wiederverwendbar ist
Ein gutes Setup erreicht eines: Es macht es schwer, versehentlich eine Dev‑URL, einen Test‑Key oder ein unfertiges Feature auszuliefern.
Verwende für jede App (Web, Backend, Mobile) dieselben drei Ebenen:
- Defaults: sichere Werte, die in den meisten Fällen funktionieren.
- Environment‑Overrides: was sich für Dev, Staging, Prod ändert.
- Secrets: sensible Werte, die niemals im Repo liegen.
Um Verwirrung zu vermeiden, wähle eine Single Source of Truth pro App und bleibe dabei. Zum Beispiel liest das Backend beim Start Umgebungsvariablen, die Web‑App liest Build‑Time‑Variablen oder eine kleine Runtime‑Konfigurationsdatei, und die Mobile‑App liest eine kleine Umgebungsdatei, die beim Build ausgewählt wird. Konsistenz innerhalb einer App ist wichtiger als dieselbe Mechanik überall zu erzwingen.
Ein einfaches, wiederverwendbares Schema sieht so aus:
- Defaults leben als nicht‑sensible Konstanten im Code (Timeouts, Seitengröße, Retry‑Counts).
- Overrides leben in env‑spezifischen Dateien oder Umgebungsvariablen (API‑Basis‑URL, Analytics an/aus).
- Secrets liegen in einem Secret‑Store und werden während Deploy/Build injiziert (JWT‑Secret, Datenbankpasswort, Third‑Party‑API‑Keys).
Benennung, die Menschen verstehen
Gib jedem Konfig‑Item einen klaren Namen, der drei Fragen beantwortet: was es ist, wo es gilt und welchen Typ es hat.
Eine praktische Konvention:
- Präfix nach App: WEB_, API_, MOBILE_
- Verwende GROSSBUCHSTABEN mit Unterstrichen
- Gruppiere nach Zweck: API_BASE_URL, AUTH_JWT_SECRET, FEATURES_NEW_CHECKOUT
- Halte Booleans explizit: FEATURES_SEARCH_ENABLED=true
So muss niemand raten, ob „BASE_URL“ für die React‑App, den Go‑Service oder die Flutter‑App ist.
Schritt für Schritt: Web‑App‑Konfiguration (React) ohne Hartkodierung
React‑Code läuft im Browser des Nutzers, sodass alles, was du auslieferst, gelesen werden kann. Ziel ist simpel: Secrets bleiben auf dem Server, der Browser liest nur „sichere“ Einstellungen wie API‑Basis‑URL, App‑Name oder nicht‑sensible Feature‑Flags.
1) Entscheide, was Build‑Time vs. Runtime ist
Build‑Time‑Konfiguration wird beim Erstellen des Bundles injiziert. Sie eignet sich für Werte, die selten ändern und die sicher zu exponieren sind.
Runtime‑Konfiguration wird beim Start der App geladen (z. B. aus einer kleinen JSON‑Datei, die mit der App ausgeliefert wird, oder einem injizierten globalen Objekt). Sie eignet sich besser für Werte, die du nach dem Deploy ändern möchtest, etwa das Umschalten einer API‑Basis‑URL zwischen Umgebungen.
Eine einfache Regel: Wenn das Ändern eines Wertes keinen Rebuild der UI rechtfertigt, mache ihn zur Runtime‑Konfiguration.
2) Speichere die API‑Basis‑URL ohne Commit
Halte eine lokale Datei für Entwickler (nicht committed) und setze echte Werte in deiner Deploy‑Pipeline.
- Local dev: nutze
.env.local(gitignored) mit etwaVITE_API_BASE_URL=http://localhost:8080 - CI/CD: setze
VITE_API_BASE_URLals Umgebungsvariable im Build‑Job oder lege sie in eine zur Laufzeit erzeugte Konfigurationsdatei während des Deployments
Runtime‑Beispiel (neben deiner App bereitgestellt):
{ "apiBaseUrl": "https://api.staging.example.com", "features": { "newCheckout": false } }
Dann lade die Datei einmal beim Start und halte die Werte an einer einzigen Stelle:
export async function loadConfig() {
const res = await fetch('/config.json', { cache: 'no-store' });
return res.json();
}
3) Exponiere nur sichere Werte an den Browser
Behandle alles in React‑Env‑Variablen als öffentlich. Packe keine Passwörter, privaten API‑Keys oder Datenbank‑URLs in die Web‑App.
Sichere Beispiele: API‑Basis‑URL, Sentry DSN (public), Build‑Version und einfache Feature‑Flags.
Schritt für Schritt: Backend‑Konfiguration (Go), die du validieren kannst
Backend‑Konfiguration bleibt sicherer, wenn sie getypt ist, aus Umgebungsvariablen geladen und vor dem Start validiert wird.
Beginne damit, explizit festzulegen, was das Backend zum Laufen braucht. Typische "Must‑Have"‑Werte sind:
APP_ENV(dev, staging, prod)HTTP_ADDR(z. B.:8080)DATABASE_URL(Postgres DSN)PUBLIC_BASE_URL(für Callbacks und Links)API_KEY(für einen Drittanbieterdienst)
Lade diese Werte in eine Struct und fail fast, wenn etwas fehlt oder falsch formatiert ist. So findest du Probleme in Sekunden, nicht erst nach einem teilweisen Deploy.
package config
import (
"errors"
"net/url"
"os"
"strings"
)
type Config struct {
Env string
HTTPAddr string
DatabaseURL string
PublicBaseURL string
APIKey string
}
func Load() (Config, error) {
c := Config{
Env: mustGet("APP_ENV"),
HTTPAddr: getDefault("HTTP_ADDR", ":8080"),
DatabaseURL: mustGet("DATABASE_URL"),
PublicBaseURL: mustGet("PUBLIC_BASE_URL"),
APIKey: mustGet("API_KEY"),
}
return c, c.Validate()
}
func (c Config) Validate() error {
if c.Env != "dev" && c.Env != "staging" && c.Env != "prod" {
return errors.New("APP_ENV must be dev, staging, or prod")
}
if _, err := url.ParseRequestURI(c.PublicBaseURL); err != nil {
return errors.New("PUBLIC_BASE_URL must be a valid URL")
}
if !strings.HasPrefix(c.DatabaseURL, "postgres://") {
return errors.New("DATABASE_URL must start with postgres://")
}
return nil
}
func mustGet(k string) string {
v, ok := os.LookupEnv(k)
if !ok || strings.TrimSpace(v) == "" {
panic("missing env var: " + k)
}
return v
}
func getDefault(k, def string) string {
if v, ok := os.LookupEnv(k); ok && strings.TrimSpace(v) != "" {
return v
}
return def
}
Das hält Datenbank‑DSNs, API‑Keys und Callback‑URLs aus dem Code und aus Git. In gehosteten Setups injizierst du diese Env‑Variablen pro Umgebung, sodass Dev, Staging und Prod sich unterscheiden können, ohne eine einzige Zeile zu ändern.
Schritt für Schritt: Mobile‑Konfiguration (Flutter), die flexibel bleibt
Flutter‑Apps brauchen meist zwei Konfigurationsschichten: Build‑Time‑Flavors (was du lieferst) und Runtime‑Einstellungen (was die App ohne neues Release ändern kann). Diese Trennung verhindert, dass „nur eine URL‑Änderung“ zu einem Notfall‑Rebuild wird.
1) Benutze Flavors zur Identität, nicht für Endpunkte
Erstelle drei Flavors: dev, staging, prod. Flavors sollten Dinge kontrollieren, die beim Build fixiert sein müssen, wie App‑Name, Bundle‑ID, Signatur, Analytics‑Projekt und ob Debug‑Tools aktiviert sind.
Gib nur nicht‑sensible Defaults mit --dart-define (oder deinem CI) weiter, sodass du sie nie hartkodierst:
ENV=stagingDEFAULT_API_BASE=https://api-staging.example.comCONFIG_URL=https://config.example.com/mobile.json
In Dart liest du sie mit String.fromEnvironment und baust beim Start ein einfaches AppConfig‑Objekt.
2) Lege URLs und Schalter in eine gefetchte Konfiguration
Wenn du für kleine Endpunkt‑Änderungen keinen Rebuild willst, behandle die API‑Basis‑URL nicht als Konstante. Lade bei App‑Start eine kleine Konfigurationsdatei (und cache sie). Der Flavor legt nur fest, woher die Konfiguration geholt wird.
Eine praktische Aufteilung:
- Flavor (Build‑Time): App‑Identität, Default‑Config‑URL, Crash‑Reporting‑Projekt
- Remote‑Config (Runtime): API‑Basis‑URL, Feature‑Flags, Rollout‑Prozentsätze, Wartungsmodus
- Secrets: nie in der App (Mobile‑Binaries können untersucht werden)
Wenn du das Backend verschiebst, aktualisierst du die Remote‑Config, sodass bestehende Nutzer die neue Basis‑URL beim nächsten Start übernehmen, mit sicherer Rückfalloption auf den zuletzt gecachten Wert.
Feature Flags und Schalter, die nicht im Chaos enden
Feature‑Flags sind nützlich für schrittweise Rollouts, A‑B‑Tests, schnelle Kill‑Switches und das Testen riskanter Änderungen in Staging, bevor du sie in Prod einschaltest. Sie ersetzen keine Sicherheitskontrollen. Wenn ein Flag etwas schützt, das wirklich gesichert werden muss, ist es kein Flag — es ist eine Auth‑Regel.
Behandle jedes Flag wie eine API: klarer Name, ein Owner und ein Enddatum.
Benennung, die die Absicht zeigt
Verwende Namen, die beschreiben, was passiert, wenn das Flag AN ist, und welchen Produktbereich es betrifft. Ein einfaches Schema:
feature.checkout_new_ui_enabled(kundenorientiertes Feature)ops.payments_kill_switch(Notaus‑Schalter)exp.search_rerank_v2(Experiment)release.api_v3_rollout_pct(schrittweiser Rollout)debug.show_network_logs(Diagnose)
Bevorzuge positive Booleans (..._enabled) statt doppelter Verneinungen. Halte ein stabiles Präfix, damit Flags durchsuchbar und auditierbar sind.
Defaults, Schutzmechanismen und Aufräumen
Starte mit sicheren Defaults: Wenn der Flag‑Service ausfällt, sollte deine App sich wie die stabile Version verhalten.
Ein realistisches Muster: Liefere einen neuen Endpoint im Backend, halte den alten weiter am Laufen und nutze release.api_v3_rollout_pct, um Traffic schrittweise zu verschieben. Wenn Fehler steigen, schaltest du zurück, ohne einen Hotfix.
Um ein Flag‑Wachstum zu verhindern, halte dich an ein paar Regeln:
- Jedes Flag hat einen Owner und ein "Remove by"‑Datum
- Entferne Flags innerhalb von 1–2 Releases nach vollständigem Rollout
- Logge Flag‑Werte in wichtigen Flows zum Debuggen
- Überprüfe Flags monatlich wie Dependencies
Secrets: Speicherung, Zugriff und Rotation—Basics
Ein "Secret" ist alles, was bei Leck Schaden anrichten würde. Denke an API‑Tokens, Datenbankpasswörter, OAuth‑Client‑Secrets, Signaturschlüssel (JWT), Webhook‑Secrets und private Zertifikate. Keine Secrets sind: API‑Basis‑URLs, Build‑Nummern, Feature‑Flags oder öffentliche Analytics‑IDs.
Trenne Secrets von den übrigen Einstellungen. Entwickler sollten sichere Konfiguration frei ändern können, während Secrets nur zur Laufzeit injiziert und nur dort verfügbar sind, wo sie gebraucht werden.
Wo Secrets leben sollten (nach Umgebung)
Im Dev‑Umfeld halte Secrets lokal und leicht austauschbar. Nutze eine .env‑Datei oder den OS‑Keychain und mache das Zurücksetzen einfach. Niemals committen.
In Staging und Prod gehören Secrets in einen dedizierten Secret‑Store, nicht ins Repo, nicht in Chat‑Logs und nicht in mobile Binaries.
- Web (React): Keine Secrets im Browser. Wenn der Client ein Token braucht, gib ein kurzlebiges Token vom Backend aus.
- Backend (Go): Lade Secrets aus Umgebungsvariablen oder einem Secrets‑Manager beim Start und halte sie nur im Speicher.
- Mobile (Flutter): Sieh die App als öffentlich. Jedes "Secret" in der App kann extrahiert werden; nutze daher vom Backend ausgestellte Tokens und sichere Gerätespeicher nur für Session‑Daten.
Rotations‑Basics (ohne Prod zu brechen)
Rotation scheitert oft, weil man einen Key swapt und vergisst, dass alte Clients ihn noch nutzen. Plane ein Überlappungsfenster.
- Unterstütze kurzzeitig zwei gültige Secrets (aktiv + vorheriges)
- Rolle das neue Secret zuerst aus, dann weise den "active"‑Pointer um
- Überwache Auth‑Fehler und entferne das alte Secret nach Ablauf des Fensters
- Logge Secret‑Versionen (nicht die Werte) zum sicheren Debuggen
Dieser Überlappungsansatz funktioniert für API‑Keys, Webhook‑Secrets und Signier‑Schlüssel und vermeidet Überraschungs‑Outages.
Beispiel‑Rollout: API‑URLs ändern ohne Nutzer zu brechen
Du hast eine Staging‑API und eine neue Production‑API. Ziel ist, Traffic phased umzuziehen mit einer schnellen Rückkehr‑Option, falls etwas schiefgeht. Das ist einfacher, wenn die App die API‑Basis‑URL aus der Konfiguration liest, nicht aus hartkodiertem Code.
Behandle die API‑URL überall als deploy‑zeitlichen Wert. In der Web‑App (React) ist sie oft Build‑Time oder Runtime‑Config‑Datei. In Mobile (Flutter) ist es typischerweise ein Flavor plus Remote‑Config. Im Backend (Go) ist es eine Runtime‑Env‑Var. Wichtig ist die Konsistenz: Der Code nutzt einen einzigen Variablennamen (z. B. API_BASE_URL) und bettet die URL nie direkt in Komponenten, Services oder Screens ein.
Ein sicherer, gestaffelter Rollout kann so aussehen:
- Deploy der Prod‑API, aber erstmal "dark" (nur interner Traffic), während Staging Standard bleibt.
- Ändere zuerst Backend‑Abhängigkeiten (falls dein Backend andere Services aufruft), über Env‑Vars und schnellen Restart.
- Verschiebe Web‑Traffic in einem kleinen Slice (oder nur interne Konten).
- Release die Mobile‑App mit dem neuen Setup, aber halte einen servergesteuerten Schalter bereit, um das Umschalten zu verzögern.
- Erhöhe Traffic schrittweise und halte eine Rollback‑Option bereit.
Verifikation ist vor allem frühes Erkennen von Unstimmigkeiten. Bevor echte Nutzer die Änderung sehen, prüfe Health‑Endpoints, Auth‑Flows und dass ein Testkonto einen wesentlichen End‑to‑End‑Pfad erfolgreich durchlaufen kann.
Schnelle Checkliste vor dem Shippen
Die meisten Production‑Config‑Bugs sind langweilig: ein Staging‑Wert blieb stehen, ein Flag‑Default ist falsch oder ein API‑Key fehlt in einer Region. Ein schneller Check fängt die meisten ab.
Vor dem Deploy bestätige, dass drei Dinge zur Zielumgebung passen: Endpunkte, Secrets und Defaults.
- Base‑URLs zeigen an die richtigen Ziele (API, Auth, CDN, Payments). Prüfe Web, Backend und Mobile getrennt.
- Keine Test‑Keys in Production und keine Produktions‑Keys in Dev/Staging. Prüfe auch, ob Key‑Namen dem entsprechen, was die App erwartet.
- Feature‑Flags haben sichere Defaults. Alles Riskante sollte standardmäßig aus sein und bewusst eingeschaltet werden.
- Build‑ und Release‑Einstellungen passen (Bundle‑ID/Package‑Name, Custom‑Domain, CORS‑Origins, OAuth‑Redirect‑URLs).
- Observability ist eingerichtet (Logs, Error‑Reporting, Tracing) und trägt das richtige Environment‑Label.
Dann mache einen schnellen Smoke‑Test. Wähle einen echten Nutzer‑Flow und führe ihn End‑to‑End aus, mit frischer Installation oder sauberem Browser‑Profil, damit du nicht von gecachten Tokens abhängst.
- Öffne die App und vergewissere dich, dass sie ohne Console‑Errors lädt.
- Melde dich an und rufe eine API‑Route auf, die Auth erfordert (Profil, Einstellungen oder eine einfache Datenliste).
- Erzeuge einen kontrollierten Fehler (falsche Eingabe oder Offline‑Modus) und vergewissere dich, dass du eine freundliche Fehlermeldung siehst, nicht einen leeren Bildschirm.
- Prüfe Logs und Error‑Reporting: Ein Testfehler sollte innerhalb weniger Minuten unter dem richtigen Environment erscheinen.
Eine praktische Gewohnheit: Behandle Staging wie Production mit anderen Werten. Das bedeutet dieselbe Konfig‑Schema, dieselben Validierungsregeln und dieselbe Deployment‑Form. Nur die Werte unterscheiden sich, nicht die Struktur.
Häufige Fehler, die zu Ausfällen führen
Die meisten Konfigurationsausfälle sind nicht exotisch. Es sind einfache Fehler, die durch verstreute Konfiguration in Dateien, Build‑Schritten und Dashboards passieren, sodass niemand klar beantworten kann: „Welche Werte verwendet diese App gerade?“ Ein gutes Setup macht diese Frage leicht.
Build‑Time und Runtime mischen
Eine häufige Falle ist, Runtime‑Werte an Build‑Time‑Orte zu legen. Eine in den React‑Build gebackene API‑Basis‑URL bedeutet, dass du für jede Umgebung neu bauen musst. Dann wird vielleicht das falsche Artefakt deployed und Production zeigt auf Staging.
Eine sicherere Regel: Backe nur Werte ein, die wirklich nach dem Release nie mehr ändern (z. B. eine App‑Version). Halte Umgebungsdetails (API‑URLs, Feature‑Switches, Analytics‑Endpoints) wenn möglich zur Laufzeit und mache die Quelle der Wahrheit offensichtlich.
Dev‑Endpunkte oder Test‑Keys ausliefern
Das passiert, wenn Defaults zwar „hilfreich“ sind, aber unsicher. Eine Mobile‑App könnte standardmäßig auf eine Dev‑API zurückfallen, wenn sie Konfig nicht lesen kann, oder ein Backend könnte auf eine lokale DB zurückfallen, wenn eine Env‑Var fehlt. Das verwandelt einen kleinen Konfig‑Fehler in einen kompletten Ausfall.
Zwei Gewohnheiten helfen:
- Fail closed: Wenn ein erforderlicher Wert fehlt, crashe früh mit einer klaren Fehlermeldung.
- Mach Production zur schwersten Umgebung zum Fehlkonfigurieren: keine Dev‑Defaults, keine Test‑Keys, keine Debug‑Endpoints erlaubt.
Ein realistisches Beispiel: Ein Release geht Freitagabend raus, und der Produktionsbuild enthält versehentlich einen Staging‑Payment‑Key. Alles „funktioniert“, bis Zahlungen stillschweigend fehlschlagen. Die Lösung ist keine neue Payment‑Bibliothek — es ist Validierung, die nicht‑production Keys in Prod ablehnt.
Staging von Production entkoppeln lassen
Staging, das nicht zu Production passt, gibt falsche Sicherheit. Unterschiedliche Datenbankeinstellungen, fehlende Hintergrundjobs oder zusätzliche Feature‑Flags führen dazu, dass Bugs erst nach dem Launch auftreten.
Halte Staging nah an Production, indem du dasselbe Konfig‑Schema, dieselben Validierungsregeln und dieselbe Deployment‑Form verwendest. Nur die Werte sollten abweichen, nicht die Struktur.
Nächste Schritte: Mach Konfiguration langweilig, wiederholbar und sicher
Das Ziel ist kein fancy Tooling, sondern langweilige Konsistenz: dieselben Namen, dieselben Typen, dieselben Regeln in Dev, Staging und Prod. Wenn Konfiguration vorhersehbar ist, fühlt sich ein Release nicht mehr riskant an.
Beginne damit, einen klaren Config‑Contract an einem Ort zu dokumentieren. Halte ihn kurz, aber spezifisch: jeder Schlüsselname, sein Typ (string, number, boolean), woher er kommen darf (Env‑Var, Remote‑Config, Build‑Time) und sein Default. Notiere Werte, die niemals in einer Client‑App gesetzt werden dürfen (z. B. private API‑Keys). Behandle diesen Contract wie eine API: Änderungen brauchen Review.
Lass Fehler früh fehlschlagen. Die beste Zeit, eine fehlende API‑Basis‑URL zu entdecken, ist in CI, nicht nach dem Deploy. Füge automatisierte Validierung hinzu, die Konfiguration genauso lädt wie deine App und prüft:
- erforderliche Werte sind vorhanden (keine leeren Strings)
- Typen sind korrekt (kein "true" vs true‑Bug)
- Prod‑Only‑Regeln passen (z. B. HTTPS erforderlich)
- Feature‑Flags haben bekannte Namen (keine Tippfehler)
- Secrets sind nicht ins Repo geraten
Schließlich: Erleichtere die Wiederherstellung, wenn eine Konfig‑Änderung schiefgeht. Snapshot, ändere eine Sache nach der anderen, verifiziere schnell und behalte einen Rollback‑Pfad.
Wenn du mit einer Plattform wie Koder.ai (koder.ai) baust und deployst, gelten dieselben Regeln: Behandle Umgebungswerte als Inputs für Build und Hosting, halte Secrets aus exportiertem Quellcode fern und validiere Konfiguration bevor du auslieferst. Diese Konsistenz macht Redeploys und Rollbacks routinemäßig.
Wenn Konfiguration dokumentiert, validiert und reversibel ist, wird sie keine Fehlerquelle mehr, sondern ein normaler Teil des Auslieferungsprozesses.
FAQ
Was gehört in die Konfiguration statt in den Code?
Werte, die sich je nach Umgebung ändern, gehören nicht in die Quelldateien. Lege unkritische Standardwerte im Code ab, nutze umgebungsspezifische Einstellungen für URLs und Schalter und injiziere Geheimnisse beim Build oder Deployment.
Wann brauche ich eine neue Umgebung?
Nutze getrennte Entwicklungs-, Staging- und Produktionsumgebungen, wenn du Daten, Zugriffe oder Risiken isolieren musst. Wenn sich nur eine URL, ein Limit oder ein Schalter ändert, füge stattdessen einen Konfigurationswert hinzu.
Kann ich Geheimnisse in einer React-App speichern?
Nein. Alles, was an den Browser ausgeliefert wird, ist für Nutzer sichtbar. Bewahre private Schlüssel und Passwörter im Backend auf und stelle nur unkritische Werte bereit, etwa eine öffentliche API-URL oder ein einfaches Feature-Flag.
Sollte meine Web-App Build-Zeit- oder Laufzeitkonfiguration verwenden?
Nutze Build-Zeit-Werte für Einstellungen, die sich selten ändern und sicher offengelegt werden können. Lade Laufzeitkonfiguration für Werte, die du nach dem Deployment ändern musst, etwa eine API-Basis-URL oder einen Wartungsschalter.
Wie sollte ein Go-Backend Konfiguration handhaben?
Lade erforderliche Umgebungsvariablen beim Start des Dienstes in eine typisierte Konfigurationsstruktur. Prüfe zulässige Umgebungen, URLs und Datenbank-Verbindungsstrings und brich den Start mit einer klaren Fehlermeldung ab, wenn ein erforderlicher Wert fehlt.
Wie sollte Flutter mit Entwicklung, Staging und Produktion umgehen?
Nutze Flutter Flavors für buildspezifische Details wie App-ID, Signierung und Analytics-Projekt. Rufe unkritische Laufzeiteinstellungen wie API-URLs und Feature-Flags aus einer Remote-Konfigurationsquelle ab.
Wie verhindere ich, dass sich Feature-Flags anhäufen?
Benenne Flags nach dem Verhalten, das sie aktivieren, etwa feature.checkout_new_ui_enabled. Weise jedem Flag einen Verantwortlichen und ein Entfernungsdatum zu, setze riskante Änderungen standardmäßig auf aus und entferne das Flag kurz nach dem vollständigen Rollout.
Wo sollte ich API-Schlüssel und Datenbankpasswörter speichern?
Speichere Staging- und Produktionsgeheimnisse in einem dedizierten Secret Store und injiziere sie nur in die Dienste, die sie benötigen. Bewahre Geheimnisse für die lokale Entwicklung in ignorierten lokalen Dateien oder im Schlüsselbund des Betriebssystems auf.
Wie kann ich Geheimnisse ohne Ausfallzeit rotieren?
Lass alte und neue Zugangsdaten für eine kurze Überschneidungsphase parallel laufen. Stelle Clients oder Dienste mit dem neuen Wert bereit, schalte den aktiven Traffic um, beobachte Authentifizierungsfehler und entferne anschließend die alten Zugangsdaten.
Was sollte ich vor einem Produktions-Release prüfen?
Prüfe, ob jeder Endpunkt auf die Zielumgebung zeigt, alle erforderlichen Geheimnisse vorhanden sind und riskante Flags standardmäßig deaktiviert sind. Führe dann einen vollständigen Nutzerablauf in einem sauberen Browserprofil oder nach einer frischen App-Installation aus und bestätige, dass die Logs die richtige Umgebungsbezeichnung verwenden.