SSE — wat is het, Server-Sent Events en eenrichtingsstreaming

Auteur: IT Sectr Gepubliceerd: 2026-06-02 Leestijd: 8 min

SSE (Server-Sent Events) — W3C-standaard waarmee de server via een enkele HTTP-verbinding in eenrichtingsmodus gegevens naar de client kan streamen. In tegenstelling tot WebSocket werkt SSE over gewone HTTP en vereist het geen speciaal protocol of bibliotheek aan de clientzijde. Volgens de W3C HTML Living Standard (2025) specificatie wordt EventSource API ondersteund in alle moderne browsers, waaronder Chrome, Firefox, Safari en Edge.

Belangrijkste punten

  • SSE — standaard voor eenrichtingsgegevensoverdracht van server naar client via een HTTP-verbinding.
  • EventSource API — ingebouwde browserinterface voor het ontvangen van SSE zonder externe bibliotheken.
  • Automatisch opnieuw verbinden — de browser herstelt automatisch de verbinding bij onderbreking.
  • Tekstprotocol — gegevens worden verzonden in text/event-stream formaat met een eenvoudig tekstformaat.
  • Eenrichtingscommunicatie — SSE is geschikt voor meldingen, nieuwsfeeds, tickers en monitoring, maar niet voor chats.

Wat is SSE?

SSE (Server-Sent Events) — technologie waarmee een webserver op elk moment na het tot stand brengen van de verbinding gegevens naar de client kan sturen. Het is gestandaardiseerd door WHATWG als onderdeel van de HTML Living Standard en gebruikt het MIME-type text/event-stream. SSE ondersteunt het verzenden van tekstgegevens met de mogelijkheid om een bericht-ID, gebeurtenistype en herverbindingsvertraging op te geven.

In tegenstelling tot WebSocket, dat een bidirectioneel protocol en een upgrade-verzoek vereist, werkt SSE over gewone HTTP. De server stelt de header Content-Type: text/event-stream in, stuurt gegevens in delen en houdt de verbinding open. De client ontvangt gegevens via de browser-EventSource API, die automatisch de stream parsed en gebeurtenissen genereert.

Volgens CanIUse (2025) wordt EventSource API wereldwijd in 97,5% van de browsers ondersteund. Het wordt niet ondersteund in Internet Explorer en sommige mobiele browsers (Samsung Internet tot versie 7.0). Voor deze gevallen zijn er polyfills die EventSource emuleren via XHR streaming. SSE werkt niet met HTTP/1.1 pipelining, maar is volledig compatibel met HTTP/2 server push.

Geschiedenis en standaardisatie

SSE werd in 2009 voorgesteld als onderdeel van de HTML5-specificatie onder de naam Server-Sent DOM Events. De eerste implementatie verscheen in Opera 9.0, daarna in Firefox 6.0 (2011), Chrome 9.0 (2011) en Safari 5.0 (2010). In 2015 werd de specificatie afgesplitst naar een aparte sectie van de HTML Living Standard. Ondanks een decennium aan geschiedenis blijft SSE minder populair dan WebSocket vanwege zijn eenrichtingsaard.

Hoe werkt SSE

Het werkingsmechanisme van SSE is als volgt: de client maakt een EventSource-instantie met de URL van het serverendpoint. De browser stuurt een GET-verzoek met de header Accept: text/event-stream. De server antwoordt met status 200 OK en de header Content-Type: text/event-stream, waarna hij begint met het verzenden van gegevens in event-stream-formaat. De verbinding blijft open totdat de server een terminatiesignaal stuurt of de client close() aanroept.

Aan serverzijde worden gegevens in delen verzonden (chunked transfer encoding). Elk gegevensblok is een tekstbericht bestaande uit veldregels (event, data, id, retry). De server kan op elk moment berichten sturen, wat SSE ideaal maakt voor meldingen en statusupdates. De verbinding vereist geen constante heartbeat-pakketuitwisseling (zoals WebSocket), hoewel het retry-veld de frequentie van herverbinding regelt.

Volgens prestatietests (2024) biedt SSE een doorvoer van maximaal 10.000 berichten per seconde per verbinding bij een berichtgrootte van 256 bytes. Aan serverzijde verbruikt elke SSE-verbinding ongeveer 5–10 KB geheugen, waardoor een enkele server 50.000+ gelijktijdige verbindingen kan ondersteunen met 1 GB RAM. Dit is aanzienlijk minder dan WebSocket vanwege het ontbreken van een binair protocol.

Event-stream formaat

Text/event-stream formaat — een eenvoudig tekstprotocol waarbij elk bericht bestaat uit benoemde velden gescheiden door nieuwe regeltekens. Elk veld heeft het formaat „Veldnaam: waarde”. Berichten worden gescheiden door twee nieuwe regeltekens ( ).

Ondersteunde velden: event (gebeurtenistype, standaard message), data (gegevensreeks, kan meerregelig zijn), id (laatste gebeurtenis-ID, opgeslagen in Last-Event-ID), retry (herverbindingstijd in milliseconden). Opmerkingen beginnen met een dubbele punt (:) en worden genegeerd door de parser, maar kunnen worden gebruikt voor heartbeat.

VeldVerplichtDoel
eventNeeGebeurtenistype (standaard message)
dataJaGegevensreeks van het bericht
idNeeGebeurtenis-ID voor Last-Event-ID
retryNeeHerverbindingsvertraging in ms

Voorbeeld van event-stream

text
: heartbeat comment
event: update
data: {"user": "Alice", "action": "typing"}
id: 1001

event: notification
data: {"type": "info", "text": "New version available"}
data: {"type": "action", "url": "/upgrade"}
retry: 3000

event: close
data: Session ended

EventSource API aan clientzijde

EventSource API — de ingebouwde browserinterface voor het ontvangen van SSE. Om een verbinding te maken volstaat het om de constructor aan te roepen met de URL van het endpoint. EventSource brengt automatisch de verbinding tot stand, beheert herverbinding en parsed inkomende berichten naar JavaScript-gebeurtenissen.

EventSource-gebeurtenissen: open (verbinding tot stand gebracht), message (bericht ontvangen zonder opgave van event), error (verbindingsfout). Voor aangepaste gebeurtenissen (event: custom) kan addEventListener met de gebeurtenisnaam worden gebruikt. EventSource stuurt automatisch de header Last-Event-ID bij herverbinding, waardoor de server de stroom kan hervatten vanaf het onderbroken punt.

Volgens MDN-documentatie (2025) ondersteunt EventSource CORS en het verzenden van credentials (withCredentials). Voor het verzenden van aangepaste headers of verzoekbody is EventSource niet geschikt — handmatige implementatie via fetch + ReadableStream is vereist. EventSource ondersteunt geen binaire gegevens — alleen tekst en JSON.

Client-side JavaScript-code

js
const eventSource = new EventSource('/api/events/stream');

eventSource.addEventListener('open', () => {
    console.log('SSE-verbinding geopend');
});

eventSource.addEventListener('message', (event) => {
    const data = JSON.parse(event.data);
    console.log('Ontvangen:', data);
    renderUpdate(data);
});

eventSource.addEventListener('notification', (event) => {
    const notification = JSON.parse(event.data);
    showNotification(notification.text);
});

eventSource.addEventListener('error', (error) => {
    console.error('SSE-fout:', error);
    // Automatische browser-herverbinding
});

// Verbinding sluiten
eventSource.close();

SSE versus WebSocket: vergelijking

SSE en WebSocket — verschillende technologieën voor real-time communicatie, elk met hun eigen sterke punten. WebSocket is geschikt voor bidirectionele gegevensuitwisseling (chats, games, gezamenlijk bewerken), SSE voor eenrichtingsstromen van server naar client (meldingen, nieuwsfeeds, tickers).

Het belangrijkste verschil — WebSocket vereist een upgrade-verzoek van HTTP/1.1 naar het WebSocket-protocol (ws://), wat door bedrijfsproxy's kan worden geblokkeerd. SSE werkt over gewone HTTP, gaat door alle proxy's heen en vereist geen speciale serverconfiguratie. SSE is ook eenvoudiger te implementeren — de server heeft geen extra bibliotheek nodig, het volstaat om het HTTP-antwoord correct te formatteren.

Volgens vergelijkende tests (2024) ondersteunt SSE op één serverproces 30–50% meer verbindingen dan WebSocket vanwege het eenvoudigere protocol. De latentie van SSE is echter hoger (50–200 ms versus 10–50 ms voor WebSocket) omdat SSE chunked HTTP gebruikt, geen volledig bidirectionele stroom met binaire frames.

KenmerkSSEWebSocket
RichtingServer → clientBidirectioneel
ProtocolHTTP (text/event-stream)ws:// / wss:// (RFC 6455)
Browsers97,5% (ingebouwde EventSource)97% (ingebouwde WebSocket)
GegevensAlleen tekst / JSONTekst + binair (Blob, ArrayBuffer)
Proxy-verwerkingGaat door alle proxy'sVereist proxy-configuratie
HerverbindingAutomatisch (browser)Handmatige implementatie
GeschiedenisLast-Event-IDGeen ingebouwde geschiedenis

SSE implementeren op de server

SSE implementeren op de server vereist geen bibliotheken — het volstaat om de juiste HTTP-headers in te stellen en gegevens te verzenden in text/event-stream formaat. Laten we een voorbeeld bekijken in Node.js met behulp van de ingebouwde http-module. De server stelt de headers Content-Type en Cache-Control in en stuurt vervolgens elke N seconden berichten.

Volgens MDN Web Docs (2025) zijn de verplichte headers voor SSE: Content-Type: text/event-stream, Cache-Control: no-cache en Connection: keep-alive. Zonder Cache-Control kan de browser de SSE-stream cachen, wat leidt tot het stoppen van de levering. Connection: keep-alive geeft de browser expliciet aan de verbinding open te houden.

Servercode in Node.js

js
const http = require('http');

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

    let eventId = 0;
    const interval = setInterval(() => {
        eventId++;
        res.write(`id: ${eventId}\n`);
        res.write(`event: update\n`);
        res.write(`data: {"tijd": "${new Date().toISOString()}", "id":${eventId}}\n\n`);
    }, 2000);

    req.on('close', () => {
        clearInterval(interval);
    });
}).listen(3000);

SSE in Python (Flask)

python
from flask import Response, Flask
import time
import json

app = Flask(__name__)

@app.route('/stream')
def stream():
    def generate():
        event_id = 0
        while True:
            event_id += 1
            data = json.dumps(
                {'ticker': 'AAPL', 'price': 150.25})
            yield f'id: {event_id}\nevent: price\ndata: {data}\n\n'
            time.sleep(1)
    return Response(generate(),
        mimetype='text/event-stream')

SSE in mobiele apps

Gebruik van SSE in mobiele apps wordt beperkt door het ontbreken van een native EventSource-implementatie voor iOS en Android. Op mobiele platforms wordt SSE geïmplementeerd via externe bibliotheken: op iOS via URLSession met NSURLProtocol, op Android via OkHttp met SSE-ondersteuning (okhttp-sse). Voor React Native en Flutter zijn pakketten beschikbaar die EventSource emuleren.

Op iOS is native SSE-implementatie mogelijk via URLSessionDataDelegate. Bij het ontvangen van gegevens in de methode urlSession(_:dataTask:didReceive:) verzamelt de app een buffer en parsed handmatig het event-stream-formaat. Volgens iOS-ontwikkelblog (2024) is het batterijverbruik bij SSE op iOS 40% lager dan bij een constante WebSocket-verbinding, vanwege het ontbreken van heartbeat-pakketten.

Op Android biedt OkHttp de klasse EventSource.Factory voor het abonneren op SSE-streams. Android-apps kunnen SSE gebruiken voor meldingen wanneer FCM niet beschikbaar is of voor gegevenssynchronisatie op de achtergrond. SSE op Android werkt goed met WorkManager voor langdurige achtergrondtaken. Volgens OkHttp-documentatie (2025) ondersteunt okhttp-sse automatische herverbinding met een aangepaste listener.

Veelgestelde vragen

Waarin verschilt SSE van WebSocket?

SSE — eenrichtingsverzending (server → client) via HTTP, vereist geen bibliotheken aan clientzijde. WebSocket — bidirectionele verzending met binair protocol. SSE is eenvoudiger te implementeren, WebSocket is geschikt voor taken waarbij de client ook gegevens verzendt.

Ondersteunt SSE binaire gegevens?

Nee, SSE verzendt alleen tekstgegevens. Voor binaire gegevens (afbeeldingen, audio) is Base64-codering vereist, wat de grootte met 33% verhoogt. Voor binaire streams kun je beter WebSocket gebruiken.

Hoe gaat SSE om met verbindingsonderbrekingen?

EventSource maakt automatisch opnieuw verbinding bij onderbreking. De vertragingstijd wordt ingesteld via het retry-veld in de stream (standaard 1000 ms). Bij herverbinding stuurt de browser de header Last-Event-ID, waardoor de server de stroom kan hervatten vanaf het onderbroken punt.

Hoeveel SSE-verbindingen kan een browser aan?

Elke browser heeft een limiet voor het aantal gelijktijdige HTTP-verbindingen met één domein. Voor HTTP/1.1 — 6–8 verbindingen per domein, voor HTTP/2 — tot 100. SSE gebruikt één verbinding, dus er is geen concurrentie met andere verzoeken.

Kan SSE worden gebruikt voor chat?

SSE is alleen geschikt voor het ontvangen van berichten (inkomend). Voor het verzenden van berichten (uitgaand) is een apart HTTP-verzoek (POST) nodig. Voor een volledige chat is het handiger om WebSocket of Socket.IO met bidirectionele communicatie in één verbinding te gebruiken.

Samenvatting

  • SSE — standaard voor eenrichtingsgegevensoverdracht van server naar client via een gewone HTTP-verbinding zonder extra bibliotheken.
  • EventSource API — ingebouwde browserinterface, ondersteund door 97,5% van de moderne browsers.
  • Eenvoudig tekstprotocol text/event-stream met velden event, data, id en retry.
  • Automatische herverbinding met Last-Event-ID-ondersteuning voor hervatting van de stroom vanaf het onderbroken punt.
  • Efficiëntie — SSE ondersteunt meer verbindingen op de server (50.000+) in vergelijking met WebSocket dankzij een eenvoudiger protocol.
  • Op mobiele platforms wordt SSE geïmplementeerd via OkHttp (Android) of URLSession (iOS) met handmatige parsing van de stream.
  • Voor eenrichtingsstromen (meldingen, feeds, tickers) kies SSE, voor bidirectionele communicatie — WebSocket of Socket.IO.

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook