Event-driven mimariye geçtiğim dönemde yaşadığım en belirgin duygu, akışın bütününü bir türlü görememekti.
API log’una bakıyorum, worker log’una bakıyorum, Kafka’da mesaj duruyor mu ona bakıyorum…
Ama parçaları bir araya getirmek pek mümkün olmuyordu. Ne olduğunu biliyorum ama “nasıl” olduğunu görmek zordu.
Monolit günlerinde işler daha sade gelirdi.
Tek proses, tek thread, tek call stack…
F5’e bastığında sistem seninle birlikte ilerlerdi.
Event-driven yapıya geçince o düzen kayboluyor.
Event sıraya giriyor, worker değişiyor, dış API gecikiyor, retry devreye giriyor, DLQ’da yeni bir yol açılıyor… derken akış düz bir çizgi olmaktan çıkıyor.
Tam bu karmaşanın içindeyken distributed tracing ile tanıştım.
Trace ID’yi ekleyince, sistemde dolaşan her adım birbirine bağlanmaya başladı.
Ne zaman süre uzamış, hangi servis beklemiş, dış API ne kadar gecikmiş… hepsi ekranda görünür hâle geliyor.
Bir şeylerin “akış” olduğunu ilk kez o zaman net şekilde fark ettim.

Log Neyi Gösterir, Neyi Göstermez?
Log hâlâ gerekli, hatta olmazsa olmaz.
Ama log, sadece olayın olduğu ana ışık tutuyor.
Bağlantılar tamamen sizin yorumunuza kalıyor.
Örneğin aşağıdaki gibi bir akışı düşünelim:
Bu adımların hepsi ayrı log’larda duruyor.
Sanki birinin not defteri başka yerde, diğerinin başka yerde.
Hepsini yan yana koyabilmek için ekstra çaba gerekiyor.
Dağıtık Sistemlerde Debug Mantığı Neden Farklı?
Event-driven mimari kendiliğinden bazı karmaşıklıklar getiriyor:
- Aynı event farklı servislerden geçebiliyor
- Queue zamanlama ekliyor
- Retry akışı değiştiriyor
- DLQ farklı bir iş hattı oluşturuyor
- Dış API’lerin gecikmesi etkiliyor
- Worker ölürse başka worker devam ediyor
Böyle olunca “kodu durdurup bakayım” yaklaşımı doğal olarak işe yaramıyor.
Artık mesele kodu durdurmak değil, akışı takip edebilmek.
Distributed Tracing ile Akışı Netleştirmek
Tracing, sistemin tüm parçalarını ortak bir kimlik üzerinden bir araya getiriyor.
Bu sayede bir isteğin nereden geçtiğini ve ne yaşadığını tek bir ekranda görebiliyorsunuz.
Bu görüntü sayesinde “şurada gecikmiş”, “burada hata almış”, “şuradan dönmüş” gibi bilgiler artık tamamen görünür oluyor.
Replay: Hata Çözmenin En Basit Hâli
Bir noktadan sonra sadece tracing görmek yetmiyor.
DLQ’ya düşen event’i alıp local’de çalıştırabilmek, hatayı olduğu gibi tekrar üretmenize izin veriyor.
Bu da hatayı bulma ve çözme sürecini oldukça kısaltıyor.
Replay, dağıtık sistemlerde gerçekten rahatlatıcı bir yöntem.
Local Ortamı Küçültmek
Başlarda tüm sistemi local’de ayağa kaldırmaya çalışıyordum.
Kafka, PostgreSQL, Redis, worker’lar, gateway, discovery, servisler…
Ama tracing devreye girdikten sonra, bütün sistemi local’de tekrar üretmenin çok da mantıklı olmadığını anladım.
Artık sadece ilgili parçayı local’de çalıştırıp, akışın kalanını tracing üzerinden takip ediyorum.
Bu çok daha sakin ve sürdürülebilir bir yöntem oldu.
Basit Ama İşe Yarayan Notlar
- Trace ID olmadan event-driven mimariyi takip etmek zor
- Log formatı mümkün olduğunca standart olmalı
- DLQ replay’i çalışma kültürünün bir parçası hâline gelmeli
- Local debug izolasyonlu yapılmalı
- Tracing ve gözlemlenebilirlik artık debug’un bir uzantısı gibi
Sonuç
Dağıtık mimaride debug kavramı bir araçtan çok bir bakış açısına dönüşüyor.
Artık önemli olan tek tek adımlar değil; olayın genel yolculuğu.
Tracing ve replay, bu yolculuğu anlamayı kolaylaştırıyor ve sistemi daha tahmin edilebilir hâle getiriyor.