Lokal ist ein Streichelzoo. Prod ist Natur. Hier sind die Klassiker, warum’s knallt – und wie du das zuverlässig abstellst, statt jedes Release zu würfeln.
„Bei mir geht’s.“ Ja. Bei dir laufen auch Debug-Flags, Hot-Reload, leere Caches, eine frische DB, keine Last und exakt dein Setup. Produktion hat: Reverse Proxy, TLS, andere ENV-Variablen, andere Daten, andere Rechte, andere Limits.
Die Lösung ist nicht „mehr testen“, sondern: Dev/Prod-Parität, reproduzierbare Builds und Observability. Kurz: Du musst die Unterschiede absichtlich klein halten und die Rest-Unterschiede messbar machen.
- Config gehört in ENV (nicht in Code) und muss in Staging/Prod identisch strukturiert sein.
- Build einmal (CI), deploye genau dieses Artefakt – kein „in Prod nochmal bauen“.
- Staging wie Prod: gleiche Reverse-Proxy-Kette, gleiche DB-Version, gleiche Caches, gleiche Limits.
- Logs + Healthchecks: Debug ohne Logs ist Hellsehen.
- Migrations automatisieren und rollback-fähig denken (oder wenigstens „forward fix“ planbar).
Warum Prod anders ist (und warum das normal ist)
Ein guter Grundsatz aus der „Twelve-Factor App“: Dev/Prod parity und Config über Environment. Heißt: Unterschiede minimieren, nicht wegerklären.
Prod ist außerdem nicht nur „Server statt Laptop“, sondern ein System: Load Balancer/Reverse Proxy, TLS-Termination, Caches, Firewalls, Rechte, Rate Limits, Observability. Wenn du lokal nur „node server.js“ machst, testest du nicht das System.
Die 10 Klassiker: warum „läuft lokal“ in Prod stirbt
1) Config/ENV-Drift: Keys fehlen, heißen anders, haben andere Defaults
Das ist der häufigste Grund. Lokal hast du .env (oder Hardcodes), in Prod ist die Variable leer, anders benannt oder wird vom Prozess nicht geladen.
- Fix: Config strikt über ENV (12-Factor) und ein „Config Schema“: welche Variablen sind Pflicht, welche haben Defaults.
- Fix: Beim Start fail-fast: wenn Pflicht-ENV fehlt → Start bricht ab (besser als „läuft irgendwie kaputt“).
2) Secrets falsch: API-Keys, JWT-Secrets, OAuth Redirect URIs
„Lokal geht Login“, in Prod nicht: falsche Redirect URI, falscher Client Secret, falsche Domain, falsche Callback-URLs.
- Fix: Secrets nicht im Repo, sondern in Secret-Store/Deployment-Settings.
- Fix: Eine Quelle der Wahrheit pro Umgebung, kein „hier noch ein Key im Code“.
3) Build ist nicht reproduzierbar: Lockfile/Node-Version/Composer-Version
Wenn Prod etwas anderes baut als CI (oder lokal), hast du faktisch zwei Apps: die, die du getestet hast, und die, die du ausrollst.
- Fix: Build einmal in CI, deploye Artefakt (Container/Image/Build-Zip).
- Fix: Lockfiles nutzen und Runtime-Versionen pinnen (z.B. Node/PHP).
4) OS/Dateisystem-Unterschiede: Case-Sensitivity, Pfade, Rechte
Mac/Windows sind oft case-insensitive, Linux in Prod oft case-sensitive. /Images/logo.png vs /images/logo.png ist dann kein „kleiner Unterschied“, sondern 404.
- Fix: Lint/CI-Checks für Pfade, konsequente Namenskonventionen.
- Fix: Schreibrechte explizit: was darf wohin? In Prod ist „alles beschreibbar“ eine schlechte Idee.
5) Reverse Proxy/TLS: Headers, Redirects, „falsches“ HTTPS
Lokal: direkt am App-Port. Prod: hinter Nginx/Traefik/Cloud LB. Dann sind Client-IP, Protocol, Hostname und Redirect-Logik plötzlich anders.
- Fix: Proxy-Header korrekt auswerten (z.B.
X-Forwarded-Proto,X-Forwarded-For) und Framework-Settings dafür richtig setzen. - Fix: HSTS/Redirects testen: keine Redirect-Loops, keine Mixed-Content-Calls.
6) CORS/CSRF: lokal egal, in Prod brennt’s
Lokal rufst du API und Frontend vom gleichen Origin auf oder hast CORS „weit auf“. In Prod sind es andere Domains/Subdomains.
- Fix: CORS-Policy strikt pro Origin (keine Wildcards mit Credentials).
- Fix: CSRF-Schutz sauber (Tokens / SameSite Cookies), besonders bei Admin/Forms.
7) Datenbank-Unterschiede: Version, Collation, Migrations, Seed-Daten
Lokal hast du eine leere DB mit netten Testdaten. Prod hat reale Daten, Sonderzeichen, alte Datensätze, und das DB-Schema ist manchmal „fast gleich“.
- Fix: Migrations automatisch in Pipeline/Deploy (kontrolliert), kein Handarbeit-Roulette.
- Fix: Staging mit anonymisierten, realitätsnahen Daten (wo möglich) statt Fantasie-Seeds.
8) Caching macht Bugs unsichtbar oder neu: App-Cache, CDN, Browser
Lokal: Cache aus oder leer. Prod: CDN, Reverse Proxy Cache, App Cache, Browser Cache. Du deployest CSS, aber Nutzer sehen die alte Version → „UI kaputt“.
- Fix: Asset-Versionierung (Hash im Dateinamen), damit Caches automatisch „richtig“ sind.
- Fix: Cache-Invalidation als Deploy-Schritt (CDN purge nur wenn nötig).
9) Timeouts, Limits, Last: es bricht nur unter echten Bedingungen
Prod hat Timeouts am Proxy, DB-Pool-Limits, Memory-Limits, Rate Limits. Lokal läuft ein Request auch mal 20 Sekunden „weil egal“.
- Fix: Timeouts bewusst setzen und messen (Server, Proxy, Client).
- Fix: Last-Tests wenigstens light (kritische Endpoints), bevor du live gehst.
10) Kein Logging/Monitoring: du siehst den Fehler nicht
Wenn du in Prod nur „500“ siehst und keine Logs/Traces hast, ist Debugging Glücksspiel. Und jeder Hotfix macht’s schlimmer.
- Fix: Strukturierte Logs (Request-ID), Error-Tracking, Healthchecks.
- Fix: „Was ist normal?“ definieren: Alarm, wenn Login-Fails explodieren, 5xx steigen, Latenz hochgeht.
Symptom → Ursache → Quick Fix
| Symptom in Prod | Wahrscheinlichste Ursache | Schneller Fix |
|---|---|---|
| Login/OAuth geht lokal, Prod nicht | Redirect URI/Domain/Secrets falsch | ENV/Secrets prüfen, Provider-Settings matchen |
| CSS/JS „kaputt“ nach Deploy | Cache/Asset-Versionierung fehlt | Hashed Assets + Cache-Header sauber |
| API Calls scheitern nur in Prod | CORS/CSRF/Origin-Setup | CORS strikt konfigurieren, CSRF sauber |
| Redirect Loop / HTTP↔HTTPS | Reverse Proxy Headers/HTTPS Detection | X-Forwarded-* korrekt, Proxy-Trust einstellen |
| Fehler nur mit echten Daten | DB Schema drift / Collation / Edge Cases | Migrations erzwingen, Staging realitätsnah |
| Es dauert ewig / Timeouts | Proxy Timeout/DB Pool/Last | Timeouts harmonisieren, Pooling prüfen |
So setzt du’s um
1) Der 30-Minuten-Plan für dein nächstes Release
- Config Schema: Liste aller ENV-Keys + Pflicht/Default + Beispielwerte.
- Build in CI: Image/Artefakt bauen, testen, signieren/taggen.
- Staging Deploy: gleiche Proxy-Kette, gleiche DB-Version, gleiche Caches.
- Smoke Tests: Login, wichtigste API, Payment/Lead-Flow, Uploads.
- Observability: Request-ID, Logs, Error-Tracking aktiv. Dann Prod.
2) Mini-Use-Case: „Staging wie Prod“ (ohne Overkill)
- Gleiche Domains/Subdomains-Struktur (mindestens gleiche Origin-Trennung).
- Gleicher Reverse Proxy (Nginx/Traefik-Konfig spiegeln).
- Gleiche Caching-Schicht (CDN optional, aber zumindest gleiche Cache-Header-Logik).
- Gleiche DB-Version + Migrations-Pipeline.
Typische Fehler & wie du sie vermeidest
- Fehler: „Lokal getestet“ gilt als Done. Fix: Staging mit Prod-Parität + Smoke Tests.
- Fehler: Build in Prod. Fix: CI baut, Prod deployt nur Artefakte.
- Fehler: Manuelle Migrations. Fix: Migrations als Deploy-Step (kontrolliert, versioniert).
- Fehler: Debug via „print_r“ und Hoffnung. Fix: strukturierte Logs + Error-Tracking.
- Fehler: „Cache ist egal“. Fix: Asset-Hashing + Cache-Strategie explizit.
Fazit: Prod ist anders – aber du kannst es planbar machen
Du wirst Prod nie komplett identisch zu lokal machen. Aber du kannst die Unterschiede klein und sichtbar machen: Parität, reproduzierbare Builds, Staging, Logs. Dann wird aus „Release-Lotto“ ein Prozess.
Nächster Schritt: Bau dir eine Release-Checkliste (ENV Schema, Build in CI, Staging Smoke, Logs). Wenn du das einmal sauber hast, wirst du nie wieder freiwillig „läuft lokal“ als Argument akzeptieren.
FAQ
Weil Prod andere Bedingungen hat: ENV/Secrets, Reverse Proxy/TLS, echte Daten, andere Rechte, Caches, Limits. Ohne Dev/Prod-Parität testest du lokal nicht das echte System.
Config Drift heißt: Umgebungen unterscheiden sich schleichend (ENV, Proxy, DB-Versionen, Caches). Verhindern: Config über ENV, Staging wie Prod, Infrastruktur versioniert (IaC) und Deploys reproduzierbar.
Weil Protokoll/Host/IP anders ankommen (TLS-Termination, Forwarded Headers). Wenn deine App HTTPS falsch erkennt, entstehen Redirect-Loops oder falsche Callback-URLs. Lösung: Proxy-Header korrekt konfigurieren und im Framework „trusted proxy“ richtig setzen.
Weil Frontend und API in Prod oft auf unterschiedlichen Origins laufen. Lokal ist es häufig „alles auf localhost“. Fix: CORS-Origins explizit erlauben, keine Wildcards mit Credentials, und CSRF bei cookie-basierten Sessions sauber lösen.
Reproduzierbare Umgebung (Container oder klare Version-Pins), Build in CI, Staging wie Prod, und eine feste Release-Checkliste. Dann zählt nicht „mein Laptop“, sondern „die Pipeline“.
Wenn dein Projekt mehr ist als eine statische Seite: ja, mindestens ein „Pre-Prod“, das die Proxy/DB/Cache-Realität abbildet. Sonst ist Prod dein Testsystem. Und das endet meist in Tränen.