Oyun Kitabı

Ödeme Sistemleri Neden Dağıtık Sistemlerdir? (Odeme Sistemleri Neden Dagitik Sistemlerdir)

Bir ödeme tek bir servisin işi değildir: sepet, stok, provider gateway ve finans aynı gerçek üzerinde anlaşmak zorundadır. Senkron zincir neden kırılır?

Dağıtık Ödeme Motoru (Distributed Payment Engine)

Bolum 1 / 22

Capture ile complete arasındaki boşluğu kapatan dağıtık ödeme mimarisi serisi.

Distributed payment engine architecture diagram

Ödeme bir buton değildir, bir koordinasyondur

Bir e-ticaret platformunda “ödeme al” dediğinizde aslında beş farklı sistemin aynı gerçek üzerinde anlaşmasını istersiniz: sepet dondurulmuş mu, stok var mı, provider gateway parayı aldı mı, sipariş onaylandı mı, finans kaydı doğru mu. Bunların hepsi tek bir process içinde, tek bir transaction'da yaşamaz.

Sepet Servisi   Stok Servisi   Checkout Orchestrator   Provider Gateway   Finans/Ledger
     |               |                  |                    |                |
     +---------------+------------------+--------------------+----------------+
                          aynı sipariş, beş farklı gerçek

Bu yazı, ödeme akışını neden “bir servisin fonksiyonu” gibi değil, dağıtık bir sistem problemi gibi tasarlamanız gerektiğini anlatıyor.

Kavramlar ilk geçtiği yerde

📦 Checkout Orchestrator
Sipariş akışının adımlarını (sepet, ödeme, stok, onay) koordine eden servis; para veya stok tutmaz, kararları sıralar.

📦 Provider Gateway
Gerçek ödeme sağlayıcısını (PSP) uygulama iç modeline çeviren soyutlama katmanı.

📦 PSP (Payment Service Provider)
Kartı veznede tutan, parayı fiilen çeken dış sistem; sizin transaction sınırınızın dışındadır.

📦 Dağıtık Transaction
Birden fazla bağımsız sistemin, tek bir “hepsi ya da hiçbiri” garantisi altında değişmesi gereken işlem.

📦 Eventual Consistency
Sistemlerin şu an değil, kısa bir süre içinde aynı gerçeğe yakınsayacağını kabul eden tutarlılık modeli.

Bu beş kavramı ayırt edemeyen bir ekip, PSP'yi kendi veritabanı gibi davranmaya zorlar. PSP asla sizin transaction'ınıza katılmaz; o yalnızca kendi gerçeğini, kendi zaman çizelgesinde bildirir.

Tek istek, beş imza gerektirir

Bir müşteri “Öde” butonuna bastığında, arka planda sırayla şu kararlar verilir: sepet fiyatı donduruldu mu, stok rezerve edildi mi, provider gateway'e ödeme isteği gitti mi, PSP parayı çekti mi, sipariş satırları finalize edildi mi, finans kaydı açıldı mı. Bunların her biri farklı bir servisin sorumluluğundadır ve farklı bir veritabanında yaşar.

Problem burada başlar: Bu altı adımı tek bir HTTP isteği zinciri içinde senkron olarak çağırırsanız, sistem bir tek noktadan diğerine bağımlı, uzun ve kırılgan bir zincir haline gelir.

Client → Checkout Orchestrator → Sepet Servisi → Stok Servisi → Provider Gateway → PSP

Senkron zincir nerede kırılır

Bu zincirde herhangi bir adım timeout verdiğinde iki soruyla baş başa kalırsınız: İstek karşı tarafa ulaştı mı, ulaştıysa işlendi mi? PSP'den dönen bir timeout, “para çekilmedi” anlamına gelmez; “cevabı alamadım” anlamına gelir. Aynı isteği tekrar göndermek, müşteriyi iki kez veznede bırakabilir.

Checkout Orchestrator --(timeout)--> Provider Gateway --(???)--> PSP
                                                        para çekildi mi, çekilmedi mi?

Bu belirsizlik, senkron zincirin doğal sonucudur: Ağ, tanım olarak güvenilmezdir; zinciri ne kadar uzatırsanız, belirsizlik o kadar birikir.

“Hepsi ya da hiçbiri” neden burada çalışmaz

Klasik dağıtık transaction çözümleri (two-phase commit gibi) tüm katılımcıların aynı koordinatöre, aynı kilitleme protokolüne ve aynı ağ güvenilirliğine sahip olmasını bekler. PSP bu dünyanın parçası değildir: kendi kilidini açmaz, sizin commit/rollback çağrınızı dinlemez, kendi zaman çizelgesinde (webhook, gecikmeli bildirim) sizi bilgilendirir.

Bu yüzden “ödeme + stok + sipariş” üçlüsünü tek bir transaction'a sığdırmaya çalışmak, çözülemeyen bir problemi çözülmüş gibi göstermektir. Gerçekte yaptığınız şey, hatayı gizlemektir; ortadan kaldırmamışsınızdır.

Olay tabanlı çözüm: iki farklı gerçek, iki farklı zaman çizelgesi

Çalışan model, senkron zinciri kısaltıp geri kalanını olaylara devretmektir. Provider gateway'e istek gönderirsiniz, PSP'nin cevabını (senkron ya da webhook ile) bir olay olarak kaydedersiniz, ve sipariş/stok/finans tarafındaki her adım bu olaya tepki veren, kendi başına idempotent birer tüketicidir.

