Real-time web geliştirirken ilk karar: WebSocket mu, Server-Sent Events mi? İkisi de tarayıcıya anlık veri iter ama mimari felsefeleri farklıdır. Bu yazı iki teknolojiyi somut kriterlerle karşılaştırır ve hangi senaryoda hangisinin daha uygun olduğunu gösterir.

Temel Fark

İlgili rehberler: Yazılım geliştirme süreçleri · PostgreSQL optimizasyonu · Git ileri seviye komutlar · Redis nedir, nasıl kullanılır · Docker ile deploy

WebSocketSSE
YönFull-duplex (iki yönlü)Server → Client tek yön
Protokolws:// / wss:// (HTTP upgrade)HTTP/1.1 veya HTTP/2
ReconnectionManuel / Socket.ioOtomatik (EventSource)
BinaryEvetHayır (text only)
Proxy uyumluluğuUpgrade gerekliStandart HTTP
Browser support~98%~95% (IE yok)
Header authBağlantı kurulurken bir kezHer reconnect''te

SSE — En Basit Başlangıç

// Sunucu — Express
app.get('/events', (req, res) => {
    res.set({
        'Content-Type': 'text/event-stream',
        'Cache-Control': 'no-cache',
        'Connection': 'keep-alive',
        'X-Accel-Buffering': 'no'  // nginx buffering kapat
    });

    const send = (data, event = null) => {
        if (event) res.write(`event: ${event}\n`);
        res.write(`data: ${JSON.stringify(data)}\n\n`);
    };

    send({ status: 'connected' }, 'init');

    const interval = setInterval(() => {
        send({ time: new Date().toISOString(), cpu: os.loadavg()[0] });
    }, 1000);

    req.on('close', () => clearInterval(interval));
});
// Client
const es = new EventSource('/events');
es.addEventListener('init', e => console.log('Connected', JSON.parse(e.data)));
es.onmessage = e => {
    const data = JSON.parse(e.data);
    document.getElementById('cpu').textContent = data.cpu;
};
es.onerror = () => console.warn('SSE error, auto-reconnecting...');
// Tarayıcı kopuk bağlantıyı otomatik tekrar kurar — manuel retry kodu yok

WebSocket — Full Duplex

// Sunucu — ws library
const { WebSocketServer } = require('ws');
const wss = new WebSocketServer({ port: 8080 });

wss.on('connection', (ws, req) => {
    console.log('New client:', req.socket.remoteAddress);
    ws.send(JSON.stringify({ type: 'welcome' }));

    ws.on('message', data => {
        const msg = JSON.parse(data);
        if (msg.type === 'ping') ws.send(JSON.stringify({ type: 'pong' }));
    });

    ws.on('close', () => console.log('Disconnected'));
});

// Broadcast
function broadcast(data) {
    wss.clients.forEach(c => {
        if (c.readyState === c.OPEN) c.send(JSON.stringify(data));
    });
}
// Client
const ws = new WebSocket('wss://example.com/ws');
ws.onopen = () => ws.send(JSON.stringify({ type: 'ping' }));
ws.onmessage = e => console.log(JSON.parse(e.data));
ws.onclose = () => setTimeout(() => reconnect(), 3000);
// Reconnection mantığını kendin yazmalısın

Socket.io — Abstraksiyon

WebSocket''un reconnection, fallback (long polling), room, namespace gibi özelliklerini hazır getirir. Ancak ağır bir abstraction — sadece bir gereklilik varsa raw ws ile başlayın.

const io = require('socket.io')(server);

io.on('connection', socket => {
    socket.join('room:general');
    socket.on('chat:message', msg => {
        io.to('room:general').emit('chat:message', {
            from: socket.id, text: msg, at: Date.now()
        });
    });
});

Ne Zaman Hangisi?

SSE seçin:

  • Sunucudan tek yönlü bildirim: notification, live score, stock price, ChatGPT stream
  • Basit kod tabanı: native EventSource + auto-reconnect
  • HTTP/2 üzerinden: aynı connection birden fazla stream''e
  • Nginx/proxy problemi olmasın: standart HTTP
  • LLM streaming (OpenAI, Anthropic API''leri)

WebSocket seçin:

  • Çift yönlü iletişim: chat, collaborative editing, multiplayer oyun
  • Düşük latency zorunlu: trading, gaming
  • Binary data: dosya transferi, streaming
  • Yüksek mesaj frekansı: SSE''nin HTTP header overhead''i var

Ölçeklendirme

Her iki protokol de stateful connection tutar; load balancer''ın sticky session''a alışması gerekir. Cluster''a yaydığınızda mesaj broadcast''i için Redis Pub/Sub veya NATS kullanın.

// Socket.io + Redis adapter
const { createAdapter } = require('@socket.io/redis-adapter');
const pubClient = new Redis();
const subClient = pubClient.duplicate();
io.adapter(createAdapter(pubClient, subClient));
// Artık tüm Node instance'ları mesajları görür

Nginx Proxy Yapılandırması

# WebSocket için upgrade header proxy'lenmeli
location /ws {
    proxy_pass http://backend;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 86400s;  # uzun bağlantı
}

# SSE için buffering kapat
location /events {
    proxy_pass http://backend;
    proxy_buffering off;
    proxy_cache off;
    proxy_read_timeout 86400s;
}
Uyarı
Cloudflare free plan WebSocket''u 100 saniyede bir kesmez ama bazı enterprise proxy''ler 60 saniyede idle timeout yapar. Heartbeat (ping) mesajı her 30 saniyede gönderin.

Authentication

WebSocket handshake''i HTTP''dir — cookie/header auth edebilirsiniz. Ancak bağlantı kurulduktan sonra yeniden auth yapamazsınız (token expire ederse). Uzun süreli bağlantılarda token rotation planı gerekir. SSE''de her reconnect''te yeniden auth kolaydır.

Modern Yazılım Geliştirme ve DevOps Pratikleri

Profesyonel yazılım geliştirme süreci üç pillar üzerine kuruludur: kaynak kontrolü (Git + GitHub/GitLab pull request akışı, code review zorunlu), CI/CD pipeline (otomatik test + lint + build + deploy), ve gözlemlenebilirlik (Sentry/Datadog/Grafana ile log, metric, trace toplama). Test piramidi (unit > integration > e2e) ile kod kalitesini garantilemek, mikroservis mimarisinde Docker container ve Kubernetes orkestrasyonu kullanmak, REST veya GraphQL API tasarımında OpenAPI/GraphQL Schema sözleşmesi tutmak modern standardlardır. Yazılım geliştirme yaşam döngüsü boyunca (gereksinim → tasarım → implementasyon → test → deploy → bakım) Agile/Scrum sprintleri 1-2 hafta, DevOps takımları sürekli teslim (continuous delivery) prensibiyle çalışır.

Real-time özellik geliştirme

WebSocket, SSE veya hybrid mimari ile real-time özellik geliştirmemiz için iletişime geçin

WhatsApp