REST zu GraphQL migrieren: Schrittweise Strategie ohne Big Bang
AI generated
{ }
type
GraphQL · REST API · Migration · BFF
REST zu GraphQL migrieren
die schrittweise Strategie ohne Big Bang

Eine bestehende REST-API auf einen Schlag durch GraphQL zu ersetzen, ist der sicherste Weg, Produktionsausfälle zu provozieren. Mit einer BFF-Schicht, dem Strangler-Fig-Pattern und einem klaren Rollout-Plan lässt sich REST zu GraphQL migrieren, während beide Protokolle monatelang parallel und risikofrei koexistieren.

18 Min. Lesezeit BFF · Strangler Fig · Schema-first · Resolver-Rollout GraphQL 16 · REST · Legacy-Migration

1. Warum ein Big Bang bei der GraphQL-Migration scheitert

Der Wunsch, eine gewachsene REST-API komplett durch GraphQL zu ersetzen, ist verständlich, aber der direkte Weg dorthin scheitert in der Praxis fast immer. Wer REST zu GraphQL migrieren will, indem alle Endpunkte gleichzeitig neu gebaut und alle Clients an einem Stichtag umgestellt werden, riskiert einen mehrwöchigen Freeze für neue Features, während parallel Regressionen in produktionskritischen Bereichen entstehen. Der Big Bang zwingt dazu, jede Fachlogik ein zweites Mal zu testen, bevor der alte Pfad überhaupt abgeschaltet werden darf.

Die Alternative ist eine inkrementelle Strategie, bei der REST und GraphQL über Monate hinweg nebeneinander existieren, während Traffic Stück für Stück von REST auf GraphQL wandert. Wer REST zu GraphQL migrieren als kontinuierlichen Prozess statt als Projekt mit festem Enddatum versteht, kann jederzeit anhalten, wenn Kapazität fehlt, und jederzeit weitermachen, sobald wieder Zeit ist. Diese Flexibilität ist der eigentliche Wert einer schrittweisen Migration, nicht nur die reduzierte Risikofläche.

2. Die BFF-Schicht als sicherer Startpunkt

Der praktikabelste erste Schritt, um REST zu GraphQL migrieren zu starten, ist eine Backend-for-Frontend-Schicht, die GraphQL nach außen spricht und im Inneren die bestehenden REST-Endpunkte aufruft. Diese BFF-Schicht ändert an den Backend-Services zunächst nichts, sie fügt lediglich eine Übersetzungsebene hinzu. Frontend-Teams können sofort GraphQL-Queries schreiben, obwohl die eigentlichen Daten noch aus denselben REST-Diensten kommen, die seit Jahren produktiv laufen.

Dieser Ansatz reduziert das Risiko drastisch, weil die fachliche Logik in den Backend-Services unverändert bleibt. Der BFF übernimmt ausschließlich Aggregation, Typumwandlung und Feld-Selektion, klassische GraphQL-Stärken, die REST nicht bietet. Erst in einem zweiten Schritt, wenn die BFF-Schicht stabil läuft, werden einzelne REST-Aufrufe im Resolver durch direkte Datenbankzugriffe oder native GraphQL-Services ersetzt, ohne dass Clients davon etwas mitbekommen.


# BFF schema: mirrors what the REST API already exposes,
# just reshaped into a typed, queryable graph
type Order {
  id: ID!
  status: OrderStatus!
  items: [OrderItem!]!
  customer: Customer!
  total: Money!
}

type Query {
  order(id: ID!): Order
  orders(customerId: ID!, limit: Int = 20): [Order!]!
}

// BFF resolver: thin adapter calling the existing REST endpoint,
// no business logic duplicated here
const resolvers = {
  Query: {
    order: async (_parent, { id }, { restClient }) => {
      // Still hits the legacy REST endpoint under the hood
      const response = await restClient.get(`/api/orders/${id}`);
      return mapRestOrderToGraphQL(response.data);
    },
  },
};

function mapRestOrderToGraphQL(restOrder: RestOrder): Order {
  return {
    id: restOrder.order_id,
    status: restOrder.status.toUpperCase(),
    items: restOrder.line_items.map(mapLineItem),
    customer: { id: restOrder.customer_id, name: restOrder.customer_name },
    total: { amount: restOrder.grand_total, currency: restOrder.currency_code },
  };
}

3. Strangler-Fig-Pattern: REST-Endpunkte schrittweise ablösen

Das Strangler-Fig-Pattern, benannt nach dem Würgefeigenbaum, der einen Wirtsbaum langsam umschließt und ersetzt, beschreibt genau die Migrationslogik hinter REST zu GraphQL migrieren: Neue Funktionalität entsteht direkt in GraphQL, bestehende Funktionalität wird Endpunkt für Endpunkt, Feld für Feld, in den GraphQL-Layer hineingezogen, während der alte REST-Code so lange bestehen bleibt, bis kein Resolver mehr auf ihn zugreift. Der alte Baum stirbt erst, wenn er komplett umschlossen ist.

Entscheidend ist die Reihenfolge: Man beginnt nicht mit dem komplexesten Endpunkt, sondern mit einem gut abgegrenzten, wenig frequentierten Bereich, um Prozess und Tooling risikoarm zu etablieren. Erst wenn dieser erste Slice erfolgreich produktiv läuft, folgt der nächste, größere Bereich. Diese Reihenfolge macht jede Migrationsphase zu einem eigenständigen, rückrollbaren Release, statt zu einem monolithischen Umbau, der als Ganzes funktionieren oder scheitern muss.

4. Schema-first: das GraphQL-Schema vor dem Code entwerfen

Bei einer Migration ist die Versuchung groß, das GraphQL-Schema eins zu eins aus den bestehenden REST-Response-Strukturen abzuleiten. Das führt aber dazu, dass historische REST-Altlasten, inkonsistente Feldnamen, redundante IDs, verschachtelte Wrapper-Objekte, unverändert in das neue Schema übernommen werden. Wer REST zu GraphQL migrieren richtig angeht, entwirft das Zielschema stattdessen unabhängig von der aktuellen REST-Struktur, orientiert an dem, was Clients tatsächlich benötigen.

Dieser Schema-first-Ansatz bedeutet in der Praxis: Erst mit den Frontend-Teams die ideale Query-Form festlegen, dann rückwärts die Resolver-Implementierung bauen, die diese Form aus den vorhandenen REST-Daten zusammensetzt. Die Übersetzungsarbeit landet komplett im Resolver, nicht im Schema. Das erzeugt zwar kurzfristig mehr Mapping-Code, verhindert aber, dass technische Schulden aus der REST-Ära dauerhaft im neuen GraphQL-Vertrag zementiert werden.


# Target schema designed independently from legacy REST shape -
# clean naming, no redundant wrapper objects, proper types
type Customer {
  id: ID!
  email: String!
  fullName: String!
  addresses: [Address!]!
  loyaltyTier: LoyaltyTier!
}

# Legacy REST response for comparison (what the resolver translates FROM):
# {
#   "cust_id": "8842",
#   "email_addr": "jane@example.com",
#   "first_name": "Jane",
#   "last_name": "Doe",
#   "addr_list": { "items": [...], "count": 2 },
#   "tier_code": "GOLD_02"
# }

5. Resolver als dünne Adapter über bestehende REST-Endpunkte

In der Übergangsphase sind GraphQL-Resolver bei dieser Migration bewusst dünn gehalten: Sie rufen bestehende REST-Endpunkte auf, transformieren die Antwort in die Zielform und geben sie zurück. Keine neue Fachlogik entsteht im Resolver selbst, sie bleibt vollständig im bestehenden Backend-Service. Diese Disziplin verhindert, dass sich Geschäftsregeln während der Migration dupliziert an zwei Stellen wiederfinden, was später zu inkonsistentem Verhalten zwischen REST und GraphQL führen würde.

Ein zentraler Fallstrick bei dieser Umsetzung ist N+1: Ruft ein GraphQL-Resolver für eine Liste von Bestellungen pro Bestellung erneut einen REST-Endpunkt auf, entstehen hunderte HTTP-Requests, wo die alte REST-API einen einzigen Response mit Embedded-Daten geliefert hat. Ein DataLoader, der REST-Aufrufe pro Request-Zyklus batcht und dedupliziert, ist deshalb ab dem ersten produktiven Resolver Pflicht, nicht optionale Optimierung für später.


// DataLoader wraps the legacy REST endpoint to prevent N+1
// during the transition period, before native batching exists
import DataLoader from "dataloader";

const customerLoader = new DataLoader<string, Customer>(async (ids) => {
  // Legacy REST endpoint supports batch fetch via query param
  const response = await restClient.get("/api/customers", {
    params: { ids: ids.join(",") },
  });
  const byId = new Map(response.data.map((c: RestCustomer) => [c.cust_id, c]));
  return ids.map((id) => mapRestCustomerToGraphQL(byId.get(id)));
});

6. Parallele Koexistenz: REST und GraphQL im selben System

Für den gesamten Migrationszeitraum, oft sechs bis achtzehn Monate, müssen REST und GraphQL denselben Datenbestand konsistent bedienen. Wer REST zu GraphQL migrieren ohne Datenintegritätsprobleme durchführen will, muss sicherstellen, dass Schreiboperationen über beide Pfade dieselbe Validierung und dieselben Nebenwirkungen auslösen, etwa Event-Publishing oder Cache-Invalidierung. Ein Mutation-Resolver, der Bestelldaten direkt in der Datenbank ändert, während der parallele REST-Endpunkt weiterhin ein Event auslöst, erzeugt sonst stille Inkonsistenzen.

Der pragmatischste Weg ist, auch Mutations zunächst über den bestehenden REST-Write-Pfad zu leiten, genau wie bei Queries, und erst später eigenständige Schreiblogik im GraphQL-Layer zu implementieren. Das verzögert zwar die vollständige Ablösung von REST intern, garantiert aber, dass während der gesamten Koexistenzphase nur ein einziger Ort existiert, an dem Geschäftsregeln für Schreiboperationen gepflegt werden.

7. Clients schrittweise umstellen ohne Breaking Changes

Die Umstellung der Clients selbst ist der Teil der Migration, der am stärksten mit dem Rest des Teams abgestimmt werden muss. Statt einer App-weiten Umstellung, die einen einzigen Deploy-Tag erzwingt, sollte REST zu GraphQL migrieren auf Feature-Ebene erfolgen: Ein neues Feature wird direkt mit GraphQL gebaut, ein bestehender Screen wird bei der nächsten ohnehin geplanten Überarbeitung umgestellt, kritische Legacy-Bereiche bleiben bewusst bei REST, bis ihre Migration einen klaren fachlichen Anlass hat.

Feature Flags sind dabei das wichtigste technische Hilfsmittel: Ein Flag pro migriertem Screen erlaubt, GraphQL für einen Teil der Nutzer zu aktivieren, Fehlerraten und Latenzen zu vergleichen, und im Problemfall sofort auf REST zurückzufallen, ohne einen neuen Client-Release auszurollen. Diese Rückfalloption ist während der gesamten Übergangszeit der wichtigste Sicherheitsmechanismus der gesamten Strategie.

8. REST-Endpunkte sicher abschalten: Traffic-getriebene Entscheidungen

Der letzte und oft unterschätzte Schritt ist die tatsächliche Abschaltung alter REST-Endpunkte. Ohne belastbare Traffic-Daten neigen Teams dazu, Endpunkte aus reiner Vorsicht jahrelang am Leben zu erhalten, obwohl kein Client mehr darauf zugreift. Wer REST zu GraphQL migrieren sauber abschließen will, instrumentiert jeden REST-Endpunkt mit Zugriffsmetriken, bevor überhaupt migriert wird, und definiert einen klaren Schwellenwert, etwa null Requests über dreißig Tage, ab dem ein Endpunkt als abschaltbar gilt.

Ein zweistufiges Vorgehen hat sich bewährt: Zunächst wird der Endpunkt mit einem Deprecation-Header versehen, der in Response-Headern und Logs sichtbar ist, danach folgt eine Übergangsfrist von typischerweise vier bis acht Wochen, in der verbleibende Aufrufer identifiziert und aktiv kontaktiert werden. Erst danach wird der Endpunkt entfernt, nie ohne vorherige Beobachtungsphase, unabhängig davon, wie sicher man sich fühlt, dass niemand mehr zugreift.

9. Migrationsstrategien im direkten Vergleich

Nicht jede Migrationsstrategie passt zu jedem Team. Die folgende Tabelle stellt die gängigen Ansätze bei REST zu GraphQL migrieren gegenüber.

Strategie Risiko Zeitaufwand Geeignet für
Big Bang Rewrite Sehr hoch Kurz, aber riskant konzentriert Kleine, wenig kritische Systeme
BFF mit REST-Passthrough Niedrig Sofort startbereit Produktionskritische Legacy-Systeme
Strangler Fig, Slice für Slice Niedrig bis mittel Lang, aber planbar Große, komplexe REST-Landschaften
Paralleler Neubau ohne BFF Hoch Doppelte Wartung während Übergang Selten empfehlenswert

Die Kombination aus BFF-Einstieg und Strangler-Fig-Fortsetzung liefert in der Praxis das beste Verhältnis aus Risiko und Geschwindigkeit. Sie erlaubt, sofort mit GraphQL-Queries zu arbeiten, ohne auf eine vollständige Backend-Migration warten zu müssen, und schafft gleichzeitig einen klaren, iterativen Pfad zur vollständigen Ablösung von REST.

Mironsoft

GraphQL-Migration, BFF-Architektur und Magento-Integration

Eure REST-API schrittweise auf GraphQL umstellen?

Wir entwerfen mit euch einen risikoarmen Migrationsplan, bauen die BFF-Schicht als sicheren Einstieg und begleiten den Strangler-Fig-Rollout bis zur vollständigen Ablösung eurer Legacy-Endpunkte.

Migrationsplan

Slice-Priorisierung, Traffic-Analyse und Rollout-Reihenfolge für eure REST-Landschaft

BFF-Implementierung

GraphQL-Schema-Design und dünne Resolver über bestehende REST-Endpunkte

Client-Umstellung

Feature-Flag-gesteuerte Migration eurer Frontend-Teams ohne Breaking Changes

10. Zusammenfassung

Wer REST zu GraphQL migrieren will, sollte den Big Bang von Anfang an ausschließen. Eine BFF-Schicht, die GraphQL nach außen spricht und intern bestehende REST-Endpunkte aufruft, ermöglicht sofortigen Start ohne Backend-Risiko. Das Strangler-Fig-Pattern zieht Funktionalität Slice für Slice in den neuen Layer, während der alte Code so lange bestehen bleibt, bis kein Resolver mehr auf ihn angewiesen ist.

Entscheidend für den Erfolg sind drei Disziplinen: ein schema-first entworfenes Zielschema statt einer Eins-zu-eins-Übernahme der REST-Struktur, konsequentes DataLoader-Batching gegen N+1 in Übergangsresolvern, und Traffic-Metriken als einzige verlässliche Grundlage für die endgültige Abschaltung alter Endpunkte. Wer diese drei Punkte beachtet, kann REST zu GraphQL migrieren, ohne jemals einen riskanten Cutover-Tag einplanen zu müssen.

REST zu GraphQL migrieren — Das Wichtigste auf einen Blick

BFF als Einstieg

GraphQL-Schicht vor bestehenden REST-Endpunkten, kein Backend-Umbau nötig, sofort startbereit.

Strangler Fig

Slice für Slice migrieren, jede Phase eigenständig releasbar und rückrollbar.

Schema-first

Zielschema unabhängig von REST-Altlasten entwerfen, Mapping-Arbeit gehört in den Resolver.

Traffic-getriebene Abschaltung

Erst Metriken sammeln, dann deprecaten, erst danach Endpunkte tatsächlich entfernen.

11. FAQ: REST zu GraphQL migrieren

1Warum scheitert ein Big Bang?
Alle Endpunkte und Clients gleichzeitig umzustellen konzentriert das Risiko auf einen Zeitpunkt und macht Rollbacks extrem aufwendig.
2Was ist eine BFF-Schicht?
Spricht nach außen GraphQL, ruft intern bestehende REST-Endpunkte auf. Kein Backend-Umbau nötig, sofortiger Start möglich.
3Was bedeutet Strangler Fig?
Slice für Slice migrieren, alter Code bleibt bis zur letzten Abhängigkeit bestehen und stirbt erst dann.
4Schema aus REST-Responses ableiten?
Nein, das übernimmt Altlasten unverändert. Schema-first entwerfen, Mapping-Arbeit gehört in den Resolver.
5N+1 in Übergangsresolvern verhindern?
DataLoader batcht REST-Aufrufe pro Request-Zyklus. Ohne ihn entstehen bei Listen leicht hunderte Einzelrequests.
6Mutations während der Übergangsphase?
Zunächst über bestehenden REST-Write-Pfad leiten, damit Geschäftsregeln nur an einer Stelle gepflegt werden.
7Clients ohne Breaking Changes umstellen?
Feature-Flag-gesteuert je Screen, erlaubt sofortigen Rückfall auf REST bei Problemen.
8Wann ist ein Endpunkt sicher abschaltbar?
Nach Zugriffsmetriken, Deprecation-Header und mehrwöchiger Übergangsfrist ohne nennenswerten Traffic.
9Wie lange dauert die Migration typischerweise?
Für mittelgroße Systeme realistisch sechs bis achtzehn Monate, abhängig von Umfang und verfügbarer Kapazität.
10Muss REST komplett verschwinden?
Nein, manche Endpunkte, etwa für Webhooks oder Drittsysteme, bleiben sinnvoll dauerhaft REST-basiert.