Provider Gateway → PaymentCaptured (event) → Outbox
                                              ↓
                         Stok Servisi   Finans Servisi   Checkout Orchestrator
                         (bağımsız, kendi hızında, kendi retry'ıyla tüketir)

Bu modelde “ödeme başarılı” ve “sipariş tamamlandı” artık aynı anda gerçekleşen tek bir olay değil, birbirini takip eden, aralarında ölçülebilir bir gecikme olabilen iki farklı gerçektir. Bu ayrımı kabul etmeyen sistemler, bu serinin ikinci bölümünde göreceğimiz durum makinesi hatalarına doğru ilerler.

Bu bölümde en çok karışan eşleştirmeler

❌ Ödeme akışı = tek bir servisin fonksiyonu
✓ Ödeme akışı = birden fazla bağımsız servisin katıldığı bir koordinasyon

❌ PSP = bizim veritabanımızdaki bir tablo gibi davranır
✓ PSP = kendi zaman çizelgesi olan, dışarıdan gözlemlenen bir sistem

❌ Timeout = işlem başarısız oldu
✓ Timeout = işlemin sonucu bilinmiyor; retry idempotent olmadan güvenli değildir

❌ Dağıtık transaction ile bu problem “çözülebilir”
✓ Dağıtık transaction, PSP gibi harici sınırlarda pratikte uygulanamaz

Bu dört yanlış eşleştirme, çoğu “ödeme neden bazen çift çekiliyor” incident'inin köküdür.

Kendi sisteminizi denetleme listesi

  1. Ödeme akışınızda kaç farklı servis, kaç farklı veritabanına yazıyor? Bu sayıyı yazın.
  2. Provider gateway'e giden çağrı timeout verdiğinde, kodunuz otomatik retry yapıyor mu? Bu retry idempotency key taşıyor mu?
  3. “Ödeme başarılı” bilgisi ile “sipariş tamamlandı” bilgisi aynı satırda mı, farklı tablolarda mı tutuluyor?
  4. PSP'den gelen webhook gecikirse veya hiç gelmezse, sisteminiz kaç saat sonra fark ediyor?
  5. Senkron zincirinizde en uzun adım hangisi ve o adım düşerse geri kalan adımlar ne yapıyor?

Bu beş soruya net cevabınız yoksa, ödeme akışınız muhtemelen “tek transaction” yanılsamasıyla tasarlanmıştır.

Bu bölümden aklında kalması gerekenler

  1. Bir ödeme, tek bir servisin işlemi değildir; sepet, stok, provider gateway ve finansın aynı gerçek üzerinde anlaştığı bir koordinasyondur.
  2. Senkron HTTP zinciri, her ek adımda belirsizliği çarparak biriktirir; timeout bir sonuç değil, bir bilinmezliktir.
  3. PSP sizin transaction sınırınızın parçası değildir; onunla senkron kilit değil, olay sözleşmesiyle konuşursunuz.
  4. Eventual consistency bir eksiklik değil, dış dünyanın (özellikle PSP'nin) gerçek davranışının kabul edilmesidir.

Ödeme sistemini “anlık ve tek parça” gibi tasarlarsanız, üretimde “gecikmeli ve çok parçalı” gerçekle çarpışırsınız.

SSS

Sık sorulan sorular

Checkout Orchestrator nedir?

Sipariş akışının adımlarını (sepet, ödeme, stok, onay) koordine eden servis; para veya stok tutmaz, kararları sıralar.

Provider Gateway nedir?

Gerçek ödeme sağlayıcısını (PSP) uygulama iç modeline çeviren soyutlama katmanı.

"Ödeme akışı = tek bir servisin fonksiyonu" doğru mu?

Ödeme akışı = birden fazla bağımsız servisin katıldığı bir koordinasyon

Bu bölüm neyi sabitler?

Bu yazı, ödeme akışını neden “bir servisin fonksiyonu” gibi değil, dağıtık bir sistem problemi gibi tasarlamanız gerektiğini anlatıyor. Bir ödeme, tek bir servisin işlemi değildir; sepet, stok, provider gateway ve finansın aynı gerçek üzerinde anlaştığı bir koordinasyondur. Bir e-ticaret platformunda “ödeme al” dediğinizde aslında beş farklı sistemin aynı gerçek üzerinde anlaşmasını istersiniz: sepet dondurulmuş mu, stok var mı, provider gateway parayı aldı mı, sipariş onaylandı mı, finans kaydı doğru mu. Bunların hepsi tek bir process içinde, tek bir transaction'da yaşamaz.

Ogrenilen Muhendislik Prensipleri

  • Bir ödeme akışı, tek servisin fonksiyonu değil; birden fazla bağımsız sistemin koordinasyonudur.
  • PSP, sizin transaction sınırınızın dışındadır; onunla event sözleşmesiyle konuşulur, senkron kilitle değil.
  • Eventual consistency bir zayıflık değil, ağın ve dış sağlayıcıların gerçek davranışının tasarıma yansımasıdır.

Okumaya devam et

Okumaya devam et

Seride sonraki yazi

Ayni seriden

Ayni seriden

Paylaş