---
term: 'Server-Sent Events vs. WebSockets vs. Polling'
seoTitle: 'SSE vs. WebSockets vs. Polling: Echtzeit-Transport wählen'
headline: 'Server-Sent Events vs. WebSockets vs. Polling: was sollten Sie verwenden?'
slug: sse-vs-websockets-vs-polling
category: api-realtime
shortDefinition: 'Polling ist ein Pull-Modell, bei dem Clients wiederholt fragen; SSE und WebSockets halten eine Verbindung offen, damit der Server in Echtzeit senden kann.'
relatedTerms:
  - websockets-real-time-sync
  - real-time-live-queries
  - pub-sub-pattern
  - api-payload-optimization
contrastsWith:
  - websockets-real-time-sync
aboutTerms:
  - 'Server-Sent Events (SSE)'
  - 'WebSockets'
  - 'Long Polling'
  - 'Short Polling'
faq:
  - question: 'Was ist besser, SSE oder WebSockets?'
    answer: 'Keines von beiden generell – die Frage ist die Richtung. SSE ist das einfachere Werkzeug, wenn Daten in eine Richtung fließen, vom Server zum Client: gewöhnliches HTTP, automatische Wiederverbindung, funktioniert durch normale Proxys. WebSockets verdienen ihre zusätzliche Komplexität, wenn auch der Client in Echtzeit senden muss – Chat, Spiele, kollaboratives Bearbeiten.'
  - question: 'Ist SSE schneller als Polling?'
    answer: 'Bei der Zustelllatenz eindeutig: Ereignisse kommen an, wenn sie passieren, während Polling im Mittel das halbe Poll-Intervall plus eine Umlaufzeit kostet. Es ist außerdem günstiger – eine gehaltene Verbindung statt einer Folge größtenteils leerer Anfrage-Antwort-Zyklen, von denen jeder den vollen HTTP-Header-Overhead bezahlt.'
  - question: 'Wann sollte ich Long Polling einsetzen?'
    answer: 'Als Rückfalloption, nicht als erste Wahl: Es existiert für Umgebungen, in denen dauerhafte Verbindungen scheitern – alte Zwischensysteme, Proxys, die WebSocket-Upgrades entfernen oder Streams puffern. Der Server hält jede Anfrage offen, bis Daten eintreffen, was Push annähert – zum Preis ständiger Wiederverbindungen und des Header-Overheads pro Anfrage.'
  - question: 'Wie viele SSE-Verbindungen kann ein Browser öffnen?'
    answer: 'Über HTTP/1.1 sechs pro Origin – und das Limit gilt gemeinsam über alle Tabs, ein dokumentierter Fallstrick, bei dem ein in sieben Tabs geöffnetes Dashboard stillschweigend verhungert. Über HTTP/2 verschiebt sich die Grenze auf gleichzeitige Streams, die über eine Verbindung multiplext werden (standardmäßig rund hundert), was das Problem praktisch erledigt.'
  - question: 'Verbindet sich SSE automatisch neu?'
    answer: 'Ja – das ist das Merkmal, das es am deutlichsten von rohen WebSockets abhebt. EventSource wiederholt abgebrochene Verbindungen von selbst, beachtet ein vom Server gesetztes Wiederholungsintervall und sendet die zuletzt empfangene Ereignis-ID im Header Last-Event-ID, sodass der Server den Stream lückenlos fortsetzen kann. Die Wiederverbindung bei WebSockets ist Code, den Sie schreiben.'
  - question: 'Kann SSE Binärdaten senden?'
    answer: 'Nein – der Stream ist laut Spezifikation UTF-8-Text; binäre Payloads müssen kodiert werden, mit rund einem Drittel Größenaufschlag. WebSockets transportieren Binärframes nativ, was für Audio, Protocol Buffers und alles bereits Kompakte zählt.'
  - question: 'Womit streamen KI-Chat-Anwendungen ihre Antworten?'
    answer: 'Fast ausnahmslos mit Server-Sent Events: Die Token-für-Token-Generierung ist einseitig gestreamter Text, und genau das ist die Form von SSE – gewöhnliches HTTP nach außen, keine Upgrade-Verhandlung, automatisches Fortsetzen. WebSockets tauchen in KI-Produkten nur dort auf, wo der Client mitten im Stream unterbrechen oder sprechen muss, etwa bei Sprachschnittstellen.'
  - question: 'Wie sieht die Rückfallreihenfolge für Echtzeit-Features aus?'
    answer: 'Feature-Erkennung und stufenweises Zurückfallen: WebSocket, wo der Pfad es unterstützt, SSE, wo nur Server-Push nötig ist oder Upgrades scheitern, Long Polling als kleinster gemeinsamer Nenner. Ausgereifte Echtzeit-Bibliotheken handeln diese Leiter automatisch aus – ein Grund, warum rohe Sockets in Produktion selten blank verwendet werden.'
codeLanguages: [javascript, dart, swift, kotlin]
externalAuthorities:
  - name: 'Server-sent events — WHATWG HTML Living Standard'
    url: 'https://html.spec.whatwg.org/multipage/server-sent-events.html'
  - name: 'RFC 6455 — The WebSocket Protocol'
    url: 'https://datatracker.ietf.org/doc/html/rfc6455'
  - name: 'Using server-sent events — MDN Web Docs'
    url: 'https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events'
  - name: 'RFC 6202 — Known Issues with Long Polling and HTTP Streaming'
    url: 'https://datatracker.ietf.org/doc/html/rfc6202'
cta:
  title: 'Die Transportentscheidung überspringen'
  text: 'Back4app Live Queries liefern Echtzeit-Aktualisierungen über eine verwaltete WebSocket-Flotte – abonnieren Sie die Abfrage, die Sie ohnehin haben, und überlassen Sie der Plattform Verbindungen, Wiederverbindungen und Fan-out.'
  linkText: 'Kostenlos starten'
  linkUrl: 'https://www.back4app.com/signup'
author: 'Back4app Engineering'
publishedDate: '2026-09-23'
translationKey: sse-vs-websockets-vs-polling
---

**Polling ist ein Pull-Modell, bei dem Clients wiederholt fragen; SSE und WebSockets halten eine Verbindung offen, damit der Server in Echtzeit senden kann.** Die Wahl zwischen ihnen sind eigentlich drei Fragen – in welche Richtung fließen die Daten, wie oft ändern sie sich, und welche Infrastruktur liegt dazwischen – und die ehrliche Antwort fällt pro Feature unterschiedlich aus, nicht pro Anwendung.

## Das Wichtigste in Kürze

| Frage | Antwort |
| --- | --- |
| Short Polling | Nach Zeitplan fragen – einfach, cachefreundlich, meist vergeudete Anfragen |
| Long Polling | Server hält die Anfrage, bis Daten kommen – simulierter Push über gewöhnliches HTTP |
| SSE | Ein HTTP-Stream, Textereignisse Server → Client, automatische Wiederverbindung eingebaut |
| WebSockets | Ein Socket, Full-Duplex, binärfähig – das Protokoll gehört Ihnen |
| Die Faustregel | Einseitig → SSE · beidseitig → WebSockets · seltene Änderungen → Polling reicht |

## Der Code, nebeneinander

```js
// 1 · Short Polling — nach Zeitplan fragen
setInterval(async () => {
  const res = await fetch('/api/messages?since=' + lastId);
  render(await res.json());              // meist leer — Header trotzdem bezahlt
}, 2000);

// 2 · Server-Sent Events — ein HTTP-Stream, der Server sendet Textereignisse
const events = new EventSource('/api/stream');
events.onmessage = (e) => render(JSON.parse(e.data));   // verbindet automatisch neu

// 3 · WebSocket — ein Socket, beide Richtungen
const ws = new WebSocket('wss://api.example.com/live');
ws.onmessage = (e) => render(JSON.parse(e.data));
ws.send(JSON.stringify({ type: 'typing' }));            // der Client sendet auch
```

Was die meisten Anwendungen tatsächlich ausliefern – eine Abonnementschicht, die den Transport für Sie besitzt:

**JavaScript:**

```javascript
// JavaScript / Node.js — Back4app JS SDK
// The polling replacement: subscribe once, receive pushes
const query = new Parse.Query('Message');
query.equalTo('room', 'general');
const subscription = await query.subscribe();    // WebSocket under the hood
subscription.on('create', (msg) => render(msg)); // pushed, not polled
// subscription.unsubscribe() when the screen closes
```

**Flutter:**

```dart
// Flutter / Dart — Back4app Flutter SDK
// The polling replacement: subscribe once, receive pushes
final liveQuery = LiveQuery();
final query = QueryBuilder<ParseObject>(ParseObject('Message'))
  ..whereEqualTo('room', 'general');
final subscription = await liveQuery.client.subscribe(query); // WebSocket under the hood
subscription.on(LiveQueryEvent.create, (msg) => render(msg)); // pushed, not polled
```

**Swift:**

```swift
// iOS / Swift — Back4app Swift SDK
// The polling replacement: subscribe once, receive pushes
let query = Message.query("room" == "general")
let subscription = try await query.subscribe() // WebSocket under the hood
subscription.handleEvent { _, event in
    if case .created(let msg) = event { render(msg) } // pushed, not polled
}
```

**Kotlin:**

```kotlin
// Android / Kotlin — Back4app Android SDK
// The polling replacement: subscribe once, receive pushes
val client = ParseLiveQueryClient.Factory.getClient()
val query = ParseQuery.getQuery<ParseObject>("Message")
query.whereEqualTo("room", "general")
val subscription = client.subscribe(query) // WebSocket under the hood
subscription.handleEvent(SubscriptionHandling.Event.CREATE) { _, msg ->
    render(msg) // pushed, not polled
}
```

## So funktioniert jede Technik

**Short Polling** ist ein `setInterval` um ein fetch herum: alle *n* Sekunden fragen, ob sich etwas geändert hat. Jeder Zyklus bezahlt eine vollständige HTTP-Anfrage samt Antwort – Header, Authentifizierung, Routing – meist nur, um "noch nichts" zu hören, und die mittlere Zustellverzögerung beträgt das halbe Intervall plus eine Umlaufzeit.

**Long Polling** verlagert das Warten auf den Server: Der Client fragt, der Server *hält die Anfrage offen*, bis Daten eintreffen oder ein Timeout greift, und der Client fragt sofort erneut. Es nähert Push über schlichtes HTTP an – der Behelf aus der Comet-Ära, dessen bekannte Kosten (ständige Wiederverbindungen, Header pro Anfrage, Sorgfalt bei der Reihenfolge) in [RFC 6202](https://datatracker.ietf.org/doc/html/rfc6202) katalogisiert sind.

**Server-Sent Events** machen die gehaltene Antwort dauerhaft: eine HTTP-Antwort mit `Content-Type: text/event-stream`, die nie endet und in die der Server UTF-8-Ereignisse schreibt (Felder `data:`, `event:`, `id:`, `retry:`, gemäß [WHATWG-Standard](https://html.spec.whatwg.org/multipage/server-sent-events.html)). Das `EventSource` des Browsers konsumiert sie – und verbindet sich automatisch neu, wobei es über `Last-Event-ID` wieder aufsetzt.

**WebSockets** verlassen HTTP vollständig: Ein Handshake stuft die Verbindung hoch (`101 Switching Protocols`, [RFC 6455](https://datatracker.ietf.org/doc/html/rfc6455)), danach tauschen beide Seiten Text- oder Binärframes mit rund 2–14 Byte Overhead aus, Full-Duplex, bis jemand den Socket schließt. Maximale Leistungsfähigkeit – und alles oberhalb des Frames (Nachrichtenformat, Bestätigungen, Wiederverbindung, Fortsetzen) müssen Sie selbst entwerfen.

```mermaid
flowchart LR
  accTitle: Pull beim Polling im Vergleich zu Push bei SSE und WebSocket
  accDescr: Beim Polling fordert der Client wiederholt Aktualisierungen vom Server an, und die meisten Antworten sind leer. Bei Server-Sent Events sendet der Server Ereignisse über einen gehaltenen HTTP-Stream an den Client. Bei WebSockets tauschen Client und Server Frames in beide Richtungen über einen dauerhaften Socket aus.
  subgraph P["Polling — Pull"]
    C1["Client"] -->|"alle n s fragen (meist leer)"| S1["Server"]
  end
  subgraph E["SSE — Push"]
    S2["Server"] -->|"ein HTTP-Stream von Ereignissen"| C2["Client<br/>(EventSource)"]
  end
  subgraph W["WebSocket — Duplex"]
    C3["Client"] -->|"Frames"| S3["Server"]
    S3 -->|"Frames"| C3
  end
```

## SSE vs. WebSockets vs. Long Polling vs. Short Polling

| | Short Polling | Long Polling | SSE | WebSockets |
| --- | --- | --- | --- | --- |
| Richtung | Pull | Simulierter Push | Server → Client | Full-Duplex |
| Protokoll | Schlichtes HTTP | Schlichtes HTTP | Schlichter HTTP-Stream | Eigenes Protokoll nach Upgrade |
| Zustelllatenz | Intervall/2 + RTT | ~RTT | ~RTT | ~RTT |
| Payloads | Beliebig | Beliebig | Nur UTF-8-Text | Text + binär |
| Automatische Wiederverbindung | Trivial (nächster Poll) | Erneute Anfrage | **Eingebaut + Last-Event-ID** | Schreiben Sie selbst |
| Reibung mit Proxy/Firewall | Keine | Gering | Gering (Pufferung beachten) | Upgrade kann entfernt werden |
| Serverzustand | Keiner | Gehaltene Anfragen | Offene Streams | Angeheftete Sockets |
| Komplexität | Trivial | Mittel | Gering | Am höchsten |
| Stärke bei | Seltenen Änderungen | Legacy-Rückfall | Feeds, Benachrichtigungen, KI-Streams | Chat, Spiele, Zusammenarbeit |

## Was kostet Polling? Die Overhead-Rechnung

Der Vergleich, den keine Ranking-Seite durchrechnet – 1.000 Clients mit 2-Sekunden-Poll gegen dieselben 1.000 per Push:

```text
1.000 Clients, 2 s Polling                1.000 Clients, Push
→ 500 Anfragen/Sekunde dauerhaft          → 0 Anfragen im Ruhezustand
→ ~800 B Header pro Zyklus                → SSE-Ereignis-Framing ~5 B
→ ~0,4 MB/s reine Header-Steuer           → WebSocket-Frame-Overhead 2–14 B
→ fast jede Antwort leer                  → Bytes fließen nur bei Daten
→ durchschn. Zustellung: 1 s + RTT        → Zustellverzögerung: ~RTT
```

Die Lehre schneidet in beide Richtungen. Push gewinnt überwältigend, wenn Aktualisierungen häufig sind und Latenz zählt. Ändern sich die Daten aber stündlich, entstehen diese 500 Anfragen/s nie – ein behutsamer Poll (oder ein Neuladen beim Fokus) ist cachefreundlich, mit curl debuggbar, serverless-tauglich und frei von Verbindungszustand. Polling pauschal abzutun ist Mode, nicht Ingenieurskunst.

## Wiederverbindung: der stille Unterschied

Verbindungen brechen ab – Funkzellenwechsel, zugeklappte Laptops, Leerlauf-Timeouts von Proxys (oft 30–120 s, weshalb SSE-Streams Kommentar-Keep-alives senden und WebSockets Ping-/Pong-Frames austauschen). Was danach passiert, trennt die Transporte. Der Vertrag von SSE regelt es: Der Browser versucht es mit der vom Server gesetzten `retry`-Verzögerung erneut und legt `Last-Event-ID` vor, sodass ein Server mit kurzem Ereignispuffer den Stream lückenlos fortsetzt. Ein roher WebSocket schließt einfach: Wiederverbindung mit exponentiellem Backoff, Nachholen verpasster Nachrichten und ein Fortsetzungsprotokoll sind allesamt Anwendungscode – der am meisten unterschätzte Posten hinter "wir nehmen einfach WebSockets". So oder so braucht ein Client, der Minuten offline war, ein *Nachholen* (das erneute Ausführen der Basisabfrage), nicht nur eine Wiederverbindung – Push-Transporte liefern Deltas, und Deltas setzen eine Ausgangsbasis voraus.

## Warum KI-Chats über SSE streamen

Token-für-Token-Ausgabe eines Modells ist die perfekte SSE-Arbeitslast: streng einseitig, Text, schubweise, über schlichtes HTTP, das jeder Proxy und jedes CDN versteht, mit Semantik zum Fortsetzen abgebrochener Generierungen. Deshalb streamen LLM-APIs ihre Completions ganz überwiegend als `text/event-stream` – und deshalb lohnt sich das Muster über Chatbots hinaus: Fortschrittsanzeigen, Build-Protokolle und Dashboards haben dieselbe Form. WebSockets betreten KI-Produkte an der Sprachebene, wo der Nutzer mitten im Stream unterbricht – in dem Moment, in dem der Client zurücksprechen muss, kauft die Duplex-Steuer etwas ein.

## Push skalieren: warum Zustandshaltung zählt

Polling und SSE sind für einen Load Balancer gewöhnliches HTTP; jeder Server kann jede Anfrage beantworten (SSE hält zwar einen Stream, behält aber HTTP-Semantik und braucht nur ungepufferte Proxys). WebSockets sind *Zustand*: Jeder Socket heftet einen Client an einen Prozess, also bedeutet horizontale Skalierung verbindungsbewusste Lastverteilung, kontrolliertes Leeren bei Deployments und ein [Pub/Sub](/glossary/pub-sub-pattern/)-Backplane (üblicherweise Redis), damit eine auf Server A veröffentlichte Nachricht die Sockets auf Server B erreicht. Über HTTP/1.1 hat SSE seinen eigenen berühmten Fallstrick – sechs Verbindungen pro Origin, *gemeinsam über alle Tabs* ([Warnung bei MDN](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events)) –, den HTTP/2 erledigt, wo Streams über eine Verbindung multiplext werden. Nichts davon ist exotisch; all das ist der Grund, warum es verwaltete Echtzeit-Schichten gibt.

## Typische Anwendungsfälle

- **Benachrichtigungs-Feeds und Ticker** – einseitig, Text, häufig: das Heimspiel von SSE.
- **Streaming von KI-Antworten** – der aktuelle Paradefall für SSE; eine Richtung, Token-Text, Fortsetzen nach Abbruch.
- **Chat und Zusammenarbeit** – Nachrichten fließen in beide Richtungen mit niedriger Latenz: [WebSockets](/glossary/de/websockets/), meist über eine verwaltete Schicht.
- **Live-Dashboards** – Server-Push von Abfrageergebnissen; in der Praxis ein [Live-Query](/glossary/de/live-queries-echtzeit/)-Abonnement statt eines selbstgebauten Transports.
- **Langsam veränderliche Daten** – Bestände, die stündlich aktualisiert werden, Einstellungsbildschirme: ehrlicherweise Polling oder Neuladen beim Fokus.

## Welchen Transport sollten Sie verwenden? Eine Entscheidungsmatrix

| Ihre Situation | Greifen Sie zu |
| --- | --- |
| Nur Server → Client (Feeds, Streams, Fortschritt) | SSE |
| Client und Server senden beide in Echtzeit | WebSockets |
| Aktualisierungen seltener als alle paar Minuten | Short Polling / Neuladen beim Fokus |
| Feindselige Proxys, veraltete Infrastruktur | Long Polling als Rückfall |
| Binäre oder hochfrequente Payloads | WebSockets |
| Serverless-Plattform, Funktions-Timeouts | Polling oder SSE über streamingfähige Hoster |
| "Ich will einfach Live-Daten auf dem Bildschirm" | Eine Live-Query-Schicht, die den Transport besitzt |

## Grenzen und Trade-offs

- **SSE ist nur Text und nur einseitig.** Binärdaten müssen kodiert werden; jeglicher Verkehr vom Client zum Server läuft über separate HTTP-Anfragen – in Ordnung für Bestätigungen, falsch für Chat.
- **WebSockets bringen Sie ins Protokollgeschäft.** Framing, Bestätigungen, Wiederverbindung, Fortsetzen, Backpressure: Der Transport ist leicht, der Vertrag darüber ist die Arbeit.
- **Die Einfachheit von Polling verbirgt eine Latenzuntergrenze.** Keine Feinabstimmung entkommt der mittleren Verzögerung von Intervall/2; ein kürzeres Intervall kauft nur die Header-Steuer zurück.
- **Long Polling ist bei Last das Schlechteste aus beiden Welten.** Gehaltene Anfragen verbrauchen Serverkapazität wie Push, während sie pro Nachricht den Wiederverbindungs-Overhead wie Pull bezahlen – deshalb überlebt es nur als Rückfallstufe.
- **Alle Push-Transporte brauchen kooperative Proxys.** Stream-Pufferung bricht SSE stillschweigend; entfernte Upgrade-Header brechen WebSockets – testen Sie durch die echte Infrastruktur, nicht über localhost.

## Echtzeit-Transporte mit Back4app

Back4app ist eine Open-Source-Plattform für Backend as a Service (BaaS), die eine verwaltete Datenbank, automatisch generierte REST- und GraphQL-APIs, Authentifizierung, Dateispeicher und Serverless-Funktionen mit Cloud Code kombiniert. Die Transportentscheidung nehmen Ihnen weitgehend [Live Queries](/glossary/de/live-queries-echtzeit/) ab: Die Code-Tabs oben abonnieren eine Abfrage und empfangen gesendete Ereignisse über eine WebSocket-Flotte, die die Plattform betreibt – samt Verbindungen, Wiederverbindungen, Berechtigungsprüfungen und Fan-out über Server hinweg –, sodass aus "SSE oder WebSockets?" ein Implementierungsdetail wird, das Sie erben, statt Infrastruktur, die Sie bauen. Wo ein gemächlicherer Takt wirklich passt, läuft dieselbe Abfrage als schlichter Abruf nach Ihrem Zeitplan; eine Parse-Abfrage zu pollen und sie zu abonnieren liegen eine Zeile auseinander, was den richtigen Transport pro Feature zu einem Refactoring macht und nicht zu einer Neuentwicklung.
