DEV Community

EME GUG
EME GUG

Posted on

WebSocket vs Server-Sent Events: choosing the right tool

Not every real-time feature needs WebSocket. Here's how to pick the right technology.

Quick Comparison

WebSocket SSE
Direction Bidirectional Server → Client only
Protocol ws:// HTTP
Reconnection Manual Automatic
Binary data Yes No (text only)
Browser support All modern All modern
Through proxies Sometimes issues Works everywhere
Complexity Higher Lower

Server-Sent Events (SSE)

Perfect for: notifications, live feeds, dashboards, progress bars.

Server (Node.js)

app.get('/events', (req, res) => {
    res.writeHead(200, {
        'Content-Type': 'text/event-stream',
        'Cache-Control': 'no-cache',
        'Connection': 'keep-alive',
    });

    const sendEvent = (data) => {
        res.write(`data: ${JSON.stringify(data)}\n\n`);
    };

    // Send initial data
    sendEvent({ type: 'connected', time: Date.now() });

    // Send updates
    const interval = setInterval(() => {
        sendEvent({ type: 'update', value: Math.random() });
    }, 1000);

    req.on('close', () => {
        clearInterval(interval);
    });
});
Enter fullscreen mode Exit fullscreen mode

Client

const source = new EventSource('/events');

source.onmessage = (event) => {
    const data = JSON.parse(event.data);
    console.log('Received:', data);
};

source.onerror = () => {
    console.log('Connection lost, reconnecting...');
    // EventSource reconnects automatically!
};
Enter fullscreen mode Exit fullscreen mode

That's it. No library needed. Auto-reconnection built in.

WebSocket

Perfect for: chat, gaming, collaborative editing, trading platforms.

Server (ws library)

const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', (ws) => {
    ws.on('message', (message) => {
        const data = JSON.parse(message);

        // Broadcast to all clients
        wss.clients.forEach((client) => {
            if (client.readyState === WebSocket.OPEN) {
                client.send(JSON.stringify({
                    user: data.user,
                    message: data.message,
                    time: Date.now()
                }));
            }
        });
    });

    ws.on('close', () => {
        console.log('Client disconnected');
    });
});
Enter fullscreen mode Exit fullscreen mode

Client

const ws = new WebSocket('ws://localhost:8080');

ws.onopen = () => {
    ws.send(JSON.stringify({ user: 'Alice', message: 'Hello!' }));
};

ws.onmessage = (event) => {
    const data = JSON.parse(event.data);
    displayMessage(data);
};

// Manual reconnection needed
ws.onclose = () => {
    setTimeout(() => {
        // Reconnect logic here
    }, 1000);
};
Enter fullscreen mode Exit fullscreen mode

Decision Framework

Do you need client → server communication?
├── Yes → Do you need it frequently (>1/sec)?
│   ├── Yes → WebSocket
│   └── No → SSE + regular HTTP POST
└── No → SSE
Enter fullscreen mode Exit fullscreen mode

Use SSE when:

  • Server pushes updates to client
  • Client actions use normal HTTP requests
  • You want simplicity and auto-reconnection
  • Examples: stock ticker, notifications, live scores

Use WebSocket when:

  • Both sides send messages frequently
  • Low latency matters (<50ms)
  • Binary data needed
  • Examples: multiplayer games, chat, live collaboration

The Hybrid Approach

Most apps benefit from combining both:

// SSE for real-time updates (notifications, feed)
const events = new EventSource('/api/events');

// Regular HTTP for user actions
async function sendMessage(text) {
    await fetch('/api/messages', {
        method: 'POST',
        body: JSON.stringify({ text })
    });
    // Server broadcasts via SSE to all connected clients
}
Enter fullscreen mode Exit fullscreen mode

Simpler than WebSocket, works through all proxies, auto-reconnects.


What do you use for real-time features? WebSocket, SSE, or something else?

Top comments (0)