{ }
type
GraphQL · Subscriptions · Realtime · WebSocket · Architektur
Subscriptions und Realtime
mit GraphQL

GraphQL Subscriptions ermöglichen Realtime-Kommunikation über persistente Verbindungen – aber sie kommen mit erheblichen Skalierungs- und Infrastrukturanforderungen. Dieser Artikel erklärt das Konzept, die Transportoptionen, die Designentscheidungen und zeigt, wann Subscriptions wirklich die richtige Wahl sind.

15 Min. Lesezeit Subscriptions · WebSocket · SSE · Polling · Pub/Sub GraphQL · Node.js · Skalierung · Magento

1. Was GraphQL Subscriptions konzeptuell bedeuten

GraphQL Subscriptions sind das dritte Operation-Typ neben Queries und Mutations. Während eine Query einmalig Daten liest und eine Mutation einmalig Daten schreibt, öffnet eine Subscription eine persistente Verbindung zwischen Client und Server. Der Server sendet aktiv Daten, wenn ein relevantes Ereignis eintritt – ohne dass der Client erneut anfragen muss. Das Grundkonzept ist vergleichbar mit einem Event-Listener: der Client meldet Interesse an bestimmten Ereignissen an, und der Server benachrichtigt ihn, wenn sie eintreten.

Das Schema-Modell von Subscriptions ist deklarativ und sieht auf den ersten Blick ähnlich aus wie eine Query: man definiert, welche Felder man empfangen möchte. Der Unterschied liegt im Transportprotokoll und im Auslieferungsmodell. Während Query und Mutation über standard HTTP request-response funktionieren, brauchen Subscriptions eine dauerhafte bidirektionale oder unidirektionale Verbindung. Diese Verbindung muss vom Server-Prozess aktiv gehalten werden – was erhebliche Implikationen für Infrastruktur und Skalierung hat.

2. Transportschichten: WebSocket, SSE und Polling im Vergleich

Die häufigste Implementierung von GraphQL Subscriptions nutzt WebSockets. Das Protokoll graphql-ws (der Nachfolger des älteren subscriptions-transport-ws) standardisiert die Nachrichtenformate für Verbindungsaufbau, Subscription-Start, Datentransfer und Verbindungsende über WebSocket. WebSockets sind bidirektional – Client und Server können beide Nachrichten senden. Für Subscriptions braucht man eigentlich nur die Server-to-Client-Richtung, aber die bidirektionale Natur ermöglicht auch Heartbeat-Mechanismen und Flow-Control.

Server-Sent Events (SSE) sind eine leichtgewichtigere Alternative: eine unidirektionale HTTP-Verbindung, über die der Server Events an den Client pusht. SSE ist einfacher zu implementieren, benötigt keine spezielle WebSocket-Infrastruktur und funktioniert mit standard HTTP/2 Multiplexing. Für viele Subscription-Szenarien ist SSE ausreichend. Polling – regelmäßiges Abfragen des Servers per Query – ist die einfachste Methode, skaliert aber schlecht und erzeugt unnötige Last, auch wenn sich nichts geändert hat. Es ist ein Notbehelf, keine Architekturempfehlung.

3. Subscription-Schema: Design und Patterns

Das Schema-Design für Subscriptions folgt denselben Prinzipien wie Query- und Mutation-Design, hat aber einige Besonderheiten. Subscription-Felder sollten granular definiert werden: statt einer allgemeinen dataChanged-Subscription, die alles abdeckt, sind spezifische Subscriptions wie orderStatusChanged, stockLevelUpdated oder chatMessageReceived besser wartbar, filterbarer und effizienter. Granulare Subscriptions erlauben es dem Server, Events gezielt nur an die Clients zu liefern, die wirklich betroffen sind.

Ein wichtiges Pattern: Subscription-Filter-Argumente. Eine Subscription orderStatusChanged(orderId: ID!) mit einem Pflicht-Argument erlaubt dem Server, die Subscription auf einen spezifischen Datensatz zu begrenzen. Ohne Filterung würde jeder Client alle Bestell-Status-Updates aller Kunden erhalten – eine gravierende Performance- und Datenschutzverletzung. Die Filterlogik muss serverseitig implementiert werden und sollte vor der Auslieferung prüfen, ob der anfragende Client die Berechtigung hat, dieses spezifische Event zu empfangen.


