# Yazılım mimarı: teslim garantisinin karar garantisi olmadığı sistemler

> Mimariyi karar, sınır ve bedel olarak yapıyorum — sistem tasarımı ve event-driven mimaride, outbox ve determinizm konularında kanıtı sitede duran işler.

- Teknolojiler: RabbitMQ, Redis, MySQL, PostgreSQL, Docker, GitHub Actions
- Deneyim: 2022'den bu yana
- Yazı: 5
- Proje: 10
- Güncelleme: 2026-10-07
- Kaynak: https://muhammetsafak.com/tr/uzmanlik/architecture/
- Dil: tr-TR
- Yazar: Muhammet Şafak

---
## Bu ekosistemde ben

Mimariyi bir desen koleksiyonu olarak değil, belirli bir sistemde, belirli bir
sınırla ve belirli bir bedelle verilmiş karar olarak yapıyorum. Bu sayfa üç
konuyu kendi kapsamında tutuyor: Software Architecture, System Design ve
Event-Driven Architecture.

Üçünün kanıtı sitede duruyor. Teslim ve idempotency tarafı
[outbox günlüğünde](/tr/blog/outbox-idempotent-tuketim-ve-alan-sifrelemesi/),
yasal bir kısıtın tasarımı nasıl daralttığı
[numara çakışması günlüğünde](/tr/blog/e-fatura-entegrasyonunda-numara-cakismasi/),
teslimden sonraki determinizm sorusu ise
[determinizm yazısında](/tr/blog/event-driven-mimaride-determinizm/).
Rollerin kendisi [özgeçmişte](/tr/ozgecmis/), konunun kitap ölçeğindeki karşılığı
[güvenilir event-driven sistemler](/tr/kitaplar/designing-reliable-event-driven-systems/)
kitabında. Derinliğe inmek isterseniz [sade.dev](https://sade.dev) tarafındaki
[mimari kararların neden çürüdüğü](https://sade.dev/tr/journal/mimari-kararlar-curur)
yazısı ve
[outbox ile idempotent tüketim](https://sade.dev/tr/systems/transactional-outbox-dual-write-ve-idempotent-tuketim)
anlatısı doğru yer.

### Bu sayfanın kapsadığı üç konu

Üçü de sitedeki bir yazıya, kayda ya da deneyime dayanıyor; derinlik değil kimlik ve kanıt düzeyinde duruyor.

- **Software Architecture** — Mikroservis sınırlarını, kritik tasarım kararlarını ve bunların ekibe aktarılmasını kapsıyor. Senior Software Developer, ardından Staff Engineer rollerinde mimariyi domain-driven design ve test-odaklı geliştirmeyle birlikte yürüttüm; sınırları wiki'de bırakmayıp koda yazıp CI'da denetleyen yaklaşım da bu başlığın parçası.
- **System Design** — Bir sistemin ölçeklenme, erişilebilirlik ve yük dağılımı kararlarını kapsıyor. Senkron bir fatura akışını ortak bir kuyruğa ve ayrı bir consumer servisine taşıdım. Bunun temeli, mimari sorumluluk üstlenmemden önce bir arama altyapısında atıldı; MySQL ile Redis'i birlikte kullanan bir önbellek katmanı ve böldüğüm veritabanı ile cache kümeleri.
- **Event-Driven Architecture** — Teslim, tekrar ve determinizm sorularını kapsıyor. Transactional outbox, idempotent tüketici ve at-least-once teslim bu başlığın pratiği; teslim edilen bir mesajın aynı sonucu üreteceğinin ayrı bir garanti gerektirdiği de.

### Bir kararın bedeli

E-fatura numarası üretiminde yasal bir kısıt tasarımın asıl kuvveti oldu. Zincir sırayla okunur.

1. **Numarayı geç üretmek race doğurdu** — Gönderim anında MAX değerine bir ekleyen yöntem tek worker'la çalışıyordu; paralel worker'lar aynı numarayı üretip dış API'ye aynı numarayla gitti.
2. **Numarayı erken üretmek boşluk doğurdu** — Numara kuyruğa atılırken üretilirse, düşen ya da iptal edilen fatura seride açıklanamayan bir boşluk bırakıyor. Yasal seride atlanan numara olamaz.
3. **Yasal kısıt çözüm kümesini daralttı** — Çakışmayı tek başına çözen çok yöntem var; boşluksuzluk eklenince çözüm kümesi bir anda daraldı. Gereksinimi iş kuralı diye kenara almadan önce mimariyi nasıl kısıtladığına bakmak gerekiyor.
4. **Numara, dış çağrıdan hemen önce rezerve edildi** — Rezerve edilen numara çağrı başarısız olsa da faturanın üstünde kalıyor ve aynı numarayla yeniden deneniyor. Dış çağrı transaction'ın dışında tutuldu; aksi hâlde sistem bir bottleneck'e dönüşürdü.

### Teslim garantisi karar garantisi değildir

Her garanti bir maliyetle geliyor; bir deseni çözmek bir sonrakini açıyor.

1. **Outbox mesajın kaybolmamasını sağlar** — Mesaj, kayıtla aynı transaction içinde bir outbox satırı olarak yazılıyor ve bir relay onu yayımlıyor. Dual-write problemi böylece kapanıyor.
2. **At-least-once tekrar getirir** — Mesaj kaybolmuyor ama tekrar edebiliyor. Tüketicinin idempotent olması, tekrarı yan etkisiz hâle getiriyor.
3. **Teslim edilen mesaj aynı kararı vermeyebilir** — Aynı önek listesi iki ayrı serviste tutulduğunda, birinin güncellenmesi, birkaç saat arayla gelen aynı biçimdeki iki mesajdan birini geçirip ötekini reddettirdi. Mesaj, kararın girdisinin tamamı değil.
4. **Bağlamı üretim anında dondurmak gerekiyor** — Karar için gereken bilgiyi tüketici kendi çözmemeli; olay kendi bağlamını taşımalı. Retry, karar anını değiştirmemeli.

### Mimariyi nasıl yürütüyorum

Üç alışkanlık, hepsi ekibin aynı kararı aynı biçimde okuyabilmesine dönük.

- **Kararın bedelini yazmak** — Bir kararın neyi kapattığını ve yerine ne koyduğunu yazmadan onu mimari saymıyorum. Yukarıdaki iki zincir bu alışkanlığın çıktısı.
- **Sınırı koda yazmak** — Katmanları ve izinli bağımlılıkları tek bir dosyada beyan edip her commit'te CI'da denetlemek, bir mimari kararın iki yıl sonra çürümesini önlüyor.
- **Bilgiyi ekibe aktarmak** — Ekibe TDD ve DDD mentörlüğü verdim ve bir code-review rehberi hazırladım; mimarinin yaşadığı yer belge değil, ekibin her gün verdiği küçük kararlar.

### Derinlik burada değil

Bu sayfa kimlik ve kanıt düzeyinde kalıyor. Desen anlatısını, mimari kararların neden çürüdüğünü ve outbox ile numara rezervasyonunun ayrıntılarını sade.dev'de yazıyorum.

## Sık sorulanlar

### Mimari alanında kaç yıldır çalışıyorsun?

2022'den bu yana, 4 yıldır. Senior Software Developer olarak başladım, Mart 2025'ten beri Staff Engineer olarak mikroservis ve event-driven mimariyi tasarlıyorum. Daha önceki arama altyapısı yıllarındaki sistem tasarımı temeli bu sürenin dayanağı; sürenin kendisine dahil değil. Bu sitede bu işlerle kesişen 5 yazı kayıtlı.

### Software Architecture, System Design ve Event-Driven Architecture arasında nasıl ayırıyorsun?

Software Architecture sınırları ve kararları, System Design bir sistemin ölçeklenme ve erişilebilirlik davranışını, Event-Driven Architecture ise servisler arasındaki teslim, tekrar ve determinizm sorularını kapsıyor. Üçü aynı işin farklı ölçekleri; bu sayfa üçünü birlikte tutuyor.

### Kuyruğa taşımak teslim garantisi verir mi?

Hayır. Outbox mesajın kaybolmamasını sağlar ama size at-least-once verir; tekrarı idempotent tüketici bastırır. Teslim edilen mesajın aynı kararı vereceği ise üçüncü bir garanti ve bir fatura akışında onu ayrıca kurmam gerekti.

### Mimari kararı nasıl değerlendiriyorsun?

Neyi kapattığına ve yerine ne koyduğuna bakarak. E-fatura numarası örneğinde numarayı geç üretmek race, erken üretmek boşluk doğuruyordu; çözüm ikisini birden tutmaktı.

### Derin mimari yazılarını nerede okuyabilirim?

sade.dev'de. Bu sayfa kimlik ve kanıt düzeyinde kalıyor; desen anlatısı ve uzun mimari yazılar orada.
