11.02.2026

SAGA Pattern Nedir? Dağıtık Transaction Rehberi

SAGA pattern ile mikroservislerde dağıtık transaction sorununu çözün: kompanzasyon, orkestrasyon vs koreografi ve örnek akışlar.

SAGA Pattern Nedir? Dağıtık Transaction Rehberi

Giriş

Mikroservislere geçince en çok can yakan sorulardan biri şudur: Birden fazla servis aynı iş adımına dahilken veriyi nasıl tutarlı tutacağım? Monolith’te tek DB transaction ile çözülen işler, dağıtık mimaride “yarım kaldı” durumlarını (sipariş alındı ama ödeme alınamadı gibi) çok daha sık üretir.

İşte bu noktada SAGA pattern devreye girer. SAGA, tek bir global transaction yerine yerel (local) transaction’lar ve gerektiğinde kompanzasyon (geri alma) adımları ile tutarlılığı yönetir.

Bu yazıda SAGA pattern nedir, hangi türleri vardır, ne zaman tercih edilir ve adım adım nasıl kurgulanır sorularını, gerçek hayattan bir e-ticaret örneğiyle netleştireceğiz.


SAGA Pattern Nedir?

SAGA pattern, bir iş sürecini birden fazla servise yayılmış ardışık yerel transaction’lar olarak tasarlar. Her adım başarılı olursa bir sonraki adıma geçilir; herhangi bir adım başarısız olursa daha önce başarıyla tamamlanmış adımlar kompanzasyon işlemleri ile geri alınır.

Bu yaklaşımın temel hedefi:

  • Dağıtık transaction (2PC gibi) karmaşıklığını ve kilitlenmeyi azaltmak
  • Servislerin gevşek bağlı kalmasını sağlamak
  • Hata durumlarında kontrollü geri dönüş üretmek

SAGA vs “Gerçek Transaction” (ACID)

SAGA, klasik ACID transaction garantisini birebir vermez. Onun yerine çoğu senaryoda pratik ve ölçeklenebilir olan eventual consistency (zamana yayılmış tutarlılık) sağlar.

Kriter ACID Transaction SAGA Pattern
Tutarlılık Anlık (strong) Zamanla (eventual)
Kilitleme Sık (lock) Az (servis içi)
Ölçeklenebilirlik Sınırlı Yüksek
Hata yönetimi Otomatik rollback Kompanzasyon adımları

Neden SAGA Pattern Kullanmalıyım?

Bunu neden yapmalıyım?” sorusunun en net cevabı: Dağıtık iş akışlarında tutarlılığı, performansı öldürmeden yönetmek.

SAGA özellikle şu durumlarda güçlüdür:

  • Bir işlem birden fazla mikroservisi etkiliyorsa (Order, Payment, Inventory, Shipping)
  • Global transaction/2PC kullanmak performans ve operasyonel risk yaratıyorsa
  • “Her şey anında tutarlı olmalı” yerine “birkaç saniyede tutarlı olsa da olur” denebiliyorsa

Kazanımlar:

  • Daha az kilitlenme, daha az “tek noktada çöküş”
  • Hata senaryolarının tasarımın parçası olması
  • Büyük işlemleri izlenebilir adımlara bölme

SAGA Türleri: Orkestrasyon vs Koreografi

SAGA’yı iki ana şekilde uygulayabilirsiniz:

1) Orkestrasyon (Orchestrated Saga)

Merkezde bir orchestrator bulunur. Bu bileşen adımları başlatır, sonuçları takip eder, bir adım fail olursa kompanzasyonları tetikler.

Artıları

  • Akış tek yerde görülebildiği için debug ve gözlemlenebilirlik kolay
  • Karmaşık akışlarda kontrol daha net

Eksileri

  • Orchestrator yanlış tasarlanırsa merkezi bağımlılık artabilir

2) Koreografi (Choreographed Saga)

Merkezi bir yönetici yoktur. Servisler event yayınlar, diğer servisler bu event’lere tepki vererek kendi adımlarını yürütür.

