Gerçek zamanlı özellik geliştiren ekipler çoğu zaman doğrudan WebSocket’e yöneliyor. Oysa yalnızca sunucudan istemciye veri akışı gereken durumlarda Server-Sent Events (SSE) çok daha sade, bakım maliyeti daha düşük ve mevcut HTTP altyapısıyla daha uyumlu bir seçenek olabilir.
SSE Nedir? Problem Ne?
Web uygulamalarında real-time veri göstermek istiyorsunuz. Stock price’lar, notification’lar, live score’lar, chat mesajları… Klasik HTTP request-response modeli bunun için uygun değil çünkü client sürekli “yeni bir şey var mı?” diye sormak zorunda (polling). Bu hem verimsiz hem de real-time değil.
İşte SSE, server’ın client’a sürekli veri “push” edebilmesini sağlayan bir teknoloji. HTTP protokolü üzerinden, tek yönlü (server’dan client’a), sürekli bir veri akışı kuruyorsunuz. Client bir kere bağlanıyor, server istediği zaman veri gönderiyor.
SSE vs WebSocket vs Long Polling
Hemen karşılaştıralım çünkü bu kafa karışıklığı çok yaygın:
Long Polling: Client request atıyor, server yeni veri gelene kadar bekletiyor. Veri gelince response dönüyor, client hemen yeni request atıyor. Hack gibi bir çözüm, modern değil.
WebSocket: Full-duplex, bi-directional communication. Hem client hem server istediği zaman mesaj gönderebiliyor. Güçlü ama complex. Ayrı bir protokol (ws://), proxy/firewall sorunları olabiliyor.
SSE: Unidirectional (sadece server→client), standart HTTP üzerinden çalışıyor. Otomatik reconnection var. Browser native support var. Basit!
Ne Zaman SSE Kullanmalı?
SSE şu durumlarda iyi çalışır:
- Live notifications: Kullanıcıya real-time bildirimler
- News feed / Timeline: Twitter gibi sürekli güncellenen feed’ler
- Progress updates: Uzun süren işlemlerin durumu
- Stock tickers: Finansal veri stream’leri
- Live scores: Spor skorları, seçim sonuçları
- Monitoring dashboards: Server metrikleri, log stream’leri
Eğer client’ın da server’a sürekli veri göndermesi gerekmiyorsa (chat uygulaması gibi), SSE genelde WebSocket’ten daha iyi seçim!
SSE’nin Teknik Detayları
SSE aslında çok basit bir protokol. Server, Content-Type: text/event-stream header’ı ile response başlatıyor ve connection’ı açık tutuyor. Sonra plain text formatında event’ler gönderiyor:
data: Hello World\n\n
data: {"user": "john", "message": "Hi!"}\n\n
event: notification\ndata: New message arrived\n\n
Format bu kadar basit! Her mesaj data: ile başlıyor, çift newline ile bitiyor. İsterseniz event: ile event type belirtebiliyorsunuz, id: ile mesaj ID’si verebiliyorsunuz.
Browser Support ve Automatic Reconnection
Modern browser’ların hepsi SSE’yi destekliyor (IE hariç tabii ki, ama kim kullanıyor ki?). En güzel özelliklerinden biri automatic reconnection. Connection koparsa, browser otomatik olarak tekrar bağlanmaya çalışıyor. Kaldığı yerden devam etmek için son event ID’sini Last-Event-ID header’ında gönderiyor.
Bu davranış pratikte önemlidir. Network kesintileri veya kısa servis yeniden başlatmalarında çoğu durumda ek reconnect kodu yazmadan akış devam eder.
HTTP/2 ve Multiplexing
SSE’nin eski bir problemi vardı: Browser’lar aynı domain’e maksimum 6 concurrent connection açabiliyordu (HTTP/1.1’de). Yani 6 SSE connection açarsanız, başka request atamazdınız.
HTTP/2 ile bu problem büyük ölçüde hafifledi. Multiplexing sayesinde aynı bağlantı üzerinde birden fazla isteği yönetmek daha kolay hale geldi ve SSE çoğu modern altyapıda rahatça kullanılabilir oldu.
Basit Örnekler
Server tarafı (Node.js/Express):
app.get("/events", (req, res) => {
// Set headers for SSE
res.writeHead(200, {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive",
});
// Send initial message
res.write("data: Connected!\n\n");
// Send timestamp every second
const interval = setInterval(() => {
res.write(`data: ${new Date().toISOString()}\n\n`);
}, 1000);
// Clean up on client disconnect
req.on("close", () => {
clearInterval(interval);
});
});
Client tarafı (JavaScript):
// Create connection
const eventSource = new EventSource("/events");
// Handle messages
eventSource.onmessage = event => {
console.log("Received:", event.data);
};
// Handle specific event types
eventSource.addEventListener("notification", event => {
showNotification(event.data);
});
// Handle errors
eventSource.onerror = error => {
console.error("SSE error:", error);
};
Load Balancing ve Scaling
SSE connection’ları long-lived olduğu için load balancing’de dikkatli olmalısınız. Sticky sessions kullanmanız ya da event’leri Redis/RabbitMQ gibi bir message broker üzerinden dağıtmanız gerekebilir.
Scaling stratejileri:
- Horizontal scaling: Her server instance kendi client’larına hizmet verir
- Message broker pattern: Tüm event’ler broker’a gider, oradan client’lara dağıtılır
- Edge caching: CDN’ler SSE’yi destekliyor (Cloudflare, Fastly)
Authentication ve Security
SSE normal HTTP request gibi çalıştığı için, authentication kolay:
- Cookie-based auth çalışır
- Token’ı query parameter olarak gönderebilirsiniz
- Custom header’lar… olmaz (EventSource API desteklemiyor)
Security için:
- HTTPS kullanın (mutlaka!)
- CORS header’larını doğru ayarlayın
- Rate limiting uygulayın
- Connection limit koyun (per user)
SSE’nin Limitasyonları
Her teknoloji gibi SSE’nin de limitasyonları var:
Unidirectional: Sadece server→client. Client veri göndermek için normal HTTP request kullanmalı.
Text only: Binary data gönderemezsiniz. Base64 encoding gerekli.
No custom headers: EventSource API custom header desteklemiyor.
Connection limits: Eski browser’larda ve HTTP/1.1’de connection limit var.
Real-World Use Cases
GitHub: Pull request’lerdeki real-time update’ler SSE ile.
Twitter: Timeline update’leri (eski versiyonda).
Grafana: Monitoring dashboard’lardaki real-time metrikler.
Stock trading platforms: Price update’leri.
CI/CD tools: Build progress ve log streaming.
SSE vs WebSocket: Hangisini Seçmeli?
SSE seçin eğer:
- Sadece server→client veri akışı yeterliyse
- Basit implementation istiyorsanız
- HTTP infrastructure’ınız varsa (proxy, LB, firewall)
- Automatic reconnection istiyorsanız
- Text-based data gönderiyorsanız
WebSocket seçin eğer:
- Bi-directional communication gerekiyorsa
- Binary data transfer gerekiyorsa
- Çok düşük latency kritikse
- Custom protocol implement edecekseniz
Modern Alternatifler
WebTransport: WebSocket’in halefi gibi. QUIC protokolü üzerinde, daha hızlı.
gRPC-Web: gRPC’nin browser versiyonu. Streaming desteği var.
GraphQL Subscriptions: GraphQL üzerinden real-time data.
Ama çoğu use case için SSE hala en basit ve yeterli çözüm!
Performance Tips
Compression kullanın: Text data olduğu için gzip çok etkili.
Heartbeat gönderin: Connection’ın alive olduğundan emin olmak için.
Batch update’ler: Her küçük değişiklik için ayrı event göndermek yerine batch’leyin.
Event ID kullanın: Reconnection sonrası kaldığı yerden devam için.
Memory leak’lere dikkat: Disconnect olan client’ları temizlemeyi unutmayın!
Sonuç
SSE, her gerçek zamanlı problem için tek cevap değil; ama tek yönlü veri akışı gereken birçok senaryoda gereksiz karmaşıklığı azaltır. Özellikle bildirim, ilerleme durumu ve canlı panel gibi use case’lerde WebSocket’e göre daha okunabilir ve daha hızlı devreye alınan bir çözüm sunar.
Kısa öneri şu: önce veri yönünü ve bağlantı modelini netleştirin. İstemciden sunucuya sürekli mesaj gerekmiyorsa, ilk değerlendirilmesi gereken seçeneklerden biri SSE olmalı.