Echtzeit-Daten sind in modernen Web-Applikationen Standard: Live-Dashboards, Chat-Systeme, kollaborative Editoren, Finanz-Feeds. Die klassische Lösung war jahrelang Polling — alle N Sekunden eine REST-Anfrage. Das ist ineffizient, langsam und verschwendet Ressourcen. GraphQL Subscriptions lösen dieses Problem elegant: Der Client abonniert ein Event, der Server schickt Updates genau dann, wenn sich etwas ändert.
2026 ist Claude Code der bevorzugte Assistent für komplexe GraphQL-Setups. Statt Stunden mit Boilerplate zu verbringen, beschreibt man das gewünschte Verhalten — Claude Code generiert Schema, Resolver, Server-Konfiguration und Client-Hooks in einem Durchlauf, vollständig typsicher in TypeScript.
1. GraphQL Schema für Subscriptions
Der erste Schritt zu Echtzeit-GraphQL ist das Schema. Neben Query und Mutation definiert GraphQL einen dritten Root-Typ: Subscription. Jedes Feld im Subscription-Typ repräsentiert einen Stream von Events, den Clients abonnieren können.
SDL GraphQL Schema Definition Language für Subscriptions
Claude Code Prompt: "Erstelle ein GraphQL Schema für ein Chat-System mit Subscriptions für neue Nachrichten und Typing-Indikatoren"
# schema.graphql
type Message {
id: ID!
content: String!
author: User!
roomId: ID!
createdAt: String!
}
type TypingIndicator {
userId: ID!
username: String!
roomId: ID!
isTyping: Boolean!
}
type Query {
messages(roomId: ID!): [Message!]!
}
type Mutation {
sendMessage(content: String!, roomId: ID!): Message!
setTyping(roomId: ID!, isTyping: Boolean!): Boolean!
}
type Subscription {
# Neue Nachrichten in einem Raum empfangen
messageAdded(roomId: ID!): Message!
# Typing-Indikator in einem Raum
userTyping(roomId: ID!): TypingIndicator!
# Alle Events in einem Raum (Union-Typ)
roomActivity(roomId: ID!): RoomEvent!
}
union RoomEvent = Message | TypingIndicator
AsyncIterator Der Subscription Resolver — AsyncIterator Pattern
Subscription Resolver haben zwei Pflichtfelder: subscribe (gibt einen AsyncIterator zurück) und resolve (transformiert das Event).
// resolvers/subscription.resolver.ts
import { PubSub, withFilter } from 'graphql-subscriptions';
import { GraphQLResolveInfo } from 'graphql';
const pubsub = new PubSub();
// Event-Topics als typsichere Konstanten
export const EVENTS = {
MESSAGE_ADDED: 'MESSAGE_ADDED',
USER_TYPING: 'USER_TYPING',
ROOM_ACTIVITY: 'ROOM_ACTIVITY',
} as const;
export const subscriptionResolvers = {
Subscription: {
messageAdded: {
// subscribe gibt einen AsyncIterator zurück
subscribe: (_: unknown, { roomId }: { roomId: string }) => {
return pubsub.asyncIterableIterator(
`${EVENTS.MESSAGE_ADDED}.${roomId}`
);
},
// resolve transformiert das rohe Event in den GraphQL-Typ
resolve: (payload: { messageAdded: Message }) => {
return payload.messageAdded;
},
},
userTyping: {
subscribe: (_: unknown, { roomId }: { roomId: string }) => {
return pubsub.asyncIterableIterator(
`${EVENTS.USER_TYPING}.${roomId}`
);
},
resolve: (payload: { userTyping: TypingIndicator }) => {
return payload.userTyping;
},
},
},
};
// Helfer-Funktion: Event publishen (z.B. aus Mutation-Resolver)
export const publishMessage = (message: Message) => {
pubsub.publish(`${EVENTS.MESSAGE_ADDED}.${message.roomId}`, {
messageAdded: message,
});
};
Claude Code Tipp: Claude Code kennt den Unterschied zwischen asyncIterator (deprecated) und asyncIterableIterator (aktuell, ab graphql-subscriptions v3). Bei neuen Projekten immer die aktuelle API verwenden — Claude Code fragt proaktiv nach der verwendeten Version.
2. graphql-ws — WebSocket Transport & Authentication
graphql-ws ist der moderne Standard für GraphQL über WebSockets. Es ersetzt das veraltete subscriptions-transport-ws Protokoll und wird von Apollo Client, URQL und allen modernen GraphQL-Clients unterstützt. Claude Code konfiguriert Server und Authentication-Middleware automatisch.
graphql-ws Server-Setup mit HTTP + WebSocket auf einem Port
// server.ts
import { createServer } from 'http';
import { WebSocketServer } from 'ws';
import { useServer } from 'graphql-ws/use/ws';
import { makeExecutableSchema } from '@graphql-tools/schema';
import { ApolloServer } from '@apollo/server';
import { expressMiddleware } from '@apollo/server/express4';
import express from 'express';
import { typeDefs } from './schema';
import { resolvers } from './resolvers';
import { verifyToken } from './auth';
const schema = makeExecutableSchema({ typeDefs, resolvers });
const app = express();
const httpServer = createServer(app);
// WebSocket Server auf dem gleichen Port wie HTTP
const wsServer = new WebSocketServer({
server: httpServer,
path: '/graphql',
});
// graphql-ws: WebSocket-Handler an den Schema binden
const serverCleanup = useServer(
{
schema,
// Context-Funktion für jeden neuen WebSocket-Client
context: async (ctx) => {
const token = ctx.connectionParams?.authorization as string;
if (!token) throw new Error('Unauthorized: No token provided');
const user = await verifyToken(token);
if (!user) throw new Error('Unauthorized: Invalid token');
return { user };
},
// Lifecycle Hooks für Monitoring/Logging
onConnect: (ctx) => {
console.log(`[WS] Client connected: ${ctx.extra.socket.remoteAddress}`);
},
onDisconnect: (ctx, code, reason) => {
console.log(`[WS] Client disconnected: ${code} ${reason}`);
},
onSubscribe: (ctx, msg) => {
console.log(`[WS] Subscription: ${msg.payload.operationName}`);
},
},
wsServer
);
// Apollo Server für HTTP-Queries und Mutations
const apolloServer = new ApolloServer({
schema,
plugins: [
{
// Cleanup WebSocket Server wenn Apollo Server stoppt
async serverWillStart() {
return {
async drainServer() {
await serverCleanup.dispose();
},
};
},
},
],
});
await apolloServer.start();
app.use('/graphql', expressMiddleware(apolloServer));
httpServer.listen(4000, () => {
console.log('Server ready at http://localhost:4000/graphql');
console.log('WebSocket ready at ws://localhost:4000/graphql');
});
Auth JWT-Authentication in WebSocket-Verbindungen
WebSockets übermitteln Auth-Tokens nicht im HTTP-Header, sondern als connectionParams beim Verbindungsaufbau.
// auth.ts
import jwt from 'jsonwebtoken';
interface JwtPayload {
userId: string;
username: string;
roles: string[];
}
export const verifyToken = (token: string): JwtPayload | null => {
try {
// Bearer-Prefix entfernen falls vorhanden
const cleaned = token.replace(/^Bearer\s+/i, '');
return jwt.verify(cleaned, process.env.JWT_SECRET!) as JwtPayload;
} catch {
return null;
}
};
Wichtig — subscriptions-transport-ws ist veraltet: Das alte Protokoll (graphql-ws npm-Paket v1-v4) hat Breaking Changes verursacht und ist in 2025/2026 deprecated. Claude Code verwendet automatisch graphql-ws v6+ mit dem graphql-ws-Protokoll, nicht das alte subscriptions-transport-ws-Protokoll. Bei bestehenden Projekten: Migration prüfen.
3. Apollo Server + Apollo Client
Apollo ist das meistgenutzte GraphQL-Ökosystem in TypeScript-Projekten. Apollo Server 4 bringt ein modernisiertes Plugin-System, Apollo Client 3 bietet den useSubscription React Hook. Claude Code generiert beide Seiten — Server-Resolver mit InMemoryPubSub und Client-Code mit Subscription-Management.
Apollo Server Mutation-Resolver der Events publisht
// resolvers/mutation.resolver.ts
import { PubSub } from 'graphql-subscriptions';
import { MessageService } from '../services/message.service';
import { EVENTS } from './subscription.resolver';
export const mutationResolvers = {
Mutation: {
sendMessage: async (
_: unknown,
{ content, roomId }: { content: string; roomId: string },
{ user, pubsub }: { user: User; pubsub: PubSub }
) => {
// Message in DB speichern
const message = await MessageService.create({
content,
roomId,
authorId: user.userId,
});
// Event an alle Subscriber publishen
await pubsub.publish(
`${EVENTS.MESSAGE_ADDED}.${roomId}`,
{ messageAdded: message }
);
return message;
},
setTyping: async (
_: unknown,
{ roomId, isTyping }: { roomId: string; isTyping: boolean },
{ user, pubsub }: { user: User; pubsub: PubSub }
) => {
await pubsub.publish(
`${EVENTS.USER_TYPING}.${roomId}`,
{
userTyping: {
userId: user.userId,
username: user.username,
roomId,
isTyping,
},
}
);
return true;
},
},
};
Apollo Client useSubscription Hook in React
Claude Code generiert Apollo Client-Setup und React Hooks in einem Schritt, inklusive Split-Link für HTTP und WebSocket.
// apollo-client.ts
import { ApolloClient, InMemoryCache, HttpLink, split } from '@apollo/client';
import { GraphQLWsLink } from '@apollo/client/link/subscriptions';
import { createClient } from 'graphql-ws';
import { getMainDefinition } from '@apollo/client/utilities';
// HTTP Link für Queries und Mutations
const httpLink = new HttpLink({
uri: 'https://api.example.com/graphql',
});
// WebSocket Link für Subscriptions
const wsLink = new GraphQLWsLink(
createClient({
url: 'wss://api.example.com/graphql',
connectionParams: () => ({
// Token beim WebSocket-Verbindungsaufbau mitsenden
authorization: `Bearer ${localStorage.getItem('token')}`,
}),
// Automatisches Reconnect bei Verbindungsabbruch
retryAttempts: 5,
retryWait: async (retries) => {
await new Promise((r) => setTimeout(r, 1000 * retries));
},
})
);
// Split: Subscriptions → WS, alles andere → HTTP
const splitLink = split(
({ query }) => {
const definition = getMainDefinition(query);
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
);
},
wsLink,
httpLink
);
export const client = new ApolloClient({
link: splitLink,
cache: new InMemoryCache(),
});
React Hook useSubscription — Live-Chat Component
// ChatRoom.tsx
import { useSubscription, useMutation, gql } from '@apollo/client';
import { useState, useEffect, useRef } from 'react';
const MESSAGE_ADDED_SUBSCRIPTION = gql`
subscription OnMessageAdded($roomId: ID!) {
messageAdded(roomId: $roomId) {
id
content
createdAt
author {
id
username
}
}
}
`;
const USER_TYPING_SUBSCRIPTION = gql`
subscription OnUserTyping($roomId: ID!) {
userTyping(roomId: $roomId) {
userId
username
isTyping
}
}
`;
export function ChatRoom({ roomId }: { roomId: string }) {
const [messages, setMessages] = useState<Message[]>([]);
const [typingUsers, setTypingUsers] = useState<Set<string>>(new Set());
// Subscription für neue Nachrichten
useSubscription(MESSAGE_ADDED_SUBSCRIPTION, {
variables: { roomId },
onData: ({ data }) => {
if (data.data?.messageAdded) {
setMessages((prev) => [...prev, data.data!.messageAdded]);
}
},
});
// Subscription für Typing-Indikator
useSubscription(USER_TYPING_SUBSCRIPTION, {
variables: { roomId },
onData: ({ data }) => {
const { userId, username, isTyping } = data.data?.userTyping ?? {};
setTypingUsers((prev) => {
const next = new Set(prev);
isTyping ? next.add(username) : next.delete(username);
return next;
});
},
});
return (
<div className="chat-room">
<div className="messages">
{messages.map((msg) => (
<div key={msg.id} className="message">
<strong>{msg.author.username}</strong>: {msg.content}
</div>
))}
</div>
{typingUsers.size > 0 && (
<div className="typing-indicator">
{[...typingUsers].join(', ')} schreibt...
</div>
)}
</div>
);
}
4. Filtering Subscriptions — withFilter() und user-spezifische Events
Ohne Filtering erhalten alle Subscriber alle Events — das ist ineffizient und kann zu Datenlecks führen. withFilter() aus graphql-subscriptions erlaubt es, Events server-seitig zu filtern, bevor sie an den Client gesendet werden. Claude Code generiert typsichere Filter-Funktionen basierend auf der Schema-Definition.
withFilter Raumbasiertes und user-spezifisches Filtering
// resolvers/subscription.resolver.ts (mit Filtering)
import { PubSub, withFilter } from 'graphql-subscriptions';
const pubsub = new PubSub();
export const subscriptionResolvers = {
Subscription: {
messageAdded: {
// withFilter(asyncIterator, filterFunction)
subscribe: withFilter(
// 1. Iterator: alle Message-Events
() => pubsub.asyncIterableIterator(EVENTS.MESSAGE_ADDED),
// 2. Filter: nur Events für den richtigen Raum zurückgeben
(payload, variables, context) => {
// Raum-Filter
if (payload.messageAdded.roomId !== variables.roomId) {
return false;
}
// Access Control: User muss Mitglied des Raums sein
return context.user.hasAccessToRoom(variables.roomId);
}
),
resolve: (payload: { messageAdded: Message }) => payload.messageAdded,
},
// Direktnachrichten: nur für den Empfänger
directMessage: {
subscribe: withFilter(
() => pubsub.asyncIterableIterator(EVENTS.DIRECT_MESSAGE),
(payload, _, context) => {
// Nur der Empfänger sieht seine Direktnachrichten
return payload.directMessage.recipientId === context.user.userId;
}
),
resolve: (payload: { directMessage: DirectMessage }) =>
payload.directMessage,
},
// Notifications: nach Typ filtern
notification: {
subscribe: withFilter(
() => pubsub.asyncIterableIterator(EVENTS.NOTIFICATION),
(
payload,
variables: { types?: string[] },
context
) => {
// User-Ownership prüfen
if (payload.notification.userId !== context.user.userId) return false;
// Optional: Notification-Typ filtern
if (variables.types?.length) {
return variables.types.includes(payload.notification.type);
}
return true;
}
),
resolve: (payload: { notification: Notification }) => payload.notification,
},
},
};
Advanced Conditional Subscriptions — Client-seitige Skip-Option
// React Component: Subscription nur wenn User eingeloggt
useSubscription(NOTIFICATION_SUBSCRIPTION, {
variables: {
types: ['MENTION', 'REPLY', 'LIKE'],
},
// skip: Subscription wird nicht gestartet wenn skip=true
skip: !currentUser || !currentUser.notificationsEnabled,
onData: ({ data }) => {
if (data.data?.notification) {
showToast(data.data.notification);
incrementUnreadCount();
}
},
onError: (error) => {
console.error('Subscription error:', error);
// Reconnect-Logik oder User-Feedback
},
});
Performance-Tipp: Statt viele granulare Subscriptions zu erstellen, empfiehlt Claude Code oft einen Activity-Stream-Ansatz: Ein einziger Subscription-Endpunkt pro Kontext (z.B. roomActivity(roomId)) der Union-Typen zurückgibt. Das reduziert WebSocket-Verbindungen und vereinfacht das Client-Management erheblich.
5. Production Setup — Redis Pub/Sub für horizontale Skalierung
InMemoryPubSub funktioniert nur auf einem einzelnen Server-Prozess. In Production mit mehreren Instanzen (Load Balancer, Docker Swarm, Kubernetes) müssen Events über alle Instanzen hinweg geteilt werden. Die Lösung: Redis als verteilter PubSub-Adapter. Claude Code generiert das komplette Production-Setup inklusive Fehlerbehandlung und Reconnect-Logik.
Redis graphql-redis-subscriptions Setup
# Installation
npm install graphql-redis-subscriptions ioredis
// pubsub.ts — Redis PubSub statt InMemory
import { RedisPubSub } from 'graphql-redis-subscriptions';
import Redis from 'ioredis';
const redisOptions = {
host: process.env.REDIS_HOST ?? 'localhost',
port: Number(process.env.REDIS_PORT) || 6379,
password: process.env.REDIS_PASSWORD,
// TLS für Production
tls: process.env.NODE_ENV === 'production' ? {} : undefined,
// Automatisches Reconnect
retryStrategy: (times: number) => {
if (times > 10) return null; // Aufgeben nach 10 Versuchen
return Math.min(times * 200, 3000); // Exponential backoff
},
};
// Separate Publisher- und Subscriber-Verbindungen (Redis Best Practice)
const publisher = new Redis(redisOptions);
const subscriber = new Redis(redisOptions);
publisher.on('error', (err) => console.error('Redis publisher error:', err));
subscriber.on('error', (err) => console.error('Redis subscriber error:', err));
// RedisPubSub ist ein Drop-in-Replacement für InMemoryPubSub
export const pubsub = new RedisPubSub({
publisher,
subscriber,
// Serializer/Deserializer für komplexe Objekte
serializer: JSON.stringify,
deserializer: JSON.parse,
});
Kubernetes Horizontal Scaling — Architektur-Überblick
# docker-compose.yml (Development mit Redis)
version: '3.9'
services:
api:
build: .
ports:
- "4000:4000"
environment:
REDIS_HOST: redis
REDIS_PORT: "6379"
JWT_SECRET: ${JWT_SECRET}
depends_on:
- redis
# Mehrere Instanzen zum Testen
deploy:
replicas: 3
redis:
image: redis:7-alpine
ports:
- "6379:6379"
command: redis-server --appendonly yes
volumes:
- redis_data:/data
# NGINX als Load Balancer
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- api
volumes:
redis_data:
# nginx.conf — WebSocket-Upgrade korrekt konfigurieren
upstream graphql_api {
least_conn; # Load Balancing Strategie
server api:4000;
server api:4001;
server api:4002;
}
server {
listen 80;
location /graphql {
proxy_pass http://graphql_api;
proxy_http_version 1.1;
# WebSocket Upgrade Headers — KRITISCH!
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# WebSocket Timeout erhöhen
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}
Health Subscription Health Monitoring
// health.ts — Subscription-Metriken tracken
import { ApolloServerPlugin } from '@apollo/server';
let activeSubscriptions = 0;
export const subscriptionMetricsPlugin: ApolloServerPlugin = {
async requestDidStart() {
return {
async executionDidStart({ operationName, operation }) {
if (operation?.operation === 'subscription') {
activeSubscriptions++;
console.log(`[Metrics] Active subscriptions: ${activeSubscriptions}`);
}
return {
async executionDidEnd() {
if (operation?.operation === 'subscription') {
activeSubscriptions--;
}
},
};
},
};
},
};
// Health-Endpoint für Load Balancer
app.get('/health', (req, res) => {
res.json({
status: 'ok',
activeSubscriptions,
redisConnected: publisher.status === 'ready',
uptime: process.uptime(),
});
});
Skalierungs-Tipp von Claude Code: Ab etwa 10.000 gleichzeitigen WebSocket-Verbindungen empfiehlt sich ein dedizierter Subscription-Server (getrennt von Query/Mutation). Claude Code kann diese Architektur automatisch aus einem monolithischen Setup extrahieren — einfach nach "WebSocket-Skalierung" fragen.
6. GraphQL Subscriptions vs WebSockets vs SSE
Nicht jedes Echtzeit-Feature braucht GraphQL Subscriptions. Die Wahl zwischen GraphQL Subscriptions, rohen WebSockets und Server-Sent Events (SSE) hängt vom Use Case, der Team-Erfahrung und den Anforderungen ab. Claude Code empfiehlt immer die einfachste Lösung die das Problem löst.
Vergleich Technologie-Matrix: Wann was verwenden
| Kriterium |
GraphQL Subscriptions |
Raw WebSockets |
Server-Sent Events (SSE) |
| Typsicherheit |
Vollständig (Schema + Codegen) |
Keine (manuell) |
Keine (manuell) |
| Kommunikation |
Bidirektional |
Bidirektional |
Nur Server → Client |
| Protokoll |
WebSocket (graphql-ws) |
WebSocket |
HTTP/2 Long Poll |
| Setup-Komplexität |
Mittel (Schema + Resolver) |
Niedrig (direkt) |
Sehr niedrig |
| Skalierung |
Redis PubSub nötig |
Custom Broker nötig |
Einfacher (HTTP) |
| Browser-Support |
Sehr gut (über WS) |
Sehr gut |
Sehr gut (nativ) |
| Reconnect |
Automatisch (Client) |
Manuell |
Automatisch (Browser) |
| Authentifizierung |
connectionParams (WS) |
Custom Token (WS) |
Standard HTTP Header |
| Ideale Use Cases |
Chat, Kollaboration, Dashboards mit existierendem GraphQL-API |
Gaming, Custom Binary-Protokolle, maximale Performance |
Notifications, Feeds, einfache Status-Updates |
| Nicht geeignet für |
Projekte ohne GraphQL, sehr hohe Nachrichtenfrequenz |
Teams ohne WS-Erfahrung, einfache Push-Notifications |
Bidirektionale Kommunikation, komplexe Datenstrukturen |
Entscheidungsbaum Welche Technologie wählen?
Nutze GraphQL Subscriptions wenn:
- Dein Backend bereits GraphQL nutzt (Query + Mutation vorhanden)
- Du Typsicherheit und Schema-Dokumentation brauchst
- Bidirektionale Kommunikation mit komplexen Datenstrukturen nötig ist
- Du Apollo Client oder URQL auf dem Frontend einsetzt
- Events gefiltert und user-spezifisch ausgeliefert werden sollen
Nutze SSE wenn:
- Nur Server-zu-Client-Kommunikation gebraucht wird (Notifications, Feeds)
- Du kein WebSocket-Infrastruktur aufbauen willst
- Einfachheit und schnelle Implementierung Priorität haben
- Das Backend REST ist und kein GraphQL-Umbau geplant ist
Nutze Raw WebSockets wenn:
- Du maximale Performance mit binären Protokollen brauchst (z.B. Gaming)
- Das GraphQL-Overhead zu groß ist (z.B. Hochfrequenz-Trading)
- Ein proprietäres Protokoll implementiert werden muss
SSE Zum Vergleich: SSE-Implementierung in Express
So einfach ist SSE — Claude Code kann auf Wunsch von GraphQL Subscriptions auf SSE migrieren oder beides parallel betreiben.
// SSE Endpoint — deutlich einfacher als WebSocket
app.get('/events/notifications', (req, res) => {
// SSE Headers setzen
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
res.flushHeaders();
// Authentifizierung via Standard-Header
const user = verifyToken(req.headers.authorization);
if (!user) { res.status(401).end(); return; }
// Event senden
const send = (event: string, data: unknown) => {
res.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`);
};
// Heartbeat alle 30 Sekunden (verhindert Timeout)
const heartbeat = setInterval(() => res.write(': heartbeat\n\n'), 30000);
// Cleanup bei Client-Disconnect
req.on('close', () => clearInterval(heartbeat));
});
// React Client (kein extra Package nötig!)
useEffect(() => {
const es = new EventSource('/events/notifications');
es.addEventListener('notification', (e) => {
handleNotification(JSON.parse(e.data));
});
return () => es.close();
}, []);
Fazit: GraphQL Subscriptions mit Claude Code in Production
GraphQL Subscriptions sind die natürliche Erweiterung eines bestehenden GraphQL-APIs um Echtzeit-Funktionalität. Das Schema bleibt konsistent, Typen werden geteilt, die Developer Experience ist durchgängig. Mit Claude Code reduziert sich der Aufwand für ein vollständiges Setup dramatisch:
Zusammenfassung Was Claude Code automatisch generiert
- Schema-Design: Subscription-Typen, Union-Typen, Input-Validierung
- Server-Setup: Apollo Server 4 + graphql-ws + HTTP/WS auf einem Port
- Resolver: subscribe-Funktion mit AsyncIterableIterator, resolve-Funktion
- Authentication: JWT-Verifikation in connectionParams, Context-Propagation
- Filtering: withFilter() mit typsicheren Filter-Funktionen
- Redis PubSub: RedisPubSub-Adapter, separate Publisher/Subscriber-Verbindungen
- NGINX-Konfiguration: WebSocket-Upgrade Headers, Load Balancing
- Apollo Client: Split-Link, useSubscription Hook, automatisches Reconnect
- Monitoring: Health-Endpoint, Active-Subscription-Metriken
Der entscheidende Vorteil: Claude Code versteht den Zusammenhang zwischen Schema, Server und Client. Wenn das Schema geändert wird, aktualisiert Claude Code automatisch Resolver, Typen und Client-Hooks — konsistent über die gesamte Stack-Ebene. Kein manuelles Nachziehen von Typen, keine vergessenen Resolver.
Für Production-Deployments mit Redis, Kubernetes und NGINX ist der Weg vom ersten Schema bis zum skalierbaren Echtzeit-System mit Claude Code auf wenige Stunden reduziert — statt Tage an Boilerplate, Dokumentations-Recherche und Trial-and-Error.
GraphQL-Modul im Kurs
Im Claude Code Mastery Kurs: vollständiges GraphQL-Modul — Schema-Design, Resolver, DataLoader, Subscriptions und Production-Deployment mit Apollo Server 4.
14 Tage kostenlos testen →