Database scaling konusu her SaaS’ta bir gün gelir. “Query’ler yavaş, DB load yüksek, read replica ekleyelim.” Klasik çözüm. Ama read replica free lunch değil, complexity getiriyor.
Onlarca projede read replica karar verdim veya vermedim. Bu yazıda pratik karar kriterlerini ve karşılaşılan gerçek sorunları anlatacağım.
Read replica temel çalışma
Primary database write işlemi aldı. Transaction commit olur olmaz, transaction log (WAL, binlog) replica’lara stream ediyor. Replica’lar bu log’u replay edip aynı state’i kuruyorlar.
Okuma read replica’dan, yazma primary’den.
Avantajlar:
– Read load primary’den replica’ya yayılıyor
– Read capacity artırmak için replica ekle (horizontal scaling)
– Primary down olsa bile replica’lar okunuyor (partial failover)
– Analytics query’leri için dedicated replica
Replication lag: nadir bahsedilen maliyet
Bu işin temel sorunu. Replica primary’den her zaman “biraz geride”. Network latency + replay süresi. Genelde milisaniyeler ama bazen saniyeler, bazen dakikalar.
Sorunlu senaryolar:
1. Write-then-read immediate. Kullanıcı profile update etti, hemen profile sayfasını yenileyince değişiklik görünmüyor (replica hâlâ eski veri).
2. Sequential business logic. Kullanıcı order verdi, sonraki adımda “orders” listesine baktığında yeni order yok (replica sync olmamış).
3. Financial operations. Kullanıcı ödeme yaptı, balance güncellenmeli. Replica’dan okuyorsan hatalı balance gösterebilirsin.
Replication lag ölçekte ciddi sorun olabiliyor. %99.9 durumda 50ms ama %0.1’de 30 saniye çıkabiliyor. Edge case’ler kullanıcı şikayetine dönüyor.
Ne zaman read replica ekleyelim?
1. Read/write ratio yüksek (10:1 veya fazla).
Get-heavy API’lar. Product catalog (her listing view read, update seyrek). Dashboard metric’leri (sürekli okunuyor). User feed.
2. Read query’leri heavy ama kritik değil.
Reporting, analytics, admin panel’deki detaylı query’ler. Biraz stale data tolere edilebilir (1-5 saniye). Bu workload’u primary’den çekmek primary’yi rahatlatıyor.
3. Geographic distribution.
Primary US’de, kullanıcıların yarısı Avrupa’da. Avrupa’da replica koyarsan read latency 150ms’den 20ms’ye düşüyor.
4. Primary’nin hardware’i saturated.
CPU %80+, memory full, IOPS limit’e yakın. Vertical scaling limit’e geldi, horizontal (read replica) gerekiyor.
Ne zaman read replica eklememeliyiz?
1. Write-heavy workload.
Mesajlaşma, real-time collaboration, IoT sensor data. Replication lag her yazma için yeni bir gecikme ekliyor. Primary zaten yoğun, replica kopyalamaya zor yetişiyor.
2. Güçlü consistency gereksinim.
Finansal, medical, inventory. “Kullanıcı $100 yatırdı, balance $100 artmış olmalı, hemen.” Replica read burada yanlış sonuç veriyor.
3. Küçük scale.
Primary %30-40 CPU’da çalışıyor. Read replica eklemek complexity getirmeden, ama gerçek bir değer vermeden. Önce query optimization, indexing.
4. Karmaşık schema değişiklikleri yaygın.
Replica yapısı primary’yi aynen kopyalıyor. Schema migration sırasında replica’lar geçici olarak sync’ten düşebiliyor. Değişiklik sıklığınız fazla ise complexity artıyor.
Uygulama tarafında handle edilmesi gerekenler
Read replica eklediğinde application layer’da değişiklikler:
1. Connection routing.
Write query → primary connection
Read query → replica connection
Most ORM’ler bu split’i destekliyor (Rails’de ActiveRecord’s db:create_with_replicas, Django’da DATABASES config). Ama manual routing gereken yerler var.
2. Session-level “read your writes”.
Kullanıcı yeni profile update etti. Sonraki read’de kendi update’ini görmeli. Session başına primary’e bağlı kal:
class Database:
def get_read_connection(self):
if session_has_recent_write(session_id):
return self.primary
return random_replica()“Recent write” süresi replication lag’e göre ayarlanmalı (~5-10 saniye).
3. Critical read’ler primary’den.
Bazı read operasyonları consistency kritik. Bu path’lerde explicitly primary’den oku:
def get_user_balance(user_id):
# Financial read, hep primary
return db.primary.query("SELECT balance FROM users WHERE id = ?", user_id)Replication lag monitoring
Monitor etmen gereken metric’ler:
- Replication lag (seconds behind primary): <100ms normal, 1s+ alarm
- Replica CPU/IO: primary ile benzer olmalı
- Replication thread health: çalışıyor mu, freeze olmuş mu?
- Replica connection count: aşırı yüklü mü?
Bunlardan herhangi birini unutursan bir gün replica bir saatten fazla geride olur ve kimse fark etmez.
Multiple replica stratejileri
Bir replica yeter mi? Daha fazla mı?
Single replica: Read failover, basit setup. Yeter için start point.
Multiple replica + load balancer: 2-3 replica, traffic distribute. High read load senaryolarında.
Dedicated analytics replica: Ayrı bir replica sadece raporlama için. Bu replica’nın daha fazla lag’i olabilir, sorun değil. Ana replica’ları operational için ayırıyor.
Multi-region replica: Coğrafi olarak dağıtılmış. Cross-region replication lag daha yüksek olabiliyor ama local read çok hızlı.
Failover scenario’ları
Primary düştüğünde ne oluyor?
Manual failover: Bir replica’yı yeni primary promote et. Diğer replica’lar yeni primary’e bağlan. 5-15 dakikalık outage.
Automatic failover (AWS RDS, Aurora): Primary down tespit edilince otomatik promote. 30 saniye – 2 dakika outage.
Split-brain risk: İki farklı node “ben primary’im” diye iddia ediyor. Data corruption tehlikesi. Managed database (RDS, CloudSQL) bunu handle ediyor, self-managed’de konfigüre edilmeli.
Maliyet
Read replica ücretsiz değil:
- Her replica ek compute + storage maliyeti
- Cross-region replica ek network transfer maliyeti
- Monitoring, alerting overhead
- Operational complexity (failover planning, disaster recovery)
AWS RDS’de primary $200/ay ise replica başına ek $150-200. 3 replica = $600-800 ek maliyet.
Bu maliyet DB load rahatlamasıyla haklı mı? Bazen evet (performans kritik), bazen hayır (query optimization daha uygun).
Önce query optimization
Read replica eklemeden yapılması gerekenler:
- Slow query log analizi. En yavaş 10 query’yi optimize et.
- Missing index’ler. EXPLAIN ile kritik query’leri incele.
- N+1 query problemleri. ORM eager loading ile çöz.
- Caching layer (Redis). Frequently accessed data’yı cache’le.
- Query result caching. Expensive query’ler materialized view veya cache’e.
Bu 5 optimizasyon genelde DB load’u %50-70 düşürüyor. Read replica gerekmiyor bazen.
Sonuç
Read replica güçlü bir scaling tool, ama her proje için değil. Doğru durumlarda değer katar (read-heavy, analytics, geographic). Yanlış durumlarda complexity ekler (write-heavy, strong consistency).
Kararını “hangi problem’i çözüyorum” sorusu ile ver. “Scale lazım galiba” diye eklemek yerine specific bir performance problem çözmek için ekle. Monitoring kur, replication lag’i izle, application layer’da routing’i doğru yap.
Çoğu proje için önce query optimization + caching dener, sonra read replica. Erken eklediğin complexity pahalı ders oluyor.