Caching, Idempotency ve Rate Limiting
Bu bölümde üç kritik backend konseptini ele alıyoruz:
- Caching: Performansı artırır
- Idempotency: Tekrarlanan isteklerde veri tutarlılığını korur
- Rate Limiting: Sistemi kötüye kullanıma ve aşırı yüke karşı korur
Bu üçü birlikte kullanıldığında hem hızlı hem güvenli hem de ölçeklenebilir API’ler elde edilir.
1) Caching
Caching Nedir?
Caching, sık erişilen verilerin daha hızlı erişilebilen bir katmanda (çoğunlukla RAM) geçici olarak saklanmasıdır.
Kullanıcı sayısı arttıkça her isteğin DB’ye gitmesi şu sonuçları doğurur:
- Veritabanı yükü artar
- Sorgu süreleri uzar
- API response süreleri yükselir
- Kullanıcı deneyimi kötüleşir
Caching bu yükü azaltarak sistemi rahatlatır.
Ne Zaman Cache Kullanılmamalı?
- Nadir erişilen veriler (cache maliyeti, getiriden fazla olabilir)
- Çok sık değişen veriler (stale veri riski artar)
- Cache, tek doğru kaynak (source of truth) olmamalıdır
Temel kural: Cache “doğruluk” değil, “hız” içindir.
Cache Türleri
1. In-Memory Cache (Map, LRU)
Veri, uygulamayı çalıştıran instance’ın RAM’inde tutulur.
Avantajlar
- Çok hızlı
- Kurulumu kolay
- Ek servis gerektirmez
Dezavantajlar
- Restart ile silinir
- RAM ile sınırlıdır
- Multi-instance ortamda tutarsızlık yaratır
Sticky sessions bazı durumlarda yardımcı olabilir fakat kalıcı çözüm değildir.
2. Distributed Cache (Redis)
Redis, cache’i uygulama sunucularından bağımsız bir servis olarak sunar.
Özellikle:
- Birden fazla instance
- Load balancer
- Horizontal scaling
olan sistemlerde Redis neredeyse zorunludur.
Akış
- İlk istekte DB’den okunur
- Redis’e yazılır
- Sonraki isteklerde Redis’ten okunur
- Bulunursa direkt client’a döner
Cache Metodolojileri
- On-Demand (Lazy Loading): İlk istek geldiğinde cache’lenir (en yaygın)
- Prepopulation: Uygulama açılırken cache doldurulur (sabit ve sık kullanılan veri)
Cache Ömrü (TTL)
- Absolute TTL: Süre dolunca silinir
- Sliding TTL: Erişildikçe süre uzar
Pratikte en dengeli yaklaşım: Absolute + Sliding birlikte kullanmaktır.
Redis ile İlgili Notlar
Redis RAM tabanlı olduğu için çok hızlıdır; ancak:
- Primary database değildir
- Kompleks sorgu yeteneği sınırlıdır
- Transaction/rollback mantığı RDBMS gibi değildir
Persistence seçenekleri
- RDB: Periyodik snapshot
- AOF: Her değişiklik loglanır (daha güvenli, daha maliyetli)
Cache Stratejileri
Cache-Aside (En yaygın)
- Redis’e bak
- Yoksa DB’den oku
- Redis’e yaz
- Client’a döndür
const cached = await redis.get(key);
if (cached) return JSON.parse(cached);
const data = await dbCall();
await redis.set(key, JSON.stringify(data), 'EX', 60);
return data;
Write-Through
Veri aynı anda DB’ye ve cache’e yazılır (tutarlılık daha iyi, yazma maliyeti daha yüksek).
Fail-safe Cache (Fall-through to DB)
Redis ulaşılamazsa sistem çökmez; istek DB’ye düşer.
Akış: Client → API → Redis → (yoksa) DB
Bu davranış caching sistemlerinde kritik bir dayanıklılık kuralıdır.
2) Idempotency
Idempotency Nedir?
Idempotency, aynı isteğin bir kez ya da birçok kez gönderilmesinin aynı sonucu üretmesi demektir.
Örnekler:
DELETE /products/10tekrar edilse bile sonuç değişmez (idempotent)POST /ordersher seferinde yeni order üretir (idempotent değil)
Neden Önemlidir?
Gerçek dünyada tekrar istekler kaçınılmazdır:
- Ağ kopması ve retry
- Double click
- Mobil uygulamalarda timeout / yeniden deneme
Idempotency yoksa:
- Çift sipariş
- Çift ödeme
- Stok hatası
- Gereksiz e-posta / bildirim
gibi kritik problemler oluşur.
Çözüm: Idempotency Key
- Client her request için benzersiz bir Idempotency-Key üretir (genelde UUID)
- Backend bu key’i kısa TTL ile saklar (çoğunlukla Redis)
- Aynı key tekrar gelirse işlem tekrarlanmaz, önceki sonuç döndürülür
if (await redis.exists(key)) {
return cachedResponse;
}
const result = await processPayment();
await redis.set(key, JSON.stringify(result), "EX", 300);
return result;
3) Rate Limiting
Rate Limiting Nedir?
Rate limiting, bir kullanıcı/IP’nin belirli bir sürede kaç istek atabileceğini sınırlamaktır.
Amaçlar
- Brute-force’u engellemek
- DDoS etkisini azaltmak
- Sunucu maliyetini ve yükü kontrol etmek
Yaygın Algoritmalar
- Fixed Window: “Dakikada 100 istek” (sınırda yığılma olabilir)
- Sliding Window: Daha hassas zaman kaydırmalı kontrol
- Token Bucket: En esnek ve popüler yaklaşım (jeton tüket/yenile)
Uygulamada Redis, bu sayaçları hızlı tutmak için sıkça kullanılır.
Üçü Birlikte Nasıl Çalışır?
Para transferi gibi kritik bir endpoint düşünelim:
- Rate Limiting: Kullanıcının saniyede çok sayıda transfer denemesini engeller
- Idempotency: Aynı transfer isteği tekrar gelirse ikinci kez işlem yapmaz
- Caching: Okuma ağırlıklı veriler (ör. hesap özeti) hızlı sunulur; işlem sonrası cache güncellenir veya temizlenir