Gerçek Dünya Mimarileri — Mikroservis, Monorepo, Hybrid
Docker kursumuzun son dersine geldik! Şu ana kadar Docker'ın tüm temellerini öğrendik — container'lar, image'lar, Compose, güvenlik, orchestration, CI/CD, monitoring, troubleshooting. Şimdi hepsini bir araya koyma zamanı: gerçek dünyada Docker ile uygulamalar nasıl tasarlanır ve deploy edilir? Monolith mi, mikroservis mi, yoksa ikisinin karışımı mı? Bu derste farklı mimari yaklaşımları, avantajlarını, dezavantajlarını ve ne zaman hangisini seçmen gerektiğini öğreneceğiz.
Şehir planlaması gibi düşün. Küçük bir kasabada tek bir belediye binası her işi halleder — nüfus, imar, su, elektrik hepsi aynı çatı altında (monolith). Şehir büyüdükçe ayrı müdürlükler kurulur — her biri kendi binasında, kendi ekibiyle, kendi bütçesiyle çalışır ama hepsi koordineli (mikroservis). Bazı şehirlerse karma model uygular — kritik hizmetler merkezi, geri kalanı dağıtık (hybrid).
Docker dünyasında da aynı seçimi yaparsın. Uygulamanı nasıl yapılandıracağın, kaç container olacak, nasıl haberleşecekler, nasıl deploy edilecekler — bunlar mimari kararlar. Bu ders, gerçek dünyada kullanılan Docker mimarilerini, hangi durumda hangisinin uygun olduğunu ve production'da nasıl çalıştırılacağını anlatıyor.
Mimari Seçenekler — Karşılaştırma
| Mimari | Ne Zaman? | Karmaşıklık | Ölçekleme | Takım |
|---|---|---|---|---|
| Monolith | MVP, küçük proje | Düşük | Tamamını ölçekle | 1-5 kişi |
| Modüler Monolith | Orta proje | Orta | Tamamını ölçekle | 3-10 kişi |
| Mikroservis | Büyük, karmaşık proje | Yüksek | Bağımsız ölçekle | 10+ kişi |
| Monorepo + Mikroservis | Büyük ekip, ortak kod | Yüksek | Bağımsız ölçekle | 10+ kişi |
| Hybrid | Geçiş dönemleri | Orta-Yüksek | Kısmen bağımsız | Değişken |
Mimari 1: Monolith — Tek Container
Tüm uygulama tek bir container'da çalışır. Basit, anlaşılır, deploy kolay.
Ne Zaman Uygun?
Startup / MVP — hızlı çıkmak istiyorsun
Küçük ekip (1-5 kişi)
Düşük trafik
Domain henüz oturmamış (sınırlar belli değil)
Mimari
Internet → Nginx (Reverse Proxy + SSL)
│
▼
App Container (API + Business Logic + Cron Jobs)
│
┌────┴────┐
▼ ▼
PostgreSQL RedisDocker Compose
# docker-compose.yml — Monolith
services:
nginx:
image: nginx:1.25-alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/ssl:/etc/nginx/ssl:ro
- static-files:/var/www/static:ro
depends_on:
app:
condition: service_healthy
restart: unless-stopped
deploy:
resources:
limits:
memory: 128M
app:
build:
context: .
target: production
expose:
- "3000"
environment:
NODE_ENV: production
DATABASE_URL: postgres://${DB_USER}:${DB_PASS}@db:5432/${DB_NAME}
REDIS_URL: redis://redis:6379
SESSION_SECRET: ${SESSION_SECRET}
volumes:
- static-files:/app/public/static
- uploads:/app/uploads
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:3000/health"]
interval: 30s
timeout: 5s
retries: 3
restart: unless-stopped
deploy:
resources:
limits:
memory: 1G
cpus: "2"
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASS}
POSTGRES_DB: ${DB_NAME}
volumes:
- pgdata:/var/lib/postgresql/data
- ./db/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER}"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
deploy:
resources:
limits:
memory: 512M
redis:
image: redis:7-alpine
command: >
redis-server
--maxmemory 128mb
--maxmemory-policy allkeys-lru
--requirepass ${REDIS_PASS}
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "-a", "${REDIS_PASS}", "ping"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
deploy:
resources:
limits:
memory: 192M
# Cron jobs — aynı image, farklı command
cron:
build:
context: .
target: production
command: ["node", "dist/cron.js"]
environment:
NODE_ENV: production
DATABASE_URL: postgres://${DB_USER}:${DB_PASS}@db:5432/${DB_NAME}
REDIS_URL: redis://redis:6379
depends_on:
db:
condition: service_healthy
restart: unless-stopped
deploy:
resources:
limits:
memory: 256M
volumes:
pgdata:
redis-data:
static-files:
uploads:Nginx Konfigürasyonu
# nginx/nginx.conf
upstream app {
server app:3000;
}
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
# Static files — Nginx'ten doğrudan serv et
location /static/ {
alias /var/www/static/;
expires 30d;
add_header Cache-Control "public, immutable";
}
# API istekleri — App'e proxy et
location / {
proxy_pass http://app;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket desteği
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# Upload limit
client_max_body_size 10M;
}Mimari 2: Mikroservis — Bağımsız Servisler
Her servis bağımsız olarak geliştirilir, deploy edilir, ölçeklenir. Kendi veritabanına sahiptir (database per service).
Ne Zaman Uygun?
Büyük ekip (10+ kişi), birden fazla takım
Farklı ölçekleme ihtiyaçları (user servisi az, payment servisi çok)
Farklı teknoloji gereksinimleri (user: Node.js, ML: Python)
Bağımsız deploy gereksinimi
Mimari
Internet → API Gateway (Traefik)
│
┌────┼────────────────────┐
▼ ▼ ▼
User Order Payment
Service Service Service
│ │ │
▼ ▼ ▼
User DB Order DB Payment DB
(Postgres) (Postgres) (Postgres)
│
▼
Message Queue ←── Notification Service → Email/SMS
(Redis)Docker Compose — Mikroservis
# docker-compose.yml — Mikroservis
services:
# === API Gateway ===
traefik:
image: traefik:v3.0
command:
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
- "--certificatesresolvers.letsencrypt.acme.email=admin@example.com"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
- "--api.dashboard=true"
- "--metrics.prometheus=true"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- letsencrypt:/letsencrypt
networks:
- traefik-public
restart: unless-stopped
# === User Service ===
user-service:
build: ./services/user
labels:
- "traefik.enable=true"
- "traefik.http.routers.user.rule=PathPrefix(`/api/users`) || PathPrefix(`/api/auth`)"
- "traefik.http.routers.user.tls.certresolver=letsencrypt"
- "traefik.http.services.user.loadbalancer.server.port=3000"
environment:
DATABASE_URL: postgres://user_svc:${USER_DB_PASS}@user-db:5432/users
REDIS_URL: redis://redis:6379
JWT_SECRET: ${JWT_SECRET}
networks:
- traefik-public
- user-net
- shared
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:3000/health"]
interval: 30s
retries: 3
restart: unless-stopped
deploy:
replicas: 2
resources:
limits:
memory: 256M
cpus: "0.5"
user-db:
image: postgres:16-alpine
environment:
POSTGRES_USER: user_svc
POSTGRES_PASSWORD: ${USER_DB_PASS}
POSTGRES_DB: users
volumes:
- user-db-data:/var/lib/postgresql/data
networks:
- user-net
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user_svc"]
interval: 10s
retries: 5
restart: unless-stopped
# === Order Service ===
order-service:
build: ./services/order
labels:
- "traefik.enable=true"
- "traefik.http.routers.order.rule=PathPrefix(`/api/orders`)"
- "traefik.http.routers.order.tls.certresolver=letsencrypt"
- "traefik.http.services.order.loadbalancer.server.port=3000"
environment:
DATABASE_URL: postgres://order_svc:${ORDER_DB_PASS}@order-db:5432/orders
REDIS_URL: redis://redis:6379
USER_SERVICE_URL: http://user-service:3000
PAYMENT_SERVICE_URL: http://payment-service:3000
networks:
- traefik-public
- order-net
- shared
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:3000/health"]
interval: 30s
retries: 3
restart: unless-stopped
deploy:
replicas: 2
resources:
limits:
memory: 256M
order-db:
image: postgres:16-alpine
environment:
POSTGRES_USER: order_svc
POSTGRES_PASSWORD: ${ORDER_DB_PASS}
POSTGRES_DB: orders
volumes:
- order-db-data:/var/lib/postgresql/data
networks:
- order-net
restart: unless-stopped
# === Payment Service ===
payment-service:
build: ./services/payment
labels:
- "traefik.enable=true"
- "traefik.http.routers.payment.rule=PathPrefix(`/api/payments`)"
- "traefik.http.routers.payment.tls.certresolver=letsencrypt"
- "traefik.http.services.payment.loadbalancer.server.port=3000"
environment:
DATABASE_URL: postgres://pay_svc:${PAY_DB_PASS}@payment-db:5432/payments
STRIPE_SECRET_KEY: ${STRIPE_SECRET_KEY}
REDIS_URL: redis://redis:6379
networks:
- traefik-public
- payment-net
- shared
restart: unless-stopped
deploy:
replicas: 1
resources:
limits:
memory: 256M
payment-db:
image: postgres:16-alpine
environment:
POSTGRES_USER: pay_svc
POSTGRES_PASSWORD: ${PAY_DB_PASS}
POSTGRES_DB: payments
volumes:
- payment-db-data:/var/lib/postgresql/data
networks:
- payment-net
restart: unless-stopped
# === Notification Service (Event-driven) ===
notification-service:
build: ./services/notification
environment:
REDIS_URL: redis://redis:6379
SMTP_HOST: ${SMTP_HOST}
SMTP_USER: ${SMTP_USER}
SMTP_PASS: ${SMTP_PASS}
networks:
- shared
restart: unless-stopped
deploy:
replicas: 1
resources:
limits:
memory: 128M
# === Shared Infrastructure ===
redis:
image: redis:7-alpine
command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
volumes:
- redis-data:/data
networks:
- shared
restart: unless-stopped
volumes:
letsencrypt:
user-db-data:
order-db-data:
payment-db-data:
redis-data:
networks:
traefik-public:
driver: bridge
user-net:
internal: true # Dış erişim yok — sadece user-service ve user-db
order-net:
internal: true
payment-net:
internal: true
shared:
driver: bridge # Servisler arası iletişim (Redis, inter-service calls)Dizin Yapısı
project/
├── docker-compose.yml
├── docker-compose.override.yml # Geliştirme override'ları
├── .env
├── services/
│ ├── user/
│ │ ├── Dockerfile
│ │ ├── package.json
│ │ ├── src/
│ │ └── tests/
│ ├── order/
│ │ ├── Dockerfile
│ │ ├── package.json
│ │ ├── src/
│ │ └── tests/
│ ├── payment/
│ │ ├── Dockerfile
│ │ └── ...
│ └── notification/
│ ├── Dockerfile
│ └── ...
├── nginx/
├── monitoring/
└── scripts/Network İzolasyonu — Neden Önemli?
traefik-public: Traefik + tüm servisler (dış erişim)
user-net: user-service ↔ user-db (internal)
order-net: order-service ↔ order-db (internal)
payment-net: payment-service ↔ payment-db (internal)
shared: Servisler arası iletişim (Redis)
⚠️ payment-db'ye sadece payment-service erişebilir
user-db'ye sadece user-service erişebilir
Güvenlik: bir servis hack'lense diğerinin DB'sine erişemezMimari 3: Monorepo — Tek Repo, Çoklu Servis
Tüm servisler tek bir Git repo'sunda, ama ayrı Docker image'lar olarak build ve deploy edilir.
Ne Zaman Uygun?
Ortak kod paylaşımı çok (shared libraries)
Atomic değişiklikler gerekli (birden fazla servisi etkileyen değişiklik)
CI/CD pipeline'ı merkezi yönetmek istiyorsun
Küçük-orta takım ama mikroservis mimarisi
Dizin Yapısı
monorepo/
├── packages/
│ ├── shared/ # Ortak kütüphane
│ │ ├── src/
│ │ │ ├── auth.ts
│ │ │ ├── logger.ts
│ │ │ └── database.ts
│ │ └── package.json
│ ├── user-service/
│ │ ├── Dockerfile
│ │ ├── src/
│ │ └── package.json # depends on @myapp/shared
│ ├── order-service/
│ │ ├── Dockerfile
│ │ ├── src/
│ │ └── package.json
│ └── payment-service/
│ ├── Dockerfile
│ ├── src/
│ └── package.json
├── docker-compose.yml
├── docker-compose.dev.yml
├── turbo.json # Turborepo config
├── pnpm-workspace.yaml
└── package.jsonMonorepo Dockerfile
# packages/user-service/Dockerfile
FROM node:20-alpine AS base
RUN corepack enable
FROM base AS deps
WORKDIR /app
# Root package files
COPY package.json pnpm-workspace.yaml pnpm-lock.yaml turbo.json ./
# Service + shared packages
COPY packages/user-service/package.json ./packages/user-service/
COPY packages/shared/package.json ./packages/shared/
RUN pnpm install --frozen-lockfile
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY --from=deps /app/packages/user-service/node_modules ./packages/user-service/node_modules
COPY --from=deps /app/packages/shared/node_modules ./packages/shared/node_modules
# Tüm kaynak kodu kopyala
COPY packages/shared ./packages/shared
COPY packages/user-service ./packages/user-service
COPY package.json pnpm-workspace.yaml turbo.json ./
# Build
RUN pnpm --filter @myapp/user-service build
FROM base AS production
WORKDIR /app
RUN addgroup -S app && adduser -S app -G app
COPY --from=builder /app/packages/user-service/dist ./dist
COPY --from=builder /app/packages/user-service/node_modules ./node_modules
COPY --from=builder /app/packages/user-service/package.json ./
USER app
EXPOSE 3000
CMD ["node", "dist/index.js"]Monorepo CI/CD — Akıllı Build
# .github/workflows/monorepo-ci.yml
name: Monorepo CI/CD
on:
push:
branches: [main]
jobs:
detect-changes:
runs-on: ubuntu-latest
outputs:
user-service: ${{ steps.changes.outputs.user-service }}
order-service: ${{ steps.changes.outputs.order-service }}
shared: ${{ steps.changes.outputs.shared }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: changes
with:
filters: |
user-service:
- 'packages/user-service/**'
- 'packages/shared/**'
order-service:
- 'packages/order-service/**'
- 'packages/shared/**'
shared:
- 'packages/shared/**'
build-user-service:
needs: detect-changes
if: needs.detect-changes.outputs.user-service == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/build-push-action@v5
with:
context: .
file: packages/user-service/Dockerfile
push: true
tags: ghcr.io/myorg/user-service:${{ github.sha }}
build-order-service:
needs: detect-changes
if: needs.detect-changes.outputs.order-service == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/build-push-action@v5
with:
context: .
file: packages/order-service/Dockerfile
push: true
tags: ghcr.io/myorg/order-service:${{ github.sha }}Mimari 4: Hybrid — Monolith + Mikroservis
Mevcut monolith'i koruyarak, yeni özellikeri ayrı servis olarak eklersin. Strangler Fig Pattern.
Ne Zaman Uygun?
Mevcut monolith'i tamamen yeniden yazmak riskli/pahalı
Yeni özellikler farklı teknoloji gerektiriyor
Kademeli geçiş stratejisi
Mimari
Internet → API Gateway (Nginx / Traefik)
│
┌────┴──────────────────┐
▼ ▼
Legacy Monolith New Microservices
(PHP/Java/...) ├── Search Service (Elasticsearch)
│ ├── Notification Service (Node.js)
▼ └── ML/Recommendation (Python)
Monolith DB │
(MySQL) Service DBsDocker Compose — Hybrid
# docker-compose.yml — Hybrid
services:
# Mevcut monolith — containerize edilmiş
legacy-app:
build:
context: ./legacy
dockerfile: Dockerfile
labels:
- "traefik.enable=true"
- "traefik.http.routers.legacy.rule=PathPrefix(`/`)"
- "traefik.http.routers.legacy.priority=1" # Düşük öncelik (fallback)
- "traefik.http.services.legacy.loadbalancer.server.port=8080"
environment:
DB_HOST: legacy-db
DB_NAME: myapp
networks:
- traefik-public
- legacy-net
restart: unless-stopped
legacy-db:
image: mysql:8.0
volumes:
- legacy-db-data:/var/lib/mysql
networks:
- legacy-net
restart: unless-stopped
# Yeni servisler — modern stack
search-service:
build: ./services/search
labels:
- "traefik.enable=true"
- "traefik.http.routers.search.rule=PathPrefix(`/api/v2/search`)"
- "traefik.http.routers.search.priority=10" # Yüksek öncelik
- "traefik.http.services.search.loadbalancer.server.port=3000"
environment:
ELASTICSEARCH_URL: http://elasticsearch:9200
LEGACY_DB_URL: mysql://readonly:${RO_PASS}@legacy-db:3306/myapp
networks:
- traefik-public
- search-net
- legacy-net # Legacy DB'ye readonly erişim
restart: unless-stopped
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.12.0
environment:
- discovery.type=single-node
- xpack.security.enabled=false
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
volumes:
- es-data:/usr/share/elasticsearch/data
networks:
- search-net
restart: unless-stopped
notification-service:
build: ./services/notification
labels:
- "traefik.enable=true"
- "traefik.http.routers.notification.rule=PathPrefix(`/api/v2/notifications`)"
- "traefik.http.routers.notification.priority=10"
networks:
- traefik-public
- shared
restart: unless-stopped
# API Gateway
traefik:
image: traefik:v3.0
command:
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
ports:
- "80:80"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- traefik-public
restart: unless-stopped
volumes:
legacy-db-data:
es-data:
networks:
traefik-public:
legacy-net:
internal: true
search-net:
internal: true
shared:💡 İpucu: Traefik'te priority ile yeni servisler öncelikli olur. /api/v2/search yeni servise, geri kalan her şey legacy'ye gider. Böylece kademeli geçiş yaparsın.
Servisler Arası İletişim Desenleri
1. Senkron — HTTP/REST
// order-service → user-service HTTP çağrısı
const response = await fetch('http://user-service:3000/api/users/123');
const user = await response.json();2. Asenkron — Message Queue (Redis/RabbitMQ)
// order-service → event yayınla
await redis.publish('order.created', JSON.stringify({
orderId: 'ord-123',
userId: 'usr-456',
total: 99.99
}));
// notification-service → event dinle
redis.subscribe('order.created', (message) => {
const order = JSON.parse(message);
sendEmail(order.userId, 'Siparişiniz alındı!');
});3. API Gateway Pattern
# Traefik routing kuralları
labels:
# Path-based routing
- "traefik.http.routers.user.rule=PathPrefix(`/api/users`)"
- "traefik.http.routers.order.rule=PathPrefix(`/api/orders`)"
# Header-based routing
- "traefik.http.routers.v2.rule=PathPrefix(`/api`) && HeadersRegexp(`X-API-Version`, `2`)"
# Rate limiting
- "traefik.http.middlewares.rate-limit.ratelimit.average=100"
- "traefik.http.middlewares.rate-limit.ratelimit.burst=50"
# Circuit breaker
- "traefik.http.middlewares.cb.circuitbreaker.expression=LatencyAtQuantileMS(50.0) > 100"Anti-Pattern'ler — Yapma!
1. Dağıtık Monolith
❌ Tüm servisler birbirine bağımlı — birini deploy etmeden diğerini deploy edemezsin
❌ Senkron çağrı zincirleri: A → B → C → D (biri çökerse hepsi çöker)
❌ Paylaşımlı veritabanı (tüm servisler aynı DB'yi kullanıyor)
Çözüm:
✅ Database per service
✅ Asenkron iletişim (event-driven)
✅ Circuit breaker pattern
✅ Bağımsız deploy edilebilir servisler2. Nano-Service
❌ Her fonksiyon ayrı servis — 50 servis, 50 container, 50 deployment
❌ Operasyonel yük çok yüksek, fayda düşük
Çözüm:
✅ Domain-driven design ile sınırları belirle
✅ Bir serviste 3-5 ilişkili endpoint olması normal
✅ Çok küçük servisler birleştir3. Docker Compose ile Production Mikroservis
❌ 20 servis, tek sunucu, Docker Compose
→ Tek sunucu çökerse her şey çöker
→ Ölçekleme yok
→ Rolling update yok
Çözüm:
✅ 5+ servis varsa Kubernetes veya Docker Swarm kullan
✅ Docker Compose sadece geliştirme ve küçük production içinMimari Karar Ağacı
Proje başlangıcı?
│
├── Evet → Monolith + Docker Compose
│ (hızlı başla, domain otur, sonra böl)
│
└── Hayır → Trafik ne kadar?
│
├── Düşük-Orta → Modüler Monolith
│ (namespace ile modüller ayır)
│
└── Yüksek → Ekip büyüklüğü?
│
├── <10 kişi → Monorepo + 3-5 servis
│ (Turborepo + Docker Compose/Swarm)
│
└── 10+ kişi → Mikroservis + Kubernetes
(Helm/ArgoCD + managed K8s)Best Practices
✅ Yap:
Monolith ile başla — erken optimizasyon yapma, domain'i önce anla
Network segmentation uygula — her servisin DB'si kendi network'ünde
Health check her container'a ekle
Shared nothing prensibi — servisler veritabanı paylaşmasın
API versioning kullan —
/api/v1/,/api/v2/Circuit breaker ve retry pattern'leri uygula
Event-driven iletişimi tercih et (asenkron, loosely coupled)
Monorepo'da değişiklik tespiti yap — sadece değişen servisleri build et
❌ Yapma:
Küçük proje için mikroservis mimarisi seçme — overkill
Tüm servisler arasında senkron HTTP çağrı zinciri kurma
Paylaşımlı veritabanı ile "mikroservis" yapma — dağıtık monolith olur
20 servisi Docker Compose ile production'a çıkarma — orchestrator kullan
Her CRUD endpoint'i ayrı servis yapma — nano-service anti-pattern'i
Legacy sistemi bir gecede yeniden yazma — strangler fig ile kademeli geç
Özet
Monolith: Tek container, basit, hızlı başlangıç — MVP ve küçük projeler için ideal
Mikroservis: Bağımsız servisler, bağımsız deploy, bağımsız ölçekleme — büyük ekipler için
Monorepo: Tek repo'da çoklu servis — ortak kod paylaşımı kolaylaştırır
Hybrid: Mevcut monolith + yeni mikroservisler — kademeli geçiş (strangler fig)
Network izolasyonu kritik — her servisin DB'si kendi internal network'ünde
API Gateway (Traefik/Nginx) dış trafiği yönetir, routing, rate limiting, SSL
Monolith ile başla, domain oturunca ve ekip büyüyünce mikroservise geç
Anti-pattern'lerden kaçın: dağıtık monolith, nano-service, paylaşımlı DB
AI Asistan
Sorularını yanıtlamaya hazır