"Unser MVP funktioniert, aber es skaliert nicht."
Das klassische Scale-up-Problem. Die gute Nachricht: Ein Rewrite ist fast nie nötig. Die schlechte: Es braucht Strategie.
Das MVP-zu-Scale-Dilemma
Was MVPs richtig machen:
- Schnell gebaut
- Validiert Product-Market-Fit
- Minimale Features, maximaler Fokus
Was MVPs falsch machen (aus Scale-Perspektive):
- "Quick & Dirty"-Code
- Monolith-Architektur (alles in einer Codebase)
- Keine Tests
- Keine Performance-Optimierung
- Hard-coded Configs
- Manuelle Deployments
Das ist OK für MVPs. Aber nicht für Production at Scale.
Meine Erfahrung: Die teuersten Fehler entstehen durch "Big Bang"-Rewrites. Ein SaaS-Startup wollte seinen erfolgreichen MVP komplett neu bauen, weil der Code "hässlich" war. Nach 9 Monaten hatten sie weder das neue System noch neue Features. Mit dem Strangler-Fig-Pattern hätten sie iterativ migrieren können - und währenddessen weiter liefern.
Die 4 Phasen der Skalierung
Phase 1: MVP (0-1.000 User)
Ziel: Product-Market-Fit finden.
Tech-Fokus:
- Schnelligkeit > Qualität
- Monolith ist OK
- Manuelles Deployment ist OK
- No-Code/Low-Code ist OK
Architektur:
[Web-App] → [Database]
↓
[Background-Jobs (optional)]
Simple. Funktioniert.
Phase 2: Growing (1.000-10.000 User)
Ziel: Stabil laufen, erste Performance-Probleme lösen.
Tech-Fokus:
- CI/CD einführen
- Monitoring & Error-Tracking
- Database-Optimierung
- Erste Tests (zumindest Critical Path)
Architektur:
[Load-Balancer]
↓
[2-3 App-Server] → [Database (mit Replikation)]
↓
[Background-Jobs]
Horizontal skalierbar, aber noch Monolith.
Phase 3: Scaling (10.000-100.000 User)
Ziel: Performance + Zuverlässigkeit.
Tech-Fokus:
- Database-Sharding oder Migration zu skalierbarer DB
- Caching (Redis, CDN)
- Service-Extraktion (Monolith →Services für kritische Teile)
- Async-Processing (Queues)
Architektur:
[CDN] → [Load-Balancer]
↓
[API-Gateway]
↓
[Core-Service] ┬─→ [Auth-Service]
├─→ [Payment-Service]
└─→ [Notification-Service]
↓
[Cache] + [Database-Cluster] + [Message-Queue]
Hybrid: Core-Monolith + kritische Services ausgelagert.
Phase 4: Scale (100.000+ User)
Ziel: Multi-Region, High-Availability, Sub-Second-Latency.
Tech-Fokus:
- Full Microservices (optional!)
- Multi-Region-Deployment
- Advanced Caching & CDN
- Event-Driven-Architecture
Architektur: Komplex, team- und domänenabhängig.
Wichtig: Viele erfolgreiche Companies bleiben bei Phase 3 (Hybrid). das ist OK!
Der Strangler-Fig-Pattern: Iterativ migrieren
Problem: "Wir migrieren alles auf einmal" →12 Monate ohne Features, hohes Risiko.
Lösung: Strangler Fig (wie die Würgefeige im Dschungel).
Wie es funktioniert:
1. Routing-Layer einführen
User-Request
↓
[Router/API-Gateway]
↓
├─→ Alt-System (Monolith) für 90% der Requests
└─→ Neu-Service für 10% der Requests
2. Feature für Feature migrieren
Woche 1: Authentication → neuer Service
→ Router sendet /auth/* an neuen Service
→ Rest geht an Monolith
Woche 4: Payment → neuer Service
→ Router sendet /payment/* an neuen Service
Woche 8: Notifications → neuer Service
→ ..
Nach N Wochen: Monolith ist leer, nur noch neue Services
3. Alt-System abschalten
Wenn Monolith keine Requests mehr bekommt →abschalten.
Vorteile:
- Inkrementell (jede Woche ist ein Fortschritt)
- Risiko-Management (Rollback jederzeit möglich)
- Team liefert weiter Features (nicht 12 Monate "nur Migration")
Die 7 kritischen Refactorings
1. Hardcoded Configs →Environment-Variables
Vorher:
python
DATABASE_URL = "postgres://localhost/mydb"
API_KEY = "sk-abc123.." # ❌
Nachher:
python
import os
DATABASE_URL = os.environ.get("DATABASE_URL")
API_KEY = os.environ.get("API_KEY")
Warum: Multi-Environment (Dev, Staging, Production), Secret-Management.
Investment: 1-2 Tage.
2. Manuelle Deployments →CI/CD
Vorher:
bash
ssh server
git pull
systemctl restart app
Nachher:
yaml
on:
push:
branches: [main]
steps:
- run: tests
- deploy: production (if tests pass)
Warum: Weniger Fehler, schneller, automatisiert.
Investment: 1 Woche Setup.
3. Keine Tests →Critical-Path-Tests
Nicht: 100% Test-Coverage sofort.
Sondern: Tests für kritische Flows.
Kritische Flows:
- User-Registrierung
- Payment
- Core-Features (die, die Geld verdienen)
Investment: 1-2 Wochen (parallel zu Features).
4. Synchrones Processing →Async (Queues)
Problem:
python
def register(user):
create_user(user)
send_welcome_email(user) # dauert 2 Sekunden
notify_admin(user) # dauert 1 Sekunde
return "Success"
Lösung:
python
def register(user):
create_user(user)
queue.enqueue(send_welcome_email, user)
queue.enqueue(notify_admin, user)
return "Success" # sofort
Warum: Bessere UX, Skalierbarkeit.
Investment: 2-4 Tage (Queue-Setup + Refactor).
5. Alles in der App →Caching
Problem: Jede Request holt alles aus der DB.
Lösung:
python
def get_user(user_id):
return db.query("SELECT * FROM users WHERE id = ?", user_id)
def get_user(user_id):
cached = cache.get(f"user:{user_id}")
if cached:
return cached
user = db.query("SELECT * FROM users WHERE id = ?", user_id)
cache.set(f"user:{user_id}", user, ttl=300) # 5 Min
return user
Warum: 10-100x schneller, weniger DB-Load.
Investment: 1 Woche (Redis-Setup + Refactor häufiger Queries).
6. Monolithische DB →Schema-Optimierung
Bevor Sie über Sharding nachdenken:
- Indizes (die meisten Performance-Probleme sind fehlende Indizes!)
- Query-Optimierung (N+1-Queries eliminieren)
- Connection-Pooling
- Read-Replicas (Reads auf Replicas, Writes auf Primary)
Investment: 1-2 Wochen (Query-Analyse + Optimierung).
Ergebnis: Oft 10-50x Performance-Verbesserung.
7. Frontend-Monolith →Code-Splitting
Problem: 5 MB JavaScript-Bundle, lädt 10 Sekunden.
Lösung:
- Code-Splitting (nur laden, was nötig ist)
- Lazy-Loading für Routes
- Tree-Shaking (tote Code entfernen)
- CDN für Assets
Investment: 1 Woche (Build-Optimierung).
Ergebnis: 80% kleinere Bundles, 5x schnellerer Load.
Wann ist ein Rewrite gerechtfertigt?
Fast nie. Aber manchmal:
Rewrite, wenn:
1. Fundamentale Architektur-Fehler, die nicht zu fixen sind
Beispiel: Gesamtes System ist Single-Threaded, aber muss Echtzeit sein.
2. Technologie ist wirklich tot
Beispiel: Flash, Silverlight, Python 2 nach 2020.
3. Business-Model-Pivot macht System obsolet
Beispiel: Von B2C zu B2B-Enterprise →völlig andere Anforderungen.
4. Compliance/Security erfordert es
Beispiel: Healthcare/Finance, alte Codebase ist nicht audit-bar.
KEIN Rewrite, wenn:
1. "Der Code ist hässlich"
→Refactoring, kein Rewrite.2. "Neue Technologie ist cooler"
→Nicht Ihr Problem. Funktioniert es? Dann OK.3. "Würde ich heute anders machen"
→Natürlich. Aber das rechtfertigt keinen Rewrite.4. "Performance-Probleme"
→Fast immer mit Optimierung lösbar.Die Skalierungs-Roadmap (praktisch)
Monate 1-2: Foundation
Ziel: Stabilität + Observability
- CI/CD-Pipeline
- Monitoring (Errors, Performance)
- Environment-Variables (keine Hardcoded-Secrets)
Monate 3-4: Performance Quick Wins
Ziel: 2-5x schneller
- Caching (Redis)
- Database-Indizes + Query-Optimierung
- CDN für statische Assets
Monate 5-8: Architektur-Evolution
Ziel: Services-Extraktion (Strangler Fig)
- API-Gateway/Router
- 1. Service extrahieren (Auth, Payment, etc.)
- Async-Processing (Queues)
Monate 9-12: Scale-Ready
Ziel: Multi-Instance, High-Availability
- Load-Balancing
- Database-Replikation
- Horizontal-Scaling-Tests
Nach 12 Monaten: System ist skalierbar, ohne kompletten Rewrite.
Die häufigsten Fehler
Fehler 1: "Big Bang"-Migration
Symptom: "Wir bauen alles neu, dann switchen wir um."
Resultat: 12 Monate, keine Features, hohes Risiko.
Fix: Inkrementell (Strangler Fig).
Fehler 2: Zu früh zu komplex
Symptom: Bei 1.000 Usern schon Microservices.
Resultat: Overhead, Komplexität, langsamer.
Fix: Scale when you need to, not before.
Fehler 3: Performance-Probleme mit Architektur lösen
Symptom: "Unser Monolith ist langsam, wir brauchen Microservices."
Realität: Fehlende Indizes, N+1-Queries, kein Caching.
Fix: Profiling + Optimierung vor Architektur-Änderungen.
Fehler 4: Dokumentation vergessen
Symptom: Keiner weiß mehr, wie das Alt-System funktioniert.
Resultat: Migration dauert 3x länger.
Fix: Dokumentieren während der Migration (Architecture Decision Records).
Die Entscheidungsmatrix
| Situation | Lösung | Investment | Nutzen |
|---|---|---|---|
| Langsame Requests | Caching + DB-Optimierung | 1-2 Wochen | 10-100x schneller |
| Deployments sind manuell | CI/CD | 1 Woche | Weniger Fehler, 10x schneller |
| Keine Tests | Critical-Path-Tests | 2 Wochen | Confidence, weniger Bugs |
| Monolith zu groß | Service-Extraktion (Strangler) | 2-4 Wochen/Service | Skalierbarkeit, Team-Autonomie |
| User wartet lange | Async-Processing (Queues) | 1 Woche | Bessere UX, Skalierbarkeit |
| Kompletter Rewrite? | ❌ Nur in Ausnahmefällen | 6-12 Monate | Oft nicht gerechtfertigt |
Fazit: Evolution, nicht Revolution
MVPs sind nicht "schlecht gebaut". Sie sind für eine andere Phase gebaut.
Die Frage ist nicht: "Rewrite oder nicht?"
Sondern: "Wie migrieren wir iterativ, ohne das Geschäft zu stoppen?"
Die Antwort: Strangler Fig, inkrementelle Refactorings, und Pragmatismus.
Funktioniert es? Liefert es Value? Dann ist es gut genug.
Bis es das nicht mehr ist. Dann anpassen. Nicht vorher.
