Raporlama sisteminde bir endpoint vardı, 50 bin satırlık CSV üretiyordu. İlk tasarımda tek istek, tek response. Çalışıyordu ama büyük müşterilerde 30 saniyeyi buluyordu, timeout’lar başladı. Streaming’e geçtik, problemler değişti. Hangisinin ne zaman doğru olduğunu gerçek senaryolarla paylaşayım.
Tek batch response
Client bir istek atıyor, server hepsini hazırlayıp tek response’ta döndürüyor. JSON array, CSV, XML, fark etmez.
Artıları:
– Basit, her HTTP client desteği var.
– Cache’lemek kolay, cdn mantığıyla.
– Idempotent. Başarısız olursa tekrar deneyin, problemi yok.
– Client tarafında state yönetimi yok.
Eksileri:
– Response büyüdükçe memory baskısı. 500 MB response’u serialize etmek server’da RAM patlatır.
– İlk byte’a kadar tüm hesaplama bitmeli, TTFB yüksek.
– Client da tamamını beklemeli, kullanıcı 25 saniye boyunca boş ekran görür.
– Timeout’lar artıyor, proxy’lerde varsayılan 30 saniye.
Streaming
Server response’u parça parça yazıyor, client parça parça okuyor ve işliyor. HTTP chunked encoding, Server-Sent Events (SSE), WebSocket, NDJSON gibi yöntemler var.
Artıları:
– İlk sonuç hızlı gelir, algılanan performans iyi.
– Memory baskısı dengeli. Sonuçlar üretildikçe gönderilir.
– Büyük veri setleri için ölçeklenebilir.
– Kullanıcı progress görür.
Eksileri:
– Tüm client’lar her protokolü desteklemiyor. Eski HTTP 1.0 proxy’ler chunked’a sorun çıkarır.
– Hata yönetimi zor. Response’un ortasında hata olursa ne yapılır?
– Idempotency riski. Yeniden deneme durumunda duplicate satır gönderilebilir.
– CDN cache imkansız.
– Test etmek zahmetli.
Karar kriterlerim
Veri hacmi
– Küçük (1 MB altı): batch.
– Orta (1-50 MB): batch hala rahat.
– Büyük (50 MB üstü): streaming veya pagination.
Gerçek zamanlılık
– Veri üretildikçe gelmeli: streaming.
– Tamamı hazır olmadan anlamı yok: batch.
Örnek: LLM cevap üretimi kelime kelime gelmeli, streaming şart. Ama rapor CSV’si ortada yarım gelirse kullanıcı hepsini bekler, batch OK.
Altyapı
– HTTP/1.1 arkasında, nginx proxy’li: streaming’de buffer ayarları önemli.
– HTTP/2 varsa streaming çok daha rahat.
– CDN arkasındaysa streaming’i bypass etmek lazım.
– Serverless (AWS Lambda) istiyorsanız timeout sınırı var, batch daha uygun.
Hata yönetimi
– Işlem atomik olmalı: batch.
– Kısmi sonuç değerli: streaming.
Benim raporlama sisteminde streaming’e geçince başta sorun çıkardı, nginx’te proxy_buffering off yazmayı unutmuştum. Nginx response’un tümünü biriktiriyordu, streaming manasını kaybetti. Ayarları düzeltince gerçek streaming açıldı.
Pratik bir karışım da var, “chunked batch”. Örneğin 10 bin satırlık veri istenirse server 1000’lik bloklar halinde NDJSON gönderir. Her satır ayrı JSON, her line break bir chunk. Client stream olarak okur ve parse eder. Tek bir satırın hatası diğerlerini etkilemez, her line bağımsız. Error handling da kolay, her satır kendi başına.
Son tecrübem: checkout history endpoint’i. Kullanıcı son 5 yılın alışveriş geçmişini istiyor. Ortalama 500 satır, ama VIP müşteri 5000 satır. Tek bir endpoint için hem stream hem batch yaz dedim, header ile seçim. Accept: application/x-ndjson ise streaming, Accept: application/json ise batch. Client kendi tercihini bildirdi. Mobil batch kullandı (parse kolay), raporlama ekranı streaming kullandı (progress göster).
Bir protokol tercih ederken client’ın tüketim şeklini düşünmek karar noktası. API tüketiminin temel kuralı bu.