Artıları

  • Daha gevşek bağlı ve dağıtık

Eksileri

  • Akış büyüdükçe “event spagetti” riski
  • Akışı uçtan uca takip etmek zorlaşır

Pratik öneri:

  • 3–4 adımdan uzun, hata senaryosu çok olan işlerde çoğunlukla orkestrasyon daha sürdürülebilir olur.

Gerçek Hayat Örneği: E-Ticaret Sipariş Akışı

Bir siparişin basit bir akışı:

  1. Order Service: Siparişi oluştur (PENDING)
  2. Payment Service: Ödemeyi al
  3. Inventory Service: Stok düş
  4. Shipping Service: Kargo kaydı aç

Başarısızlık örneği:

  • Ödeme alındı ✅
  • Stok düşme ❌ (stok yok)

Bu durumda SAGA şunu yapmalı:

  • Payment için kompanzasyon: “refund/void payment”
  • Order durumunu CANCELLED yap

Kompanzasyon Adımı Ne Demek?

Kompanzasyon, “tam rollback” değildir; iş mantığına uygun ters işlemdir.

  • Stok düşmenin kompanzasyonu: stok iade
  • Ödeme almanın kompanzasyonu: iade/iptal
  • Kargo açmanın kompanzasyonu: kargo iptali

Adım Adım: Orkestrasyon ile SAGA Tasarlama

Aşağıdaki adımlar, sahada en çok işe yarayan “uygulanabilir” çerçevedir.

1) Adımları ve Kompanzasyonları Çıkar

Önce tabloyu yazın. Bu, tasarımın omurgasıdır.

Adım İşlem Başarısız Olursa Kompanzasyon
1 Order create Sipariş oluşmaz Yok
2 Payment charge Ödeme alınamaz Order cancel
3 Inventory reserve Stok yok Payment refund + Order cancel
4 Shipping create Kargo açılamaz Inventory release + Payment refund + Order cancel

2) Durum Modeli Tanımla (State Machine)

Order gibi bir “aggregate” üzerinde durumları netleştirin:

  • PENDING
  • PAID
  • RESERVED
  • SHIPPED
  • CANCELLED

Bu sayede hem UI hem de operasyon ekipleri süreci anlayabilir.

3) Mesajlaşmayı Güvenli Hale Getir (En Azından Idempotency)

Dağıtık sistemlerde aynı mesaj tekrar gelebilir. Her adımın idempotent olması gerekir.

Örnek stratejiler:

  • Her komutta bir sagaId ve commandId taşı
  • Servis içinde commandId ile “daha önce işlendi mi?” kontrolü yap

4) Minimal Bir Orchestrator Akışı (Pseudo + Kod)

Aşağıdaki örnek, Node.js/TypeScript ile basit bir orkestratör mantığını gösterir (mesajlaşma altyapısı Kafka/RabbitMQ olabilir).

type SagaState =
  | "STARTED"
  | "ORDER_CREATED"
  | "PAYMENT_CHARGED"
  | "INVENTORY_RESERVED"
  | "SHIPPING_CREATED"
  | "COMPENSATING"
  | "COMPLETED"
  | "FAILED";

interface SagaContext {
  sagaId: string;
  orderId?: string;
  paymentId?: string;
  reservationId?: string;
  shipmentId?: string;
  state: SagaState;
}

async function runOrderSaga(ctx: SagaContext) {
  try {
    ctx.state = "STARTED";

    // 1) Order
    ctx.orderId = await orderCreate(ctx.sagaId);
    ctx.state = "ORDER_CREATED";

    // 2) Payment
    ctx.paymentId = await paymentCharge(ctx.sagaId, ctx.orderId);
    ctx.state = "PAYMENT_CHARGED";

    // 3) Inventory
    ctx.reservationId = await inventoryReserve(ctx.sagaId, ctx.orderId);
    ctx.state = "INVENTORY_RESERVED";

    // 4) Shipping
    ctx.shipmentId = await shippingCreate(ctx.sagaId, ctx.orderId);
    ctx.state = "SHIPPING_CREATED";

    ctx.state = "COMPLETED";
    return ctx;
  } catch (err) {
    ctx.state = "COMPENSATING";

    // Ters sırayla kompanzasyon
    if (ctx.shipmentId) await shippingCancel(ctx.sagaId, ctx.shipmentId);
    if (ctx.reservationId) await inventoryRelease(ctx.sagaId, ctx.reservationId);
    if (ctx.paymentId) await paymentRefund(ctx.sagaId, ctx.paymentId);
    if (ctx.orderId) await orderCancel(ctx.sagaId, ctx.orderId);

    ctx.state = "FAILED";
    throw err;
  }
}

Not: Üretimde bunu doğrudan “tek process”te tutmak yerine:

  • Saga state’i DB’de saklamak
  • Her adımdan sonra state’i persist etmek
  • Retry ve timeout politikaları eklemek

5) Retry, Timeout ve Dead-Letter Kurgusu

SAGA’larda başarısızlık ikiye ayrılır:

  • Geçici hata (network, timeout) → retry
  • Kalıcı hata (stok yok) → kompanzasyon

Önerilen pratikler:

  • Her adım için timeout (ör. 10s)
  • Kademeli retry (ör. 1s, 5s, 30s)
  • Belirli denemeden sonra dead-letter kuyruğu

6) Gözlemlenebilirlik: Log + Trace + İş Metrikleri

SAGA’nın en büyük farkı: hata “normaldir”. Bu yüzden görünür olmalı.

Takip etmek isteyeceğiniz metrikler:

  • saga_completed_total
  • saga_failed_total
  • saga_compensated_total
  • Ortalama tamamlanma süresi (p95)

Log’larda mutlaka şunlar olsun:

  • sagaId, orderId
  • currentStep, state
  • kompanzasyon başladığında ayrı log çizgisi

Sık Sorulan Sorular (FAQ)

1) SAGA Pattern ile veri tutarsızlığı tamamen biter mi?

Hayır. SAGA çoğunlukla eventual consistency sağlar. Kısa süreli tutarsızlıklar olabilir; önemli olan bunun yönetilebilir olmasıdır.

2) SAGA mı, 2PC (Two-Phase Commit) mi?

Çoğu mikroservis senaryosunda 2PC operasyonel olarak ağır ve ölçeklenmesi zor olduğu için SAGA daha pratiktir.

3) Kompanzasyon her zaman mümkün mü?

Her zaman “tam ters işlem” mümkün olmayabilir. Bu durumda iş kuralı ile telafi tasarlarsınız (örn. kupon tanımlama, manuel inceleme kuyruğu).

4) Orkestrasyon mu koreografi mi seçmeliyim?

Akışınız uzunsa, adımlar arası bağımlılık fazlaysa ve izlenebilirlik kritikse genelde orkestrasyon daha kolay yönetilir.

5) SAGA için hangi araçlar kullanılabilir?

Mesajlaşma için Kafka/RabbitMQ; orkestrasyon için özel servis veya iş akışı motorları (Temporal gibi) tercih edilebilir. Önemli olan state + retry + gözlemlenebilirlik üçlüsüdür.


Sonuç

SAGA pattern, mikroservislerde dağıtık transaction problemini; yerel transaction + kompanzasyon yaklaşımıyla yönetilebilir hale getirir. Orkestrasyon ve koreografi seçenekleriyle, sisteminizin karmaşıklığına göre doğru modeli seçebilirsiniz.

Bir sonraki adım olarak:

  • Kendi ürününüzdeki kritik bir akışı (ör. sipariş/ödeme) seçin,
  • Adımları + kompanzasyonları tabloya dökün,
  • Basit bir orchestrator state modeli çıkarıp küçük bir POC deneyin.

Sorunuz varsa akışınızı (kaç servis, hangi adımlar) yorumlarda paylaşın; birlikte en doğru SAGA kurgusunu netleştirelim.