Eylül 19 2026

Legacy Sistemlerde Modernizasyon: ‘Strangler Fig’ Modeli ile Göç Stratejileri

Bir sabah uyandığınızda yönetimin “Artık bu monolit bizi taşımıyor, her şeyi sıfırdan yazıyoruz!” dediğini duyduysanız, soğuk terler dökmüşsünüzdür. Legacy bir altyapıyı bir gecede rafa kaldırmaya çalışmak (namıdiğer Big Bang rewrite), havacılıkta uçak havadayken motor değiştirmeye değil, uçağı havada patlatıp parçalarından jet yapmaya benzer. Başarılı bir modernizasyon süreci için ihtiyacımız olan şey cesur bir intihar girişimi değil, kontrollü bir yazılım mimarisi evrimidir. İşte tam bu noktada, monoliti boğarak öldüren mikroservis dönüşüm yaklaşımı: Strangler Fig (Boğucu İncir) paterni devreye giriyor.

Martin Fowler’ın Avustralya’daki asalak incir ağaçlarından esinlenerek adlandırdığı bu model, yeni sistemi eski sistemin etrafına adım adım sarıp, zamanla eskiyi işlevsiz bırakarak çürütme prensibine dayanır. Peki bu teoriyi prodüksiyonda 500k RPM trafik altında çalışan bir Kubernetes kümesinde nasıl hayata geçiririz? Gelin, lafı uzatmadan işin mutfağına inelim.

1. Keşif ve Sınırların Çizilmesi: Nereden Başlamalı?

Strangler Fig yaklaşımında yapılan en büyük hata, doğrudan sistemin kalbi sayılan domain’e (örneğin e-ticaretteki ödeme veya sipariş akışı) saldırmaktır. İlk adayınız şu üç kriteri sağlamalı:

  • Düşük Bağımlılık (Low Coupling): Monolitin veri tabanındaki 40 farklı tabloya JOIN atmayan bir context.
  • Yüksek Değer / Hızlı Kazanım: Hata yaptığınızda şirketi batırmayacak ama çalıştığında ekibe “bu iş oluyor” güvenini verecek bir modül (Örn: Bildirim servisi, PDF/Fatura oluşturucu, Statik içerik sunumu).
  • Net API Kontratı: Girdisi ve çıktısı belirgin olan işlevler.

Sınırları belirledikten sonra mimarinin en kritik bileşenini devreye alıyoruz: Interception (Yakalama) Katmanı.

2. Interception Katmanı: Akıllı Yönlendirme (Routing)

Strangler Fig modelinin kalbi API Gateway ya da Reverse Proxy katmanıdır. İstemciler (web, mobil, 3rd party API) asla monolitle mi yoksa yeni mikroservisle mi konuştuklarını bilmemelidir. Trafik önce bu katmana çarpar ve yönlendirme kurallarına göre hedefe dağıtılır.

Bu aşamada sadece path-based routing yetmez; feature flag’ler, canary dağıtımlar ve cookie/header bazlı yönlendirmeler gerekir. NGINX kullanarak bu katmanı nasıl kurabileceğimize bakalım:

# /etc/nginx/conf.d/strangler_router.conf

upstream legacy_monolith {
    server 10.0.1.10:8080 max_fails=3 fail_timeout=10s;
    keepalive 32;
}

upstream new_notification_service {
    server 10.0.2.20:3000 max_fails=2 fail_timeout=5s;
    keepalive 16;
}

# Feature flag kontrolü: Header veya Cookie bazlı canary
map $http_x_use_microservice $notification_backend {
    default legacy_monolith;
    "true"  new_notification_service;
}

server {
    listen 80;
    server_name api.sirket.internal;

    # Henüz dokunulmamış tüm trafik doğrudan monolite
    location / {
        proxy_pass http://legacy_monolith;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    # Strangled endpoint: Kademeli göç edilen servis
    location /api/v1/notifications {
        proxy_pass http://$notification_backend;
        proxy_set_header Host $host;
        proxy_set_header X-Request-ID $request_id;
        
        # Olası mikroservis çökmesinde monolite failover mekanizması
        proxy_next_upstream error timeout http_502 http_503;
        proxy_next_upstream_tries 2;
    }
}

Buradaki kritik detay proxy_next_upstream kullanımıdır. Yeni mikroservisiniz beklediğiniz yükü kaldıramaz veya 502/503 dönerse, istek anında monolite yönlendirilerek SLA ihlali önlenir. Tabii ki bu fallback state-mutating (POST/PUT/DELETE) isteklerde idempotentlik garantisi yoksa dikkatli kullanılmalıdır.

3. En Büyük Karın Ağrısı: Veri Bütünlüğü ve CDC (Change Data Capture)

İş mantığını ayırmak kolaydır; veri tabanını ayırmak ise tam bir mayın tarlasıdır. Legacy uygulamalarda genellikle tek bir devasa MySQL veya Oracle veri tabanı bulunur. Mikroservis mimarisinde ise her servisin kendi veri tabanı olmalıdır (Database-per-Service).

Bunu çözmek için kesinlikle monolit içinden “hem eski DB’ye yazayım hem yeni servisin DB’sine yazayım” (Dual Writing) gafletine düşmeyin. Ağ gecikmeleri, connection pool tükenmesi ve dağıtık transaction problemleri başınızı ağrıtır. Bunun yerine Change Data Capture (CDC) kullanarak veri akışını asenkron hale getirin.

Debezium ve Apache Kafka ikilisi, legacy veri tabanının transaction log’larını (binlog / redo log) dinleyerek olay bazlı (event-driven) veri aktarımı sağlar:

# Debezium MySQL Source Connector Konfigürasyonu (Kafka Connect REST API)
curl -i -X POST -H "Accept:application/json" -H "Content-Type:application/json" \
  http://kafka-connect.infra:8083/connectors/ \
  -d '{
    "name": "legacy-mysql-cdc-connector",
    "config": {
      "connector.class": "io.debezium.connector.mysql.MySqlConnector",
      "tasks.max": "1",
      "database.hostname": "legacy-db-primary.internal",
      "database.port": "3306",
      "database.user": "debezium_cdc",
      "database.password": "VaultGuardedSecret123!",
      "database.server.id": "184054",
      "database.server.name": "legacy_core",
      "database.include.list": "core_production",
      "table.include.list": "core_production.notifications,core_production.user_preferences",
      "database.history.kafka.bootstrap.servers": "kafka-cluster:9092",
      "database.history.kafka.topic": "schema-changes.legacy.core",
      "decimal.handling.mode": "double",
      "time.precision.mode": "connect"
    }
  }'

Bu yapı sayesinde, monolit eski tabloya yazmaya devam ederken Debezium bu değişiklikleri anında Kafka’ya fırlatır. Yeni mikroservisiniz de bu event’leri tüketerek (consume) kendi izole PostgreSQL veya MongoDB veritabanını besler (Eventual Consistency).

4. Trafik Kademelendirme: Shadowing (Dark Launching)

Yeni yazdığınız mikroservisi prodüksiyon trafiğiyle ilk kez karşılaştırmak istemezsiniz. Yük testleri sentetiktir; gerçek kullanıcı davranışlarını simüle edemez. Bu yüzden Traffic Shadowing (Trafik Aynalama) tekniğini kullanmalısınız.

Trafik Gateway katmanına geldiğinde hem monolite hem de mikroservise gönderilir. Monolitin cevabı kullanıcıya dönülürken, mikroservisin cevabı arka planda loglanır veya karşılaştırılır (semantic diffing). İstemci mikroservisten haberdar bile olmaz.

Kubernetes üzerinde Envoy tabanlı bir Ingress (örneğin Emissary-ingress veya doğrudan Envoy proxy) kullanıyorsanız, shadowing tanımı şu kadar basittir:

apiVersion: getambassador.io/v3alpha1
kind: Mapping
metadata:
  name: notification-shadow-mapping
  namespace: production
spec:
  hostname: api.sirket.internal
  prefix: /api/v1/notifications/send
  service: legacy-monolith-service.production:8080
  shadow: true
  shadow_service: new-notification-microservice.modern-apps:3000
  timeout_ms: 2500

Shadowing devredeyken neyi izlemelisiniz?

  • HTTP Status Kodu Farkları: Monolit 200 dönerken mikroservis 500 mü veriyor? Neden?
  • p99 ve p95 Latency: Yeni servis gerçekten hedeflenen performansı sunuyor mu?
  • Payload Uyuşmazlığı: Yanıt gövdeleri arasındaki farklar neler?

5. Monoliti Boğmak: Eski Kodu Temizlemek

Mikroservisiniz shadowing aşamasını başarıyla geçti, veri senkronizasyonu stabil, canary deployment ile trafiğin %100’ünü yeni servise aktardınız. Tebrikler, servisi göç ettiniz!

Ama işiniz bitmedi. Strangler Fig paterninin son ve en çok ihmal edilen adımı: Eski kodun monolit içinden sökülüp atılmasıdır.

Geliştiriciler genelde “ne olur ne olmaz, kod kalsın” diyerek eski methodları ve endpoint’leri monolitte bırakır. Bu durum, monoliti zamanla yaşayan bir zombi kod yığınına çevirir. Bir sonraki göç adımında bu zombiler ayağınıza dolanır.

Yapılacaklar net:

  1. Monolitteki eski endpoint’e bir log alert’i koyun (artık 0 istek alıyor olmalı).
  2. Monolit kod tabanından ilgili controller, service ve data access katmanlarını silin.
  3. CDC konfigürasyonundan o tabloyu çıkartın ve monolit veri tabanındaki eski tabloyu READ-ONLY moda alıp birkaç hafta sonra arşivleyin.

Özet ve SRE Çıkarımları

Bir legacy mimariyi modernize etmek yazılım mühendisliğinden çok bir cerrahi operasyondur. Strangler Fig yaklaşımı bu operasyonu lokal anestezi altında, hasta yürümeye devam ederken yapmanızı sağlar.

Bu yolculukta aklınızdan çıkarmamanız gereken altın kurallar şunlar:

  • Önce Gateway katmanını güçlendirin; yönlendirme kabiliyetiniz yoksa göçü yönetemezsiniz.
  • Veritabanı senkronizasyonunu CDC gibi asenkron ve güvenilir araçlarla çözün.
  • Prodüksiyon trafiğini aynalayarak (traffic mirroring) riskinizi sıfırlayın.
  • Göçü tamamlanan her parçadan sonra monolitteki ölü kodu acımadan temizleyin.

Bir sonraki sprint planlamasında masaya “Her şeyi sıfırdan yazalım” fikri gelirse, bu makaleyi Slack kanalına usulca bırakın ve monoliti boğmaya odaklanın.

Etiketler: , , ,
Copyright 20254541. All rights reserved.

Posted 19 Eylül 2026 by Kerem Danış in category "Genel