# Subscription schema design: granular, filtered, documented
type Subscription {
  orderStatusChanged(orderId: ID!): OrderStatusEvent
    @doc(description: "Fires when the status of a specific order changes")

  stockLevelUpdated(sku: String!): StockUpdateEvent
    @doc(description: "Fires when stock quantity for a SKU changes")

  chatMessageReceived(conversationId: ID!): ChatMessage
    @doc(description: "New message in a specific customer support conversation")
}

type OrderStatusEvent {
  order_id: ID!
  old_status: String!
  new_status: String!
  updated_at: String!
}

type StockUpdateEvent {
  sku: String!
  quantity: Int!
  is_in_stock: Boolean!
}

4. Pub/Sub-Backend: der fehlende Teil des Puzzles

GraphQL-Subscriptions brauchen ein Pub/Sub-Backend, das Events zwischen dem Teil des Systems, der Events erzeugt (z.B. ein Order-Status-Update im Backend), und dem Subscription-Server vermittelt, der die persistenten Client-Verbindungen hält. Ohne dieses Mittelglied müsste jeder Server-Prozess alle Events selbst generieren – was bei mehreren Instanzen zu dem Problem führt, dass ein Client mit Instanz A verbunden ist, während das Event auf Instanz B ausgelöst wird.

Bewährte Pub/Sub-Backends für GraphQL: Redis mit Pub/Sub-Funktionalität ist die häufigste Wahl für mittelgroße Deployments. Redis ermöglicht es, Events auf einem Channel zu publishen und von allen subscribed Server-Instanzen zu empfangen. Für größere Deployments und höhere Durchsatzanforderungen kommen Apache Kafka oder Google Cloud Pub/Sub in Frage. Der Subscription-Server empfängt Events vom Pub/Sub-System und leitet sie an die passenden verbundenen Clients weiter – nach Filterung und Berechtigungsprüfung.


# Subscription flow: event triggers publication, server filters and pushes

# 1. Backend fires event (order status change):
#    Redis PUBLISH order:status:changed '{"orderId":"100000123","newStatus":"shipped"}'

# 2. Subscription server receives event from Redis
# 3. Server finds all clients subscribed to orderStatusChanged(orderId: "100000123")
# 4. Server checks authorization for each client
# 5. Server pushes filtered data to authorized clients

subscription WatchMyOrder {
  orderStatusChanged(orderId: "100000123") {
    order_id
    new_status
    updated_at
  }
}

# Client receives update automatically when status changes:
# { "data": { "orderStatusChanged": {
#     "order_id": "100000123",
#     "new_status": "shipped",
#     "updated_at": "2026-05-09T14:23:11Z"
# }}}

5. Skalierungsherausforderungen bei Subscriptions

Die größte Herausforderung bei der Skalierung von GraphQL Subscriptions: persistente Verbindungen binden Server-Ressourcen dauerhaft. Ein HTTP-Request für eine Query ist nach wenigen Millisekunden abgeschlossen. Eine WebSocket-Verbindung für eine Subscription kann Stunden oder Tage bestehen – und während dieser Zeit belegt sie einen File-Descriptor, Memory und CPU-Kapazität. 10.000 gleichzeitige Subscription-Verbindungen bedeuten 10.000 persistente Verbindungen, die auf demselben oder verteilten Servern gehalten werden müssen.

Für hohe Verbindungszahlen braucht man einen Subscription-Server mit Event-Loop-Architektur – typischerweise Node.js mit dem graphql-ws-Paket, oder spezialisierte Dienste wie Ably, Pusher oder AWS AppSync. PHP-basierte Applikationsserver wie Magento sind strukturell nicht geeignet, tausende persistente WebSocket-Verbindungen zu halten, weil PHP traditionell synchron und request-bound arbeitet. ReactPHP oder Swoole bieten asynchrone Erweiterungen, aber sie erfordern erhebliche architektonische Anpassungen und sind in Magento-Projekten selten eingesetzt.

6. Magento und Subscriptions: die ehrliche Einschätzung

Magento GraphQL unterstützt aktuell keine nativen Subscriptions. Das Framework ist primär auf synchrone HTTP-Request-Response-Zyklen ausgelegt, und die PHP-Architektur macht persistente WebSocket-Verbindungen praktisch schwierig. Das ist keine Schwäche von Magento, sondern eine Konsequenz der Designentscheidungen, die auf hohe Durchsatzfähigkeit für transaktionale Webshop-Requests optimieren – nicht auf persistente Echtzeit-Kommunikation.

In der Praxis bedeutet das: wenn Magento-Projekte Realtime-Funktionen brauchen – Live-Tracking von Bestellungen, Lagerbestand-Benachrichtigungen, Chat-Support – nutzen sie ein separates Service-Layer für die Subscription-Infrastruktur. Dieser Service empfängt Events von Magento (über Webhooks, Message-Queues oder direkte Datenbankänderungs-Events) und leitet sie über WebSocket oder SSE an die Clients weiter. Der GraphQL-Endpoint von Magento bleibt für transaktionale Queries und Mutations zuständig, während ein Node.js-Subscription-Server die Realtime-Kommunikation übernimmt.

7. Realtime-Alternativen ohne native Subscriptions

Für viele Realtime-Anforderungen sind Subscriptions nicht die einzige oder beste Lösung. Intelligentes Polling – Queries in kurzen Abständen mit If-Modified-Since-Logik – kann für viele Use Cases ausreichend sein, ohne die Infrastrukturkomplexität von WebSockets. Der Vorteil: standard HTTP, keine persistente Verbindung, einfach cachebar. Der Nachteil: höhere Latenz und unnötige Requests wenn sich nichts geändert hat.

Server-Sent Events (SSE) sind ein ausgezeichneter Mittelweg: einfachere Infrastruktur als WebSocket, funktionieren über standard HTTP, automatisches Reconnecting im Browser. Für viele Commerce-Realtime-Szenarien – Bestellstatus-Updates, Lagerbestand-Warnungen – ist SSE vollständig ausreichend. Push-Benachrichtigungen über Firebase oder Web Push API eignen sich für asynchrone Benachrichtigungen, die auch dann zugestellt werden, wenn der Nutzer nicht aktiv auf der Seite ist. Die Entscheidung zwischen diesen Optionen hängt von der geforderten Latenz, der Infrastrukturkomplexität und der Anzahl gleichzeitiger Nutzer ab.


# Alternative to subscriptions: smart polling with change detection
# Query with timestamp filter — only fetch if data changed

query OrderStatusSince($orderId: ID!, $since: String!) {
  orderStatusHistory(orderId: $orderId, changedSince: $since) {
    has_changes
    current_status
    history {
      status
      changed_at
      comment
    }
  }
}

# Client polls every 30 seconds, passes last-seen timestamp
# Server returns has_changes: false if nothing changed (lightweight)
# Only on change: server returns full data

8. Falsch / Richtig: wann Subscriptions Sinn machen

Subscriptions machen dann Sinn, wenn niedrige Latenz und hohe Aktualisierungsfrequenz gleichzeitig gefordert sind. Chat-Anwendungen, Live-Collaboration-Tools, Echtzeit-Auktionen oder Live-Sport-Scores – hier ist Polling zu langsam und SSE möglicherweise zu unidirektional. Für Commerce-Szenarien wie Bestellstatus-Updates, die sich selten ändern, ist Polling oder SSE fast immer die bessere Wahl – einfacher zu implementieren, einfacher zu skalieren und ausreichend für den Use Case.

Methode Latenz Infrastruktur Bester Use Case
Polling Hoch (Interval-abhängig) Standard HTTP Selten wechselnde Daten, einfache Setups
SSE Niedrig (sub-second) HTTP, keine WS-Infra Server-Push, Benachrichtigungen, Status-Updates
WebSocket/Subscription Sehr niedrig (ms) WS-Server + Pub/Sub Chat, Collaboration, Live-Auktionen
Web Push Variabel (minutes) Push-Service (Firebase etc.) Asynchrone Benachrichtigungen, auch offline
Managed Services Niedrig Ausgelagert (Ably, Pusher) Schnell einsetzen ohne eigene Infra

9. Realtime-Ansätze im Vergleich

Die wichtigste Designentscheidung bei Realtime in GraphQL-Projekten: immer mit dem einfachsten Ansatz beginnen, der die Anforderungen erfüllt. Subscriptions sind mächtig, aber sie erhöhen die Systemkomplexität erheblich. Wer für Bestellstatus-Updates auf einer E-Commerce-Seite WebSockets einführt, betreibt überkomplex für den Use Case. Wer für ein Live-Chat-Feature mit Polling arbeitet, kämpft gegen strukturelle Grenzen. Die richtige Technologiewahl ergibt sich aus der Latenzanforderung, der Update-Frequenz und der akzeptablen Infrastrukturkomplexität.

GraphQL Subscriptions und Realtime — Das Wichtigste auf einen Blick

Wann Subscriptions

Niedrige Latenz + hohe Update-Frequenz gleichzeitig: Chat, Collaboration, Live-Auktionen. Nicht für gelegentliche Status-Updates.

Transport

WebSocket (graphql-ws) für bidirektionale Use Cases. SSE für einfacheres Server-to-Client-Pushing. Polling als Fallback.

Magento

Keine nativen Subscriptions. Separater Node.js-Service + Redis Pub/Sub für Realtime, mit Magento als Event-Quelle via Message-Queue.

Skalierung

Persistente Verbindungen binden Ressourcen. Redis Pub/Sub für multi-instanz Deployments. Managed Services für schnelle Umsetzung.

10. Zusammenfassung

GraphQL Subscriptions sind ein mächtiges Werkzeug für Realtime-Kommunikation – aber kein Standardwerkzeug für jedes Projekt. Die Infrastrukturanforderungen (WebSocket-Server, Pub/Sub-Backend, persistente Verbindungsverwaltung) rechtfertigen den Aufwand nur, wenn der Use Case wirklich niedrige Latenz und hohe Aktualisierungsfrequenz braucht. Für Commerce-Szenarien wie Bestellstatus-Updates oder Lagerbestandswarnungen sind SSE oder intelligentes Polling in den meisten Fällen die bessere Wahl.

In Magento-Projekten stehen native Subscriptions nicht zur Verfügung, und der Umweg über separate Services ist in der Praxis der verbreitete Ansatz. Wer Realtime in Magento-Projekten implementieren will, sollte mit dem einfachsten Ansatz beginnen, der die Anforderungen erfüllt: zuerst Polling, dann SSE, dann WebSocket/Subscriptions – und bei jedem Schritt die zugefügte Komplexität gegen den Mehrwert abwägen. Die GraphQL-Subscription-Syntax ist elegant; die Infrastruktur dahinter ist es deutlich weniger.

11. FAQ: GraphQL Subscriptions und Realtime

1Unterschied Query vs. Subscription?
Query: einmalig Anfrage-Antwort. Subscription: persistente Verbindung, Server sendet aktiv bei Ereignissen.
2Welches Protokoll nutzen Subscriptions?
Standardmäßig WebSocket mit graphql-ws. Alternativ SSE für einfachere unidirektionale Szenarien.
3Warum brauchen Subscriptions Pub/Sub?
Bei mehreren Instanzen: Events können auf Instanz A ausgelöst werden, während Clients mit Instanz B verbunden sind. Redis vermittelt instanzübergreifend.
4Unterstützt Magento native Subscriptions?
Aktuell nicht. Realtime in Magento wird typischerweise über separate Node.js-Services mit Redis realisiert.
5Wann ist Polling besser als Subscriptions?
Wenn Daten sich selten ändern, einfache Infrastruktur wichtig ist und Latenz im Minutenbereich akzeptabel ist.
6Was sind Server-Sent Events?
HTTP-Verbindung für unidirektionales Server-Pushing. Einfacher als WebSocket, funktioniert mit HTTP/2, automatisches Reconnecting.
7Wie skaliert man viele WebSocket-Verbindungen?
Redis Pub/Sub für instanzübergreifende Events. Event-Loop-Server (Node.js). Bei sehr hohen Zahlen: Managed Services wie Ably.
8Wie filtert man Events pro Client?
Subscription-Argumente (orderId: ID!). Server filtert subscribed Clients und prüft Berechtigung jedes Clients beim Empfang eines Events.
9Was ist graphql-ws?
Empfohlenes WebSocket-Protokoll für GraphQL. Ersetzt subscriptions-transport-ws mit besserer Stabilität und aktiver Wartung.
10Was sind Managed Subscription Services?
Ably, Pusher, AWS AppSync: WebSocket-Infrastruktur als Managed Service. Reduziert Betriebsaufwand, erzeugt aber Vendor-Abhängigkeit.