Event Sourcing Nedir? Audit Trail ve Geri Sarma Rehberi
Event Sourcing nedir, ne zaman seçilir, nasıl tasarlanır? Audit trail, replay, snapshot ve hata senaryolarıyla adım adım rehber.
Event Sourcing Nedir? Audit Trail ve Geri Sarma Rehberi
Meta Description
Event Sourcing nedir? Olay akışıyla geri sarma, audit trail, snapshot ve replay mantığını öğrenin. Üretimde uygulanabilir örneklerle başlayın.
Giriş (Introduction)
Event Sourcing, “verinin son hali” yerine “veriyi değiştiren olayları” (event) saklayan bir mimari yaklaşımdır. Birçok ekipte problem aynıdır: Kim, ne zaman, hangi veriyi değiştirdi? veya Hatalı bir güncellemeden sonra sistemi güvenle nasıl eski haline döndürürüm?
Klasik CRUD modelinde tabloda sadece güncel durum durur; geçmişe dönük analiz, denetim (audit) ve geri alma (rollback) çoğu zaman sonradan yamalarla çözülür. Event Sourcing ise bu sorunu kökten ele alır: tüm değişimleri sıralı bir şekilde kayıt altına alır.
Bu yazıyı okumalısınız çünkü Event Sourcing; finans, sipariş, stok, faturalama gibi “izlenebilirlik” ve “geri sarma” ihtiyacının yüksek olduğu alanlarda doğru uygulandığında hem denetlenebilirliği artırır hem de yeni ihtiyaçlara (analitik, audit, replay) daha hızlı uyum sağlar.
Event Sourcing Nedir?
Event Sourcing, uygulamanın durumunu doğrudan tabloya yazmak yerine, durum değişikliklerini temsil eden immutable (değiştirilemez) event kayıtlarını saklama yaklaşımıdır.
- CRUD yaklaşımı:
balance = 1200(son durum) - Event Sourcing yaklaşımı:
MoneyDeposited(1000),MoneyWithdrawn(200)→ replay ederekbalancehesaplanır
Temel kavramlar
- Event (Olay): Sisteminizde olmuş bir gerçeğin kaydıdır. Geçmişte oldu, değişmez.
- Aggregate: Event’lerden türeyen iş kurallarını yöneten domain nesnesi (DDD’de sık geçer).
- Event Store: Event’lerin append-only (ekle-çık) tutulduğu depo.
- Projection / Read Model: Sorgu için optimize edilmiş türetilmiş görünüm (ör. “sipariş listesi”).
- Replay: Event’leri baştan oynatıp state’i yeniden üretme.
Event Sourcing’i Neden Yapmalıyım?
Aşağıdaki faydalar gerçekten işinize yarıyorsa Event Sourcing iyi bir adaydır:
- Audit trail (denetim izi) otomatik gelir: Kim, neyi, ne zaman yaptı?
- Zaman yolculuğu (time travel): “Dün 14:32’de sistemin durumu neydi?” sorusuna cevap.
- Geri sarma / düzeltme: Hatalı bir iş kuralı sonrası event’leri düzeltme stratejileri.
- Asenkron entegrasyon kolaylığı: Diğer servisler event akışını dinleyebilir.
- Analitik ve raporlama için sağlam kaynak: Ham gerçekler event olarak durur.
Gerçek hayat örneği: Bir pazaryerinde “kargo ücreti” yanlış hesaplandıysa; sadece son fiyatı düzeltmek yetmez. Hangi siparişler etkilendi, hangi kullanıcıya iade doğdu, hangi kampanya tetiklendi gibi soruların cevabı event geçmişinde netleşir.
Event Tasarımı: İyi Event Nasıl Yazılır?
Event’leriniz iş anlamı taşımalı ve gelecekte okunabilir olmalıdır.
İyi event isimlendirme örnekleri
- ✅
OrderPlaced - ✅
PaymentAuthorized - ✅
StockReserved - ❌
OrderUpdated(ne değişti belirsiz) - ❌
DataChanged(iş anlamı yok)
Event payload önerileri
- Event id (uuid)
- aggregate id (örn. orderId)
- type (event adı)
- occurredAt (zaman)
- actor (kullanıcı/servis)
- version (schema versiyonu)
- data (iş verisi)
Minimal örnek JSON
{
"eventId": "8d4f...",
"aggregateId": "order_123",
"type": "OrderPlaced",
"occurredAt": "2026-02-02T10:20:00Z",
"actor": "user_987",
"version": 1,
"data": {
"items": [{"sku": "ABC", "qty": 2}],
"currency": "TRY"
}
}
Event Store Seçenekleri ve Saklama Stratejileri
Event store için 3 yaygın yol:
| Yaklaşım | Artı | Eksi | Ne zaman? |
|---|---|---|---|
| PostgreSQL (append-only tablo) | Basit, ucuz, ACID | Yük arttıkça partition/performans gerekir | İlk geçiş, orta ölçek |
| Kafka (log) + ayrı storage | Stream için güçlü | Query için tek başına yeterli değil | Çok servisli event akışları |
| Özel event store (EventStoreDB vb.) | Event odaklı özellikler | Ek operasyonel yük | Event Sourcing çekirdek ürünse |
PostgreSQL ile basit event store tablosu
CREATE TABLE event_store (
id UUID PRIMARY KEY,
aggregate_id TEXT NOT NULL,
sequence BIGINT NOT NULL,
type TEXT NOT NULL,
occurred_at TIMESTAMPTZ NOT NULL,
payload JSONB NOT NULL,
UNIQUE (aggregate_id, sequence)
);
CREATE INDEX idx_event_store_agg ON event_store(aggregate_id);
Neden sequence önemli? Aggregate başına event sırasını garanti ederek replay’i deterministik yapar.
Projection (Read Model) Mantığı: Okumayı Hızlandırma
Event Sourcing’de sık yapılan hata: “Her sorguda event’leri replay ederim.” Bu, çoğu ekranda pahalıdır.
Çözüm: Projection (türetilmiş okuma modeli)
Örnek projection: Sipariş listesi
- Event’ler:
OrderPlaced,PaymentAuthorized,OrderCancelled - Read model tablosu:
order_list_view
CREATE TABLE order_list_view (
order_id TEXT PRIMARY KEY,
status TEXT NOT NULL,
total_amount NUMERIC NOT NULL,
updated_at TIMESTAMPTZ NOT NULL
);
Projection güncelleme mantığı (psödo):
On OrderPlaced -> insert order_list_view
On PaymentAuthorized-> update status = 'PAID'
On OrderCancelled -> update status = 'CANCELLED'
“Bunu neden yapmalıyım?”
- UI ve API read işlemleri hızlı olur
- Event geçmişi bozulmadan kalır
- İleride yeni bir ekran için yeni projection eklemek kolaydır
Replay, Snapshot ve Performans: Üretimde Nasıl Yürür?
Replay (yeniden oynatma)
Bir aggregate’ın state’ini üretmek için event’leri sırayla uygularsınız:
# basit bir fikir vermesi için
state = EmptyOrder()
for event in events:
state = apply(state, event)
return state
Snapshot (anlık görüntü)
Event sayısı çok artınca replay maliyetini düşürmek için ara state saklanır.
- Her 100 event’te bir snapshot
- Replay: son snapshot + sonrası event’ler
Snapshot ne zaman mantıklı?
- Aggregate başına yüzlerce/binlerce event birikiyorsa
- Sık state rebuild yapıyorsanız (ör. yoğun doğrulamalar)
Zor Kısım: Versiyonlama, Düzeltme ve Silme (GDPR)
Event Sourcing “event değişmez” dediği için bazı gerçeklerle yüzleşirsiniz.
1) Event schema versiyonlama
Event payload zamanla değişir. Çözüm:
versionalanı kullanın- Okuyucularda upcaster mantığı kurun (eski event’i yeni formata çevir)
2) Hatalı event düzeltme
Event’i silmek yerine genelde:
- Compensating event yazılır (telafi)
- Örn:
PaymentCapturedhatalıysaPaymentReversed
- Örn:
3) Kişisel veriyi event’te tutma
Event içine e-posta/telefon gibi PII koymak risklidir.
- Event’te referans tutun (userId)
- PII ayrı sistemde saklansın
- GDPR/KVKK için “forget” stratejinizi en baştan planlayın
Adım Adım Başlangıç Planı (Pratik Yol Haritası)
- Uygun bounded context seçin: En kritik ve audit isteyen modül (örn. ödeme, sipariş).
- Event sözlüğü çıkarın: 10–15 net event adıyla başlayın.
- Event store’u kurun: İlk aşamada PostgreSQL append-only yeterli olabilir.
- İlk projection’ı yazın: En çok kullanılan ekran/API için read model oluşturun.
- Idempotency ve sequence kuralını ekleyin: Aynı event iki kez işlenmesin.
- Gözlemlenebilirlik ekleyin: Event işleme gecikmesi, projection lag metriği.
Sık Sorulan Sorular (FAQ)
1) Event Sourcing ile CQRS aynı şey mi?
Hayır. Event Sourcing veri saklama yaklaşımıdır; CQRS okuma-yazma modellerini ayırma yaklaşımıdır. Birlikte sık kullanılır ama zorunlu değildir.
2) Event Sourcing her projeye uygun mu?
Hayır. Audit ve geri sarma ihtiyacı düşük, domain basit ve ekip küçükse gereksiz karmaşıklık yaratabilir.
3) Projection bozulursa ne olur?
Event’lerden replay ederek projection’ı baştan üretebilirsiniz. Bu, mimarinin en büyük avantajlarından biridir.
4) Event sayısı çok artarsa performans düşer mi?
Doğru tasarım yoksa evet. Çözüm genellikle snapshot, doğru indeksleme, partitioning ve projection stratejisidir.
Sonuç
Event Sourcing, sistemi “son durum” yerine “olayların gerçeği” üzerinden kurgulayarak audit trail, geri sarma ve replay gibi kritik yetenekler kazandırır. Doğru yerde kullanıldığında hem operasyonel hataları yönetmeyi kolaylaştırır hem de yeni ihtiyaçlara daha hızlı adapte olmanızı sağlar.
Bir sonraki adım olarak: Kendi ürününüzde audit ihtiyacı en yüksek modülü seçin, 10 event’lik küçük bir kapsamla başlayın ve tek bir projection’ı ayağa kaldırın. Deneyiminizi, takıldığınız noktaları veya kullandığınız event tasarımını yorumlarda paylaşın; birlikte iyileştirelim.