~/zafer
Tüm yazılara dön
3 dk okuma

Debounce, Throttle, Pagination ve Search: Sık Sorulan Mülakat Soruları

Giriş

Bir arama kutusuna her harf yazdığınızda arka planda ne oluyor? 1 milyon kayıtlık bir veritabanında "sayfa sayfa" veri çekmek nasıl işliyor? Bu yazıda frontend ve backend mülakatlarında sıkça karşılaşılan bu konuları toparladık.


1. Pagination: Offset vs Cursor-Based

Offset-based pagination

LIMIT ve OFFSET kullanılır:

GET /items?limit=20&offset=40

Artıları: Basit, belirli bir sayfaya direkt atlanabilir, toplam sayfa sayısı kolay hesaplanır.

Eksileri: Büyük offset'lerde veritabanı performansı düşer; veri sayfalar arası değişirse (ekleme/silme) kayıtlar kayar, tutarsızlık oluşur.

Cursor-based (keyset) pagination

Sayfa numarası yerine "son görülen kaydın işaretçisi" kullanılır:

GET /items?limit=20&after=item_12345

Artıları: Veri boyutundan bağımsız performans, değişen veride tutarlı sonuç, sonsuz kaydırma (infinite scroll) için ideal.

Eksileri: Rastgele bir sayfaya direkt atlanamaz, uygulaması biraz daha karmaşık.


2. Search-as-you-type: Debounce ve Throttle

Problem

1M kayıtlık bir veri setinde her tuşa basışta arama tetiklenirse:

  • "a" yazınca istek gider
  • "ab" olunca yeni istek gider
  • "abc" olunca bir istek daha gider

Bu durumda race condition oluşabilir: "abc" için giden istek önce dönebilir, ardından geç kalan "ab" isteği dönüp ekranı yanlış sonuçla günceller. Yani kullanıcı "abc" yazmışken ekranda "ab" sonuçları görünebilir.

Debouncing

Kullanıcı yazmayı bırakana kadar (örneğin 300ms) bekle, sonra ara:

let timer;
input.addEventListener('input', (e) => {
  clearTimeout(timer);
  timer = setTimeout(() => search(e.target.value), 300);
});

Throttling

"En fazla X ms'de bir çalıştır" mantığı — sürekli tetiklenen olaylarda (scroll, resize gibi) belirli aralıklarla çalışır.

Race condition çözümü: Request cancellation

let controller;
async function search(query) {
  if (controller) controller.abort(); // önceki isteği iptal et
  controller = new AbortController();
  const res = await fetch(`/search?q=${query}`, { signal: controller.signal });
}

3. Terimler Özeti

Terim Ne işe yarar
Debounce Yazma bitene kadar isteği erteler
Throttle İstekleri belirli aralıklarla sınırlar
Race condition Geç dönen eski cevabın ekranı yanlış güncellemesi
AbortController Eski isteği iptal edip sadece son isteğin cevabını kullanmak
Offset pagination Sayfa numarasına göre veri çekme
Cursor pagination Son kayda göre veri çekme

4. Bu Konularla İlgili Sık Sorulan Mülakat Soruları

Debounce / Throttle

  • Debounce ile throttle arasındaki fark nedir, ne zaman hangisini kullanırsın?
  • Debounce fonksiyonunu sıfırdan yaz (JavaScript'te)
  • Throttle fonksiyonunu sıfırdan yaz
  • "Leading" ve "trailing" debounce nedir, farkı ne?
  • Search input'u için neden debounce, scroll event'i için neden throttle daha mantıklı?

Race Condition / Async

  • Search-as-you-type yaparken eski isteğin geç dönüp ekranı yanlış güncellemesini nasıl engellersin?
  • AbortController nedir, ne işe yarar?
  • Promise.all ile Promise.allSettled arasındaki fark nedir?
  • İki API isteği aynı state'i güncellerse ne tür bug'lar oluşabilir?

Pagination

  • Offset-based ile cursor-based (keyset) pagination arasındaki fark nedir?
  • Neden büyük veri setlerinde OFFSET performans sorunu yaratır?
  • Infinite scroll nasıl implemente edilir, hangi pagination yöntemi buna daha uygun?
  • Sayfalar arası veri değişirse (ekleme/silme) offset pagination'da ne gibi sorun çıkar?

Arama / Büyük Veri

  • 1M+ kayıtta full-text search nasıl yapılır? (Elasticsearch, Postgres full-text search, trigram index vb.)
  • Database index nedir, arama sorgusunu nasıl hızlandırır?
  • LIKE '%query%' neden yavaştır, alternatifi nedir?
  • N+1 query problemi nedir?

Genel Sistem Tasarımı

  • "Google gibi bir arama kutusu tasarla" — nelere dikkat edersin? (debounce, cache, cancel, loading state, error handling)
  • Bir e-ticaret sitesinde ürün listesi sayfalama nasıl tasarlanır?
  • Rate limiting nedir, nasıl implemente edilir?

Hazırlayan: Claude