Zum Hauptinhalt springen
OpenAI

11. September 2026

Ingenieurwesen

Onlinespeicher schnell für über 1 Milliarde Menschen mit ChatGPT skalieren

Wie wir unsere Anwendungsspeicherplattform Habitat in Python an beispielloses Wachstum angepasst haben.

Von Jon Lee, Chaomin Yu und Ben Ries, Members of Technical Staff

Laden …

Jedes Produkt von OpenAI ist auf schnellen und zuverlässigen Datenzugriff angewiesen, ob sich jemand anmeldet, die Codex-Einstellungen prüft oder eine neue Unterhaltung in ChatGPT beginnt. Für jede dieser Aktionen können viele einzelne Datenabfragen nötig sein, bevor das Produkt reagieren kann. Sind diese Anfragen langsam, wirkt auch das Produkt langsam. Schlagen diese Anfragen fehl, funktioniert das Produkt überhaupt nicht mehr.

Habitat ist die von uns entwickelte Onlinespeicherplattform, über die Produkte von OpenAI schnell und zuverlässig auf benötigte Informationen zugreifen können. Habitat verarbeitet inzwischen mehr als 70 Millionen Anfragen pro Sekunde und unterstützt in fast 40 geografischen Regionen Produkte, die wöchentlich von über 1 Milliarde Menschen genutzt werden. Habitat wurde erstmals für GPTs auf dem DevDay 2023 eingeführt, zunächst als einfache clientseitige Python-Bibliothek, die mit einer einzelnen Datenbank verbunden war. Heute ist Habitat ein komplexes verteiltes System, das mehr als 500 Petabyte Daten bereitstellt.

Abbildung 01 · Was ist Habitat?

Onlinespeicherplattform

Habitat ist die von uns entwickelte Onlinespeicherplattform, über die Produkte von OpenAI schnell und zuverlässig auf benötigte Informationen zugreifen können.

  • Anfrage
  • Antwort
  • Änderungen (CDC)

Clients

Onlinespeicherplattform

Speicherressourcen

  • ChatGPT
  • API
  • Codex
  • Interne Dienste
  • Und mehr

Habitat

  • CachingCaches
  • ACL-RichtlinienAutorisierung
  • Platzierung und DatenresidenzDatenresidenz
  • VerschlüsselungDatensicherheit
  • IsolierungMandantenfähigkeit
  • RatenbegrenzungRequest Shaping
  • RoutingSchemasuche · Datenresidenz
  • Azure Cosmos DBOnlinespeicher
  • NanobaseOnlinespeicher
  • ValkeyCaches
  • Blob-SpeicherSpeicherressourcen
CDC-DiensteChange Data Capture
  • Databricks
  • Rockset
  • Kafka
  • Und mehr

Infrastruktur in diesem Maßstab aufzubauen und zu betreiben, ist keine Kleinigkeit, aber auch nicht außergewöhnlich schwierig. Das Besondere an unserer Situation war das beispiellose Tempo der Skalierung: Wir mussten ein enormes Wachstum bei Nutzung und Produktnachfrage unterstützen und zugleich eine ausgereifte Plattform aufbauen. Systementwickelnde planen häufig für eine zehnfache Skalierung und hoffen, dass sie einige Jahre ausreicht, während sie die nächste Verzehnfachung vorbereiten. Bei uns hat sich der Umfang in den vergangenen drei Jahren jedes Jahr mehr als verzehnfacht. Aufbau und Betrieb von Habitat erforderten daher eine Reihe taktischer Entscheidungen in der richtigen Reihenfolge. Wir mussten jede Komponente bis ins Detail verstehen, um möglichst viel aus unserem bestehenden Stack herauszuholen, und zugleich Engpässe bei Speicher- und Rechenkapazität abwenden, um Zeit für grundlegende Investitionen zu gewinnen.

  • 70 Mio.+

    Anfragen pro Sekunde

  • 1 Mrd.+

    Menschen pro Woche

  • 500 PB+

    Daten

Mit OpenAI musste auch Habitat wachsen: zunächst zu ausreichender Zuverlässigkeit für geschäftskritischen Produktverkehr, dann zu ausreichender Geschwindigkeit für eine weltweite Nutzung und schließlich zu einem reibungslosen Betrieb in enormem Maßstab. Dieser Beitrag ist der erste Teil einer zweiteiligen Reihe über die Skalierung unseres Onlinespeichers. Wir zeigen, wie sich Habitat entwickelt hat, warum wir aus der Bibliothek einen Dienst gemacht haben und wie wir einen Dienst in der für Server-Stacks ungewöhnlichen Sprache Python zu einer zuverlässigen Speicherschicht ausgebaut haben.

In einem künftigen Beitrag erläutern wir ausführlich, wie wir Mandantenfähigkeit im großen Maßstab zuverlässig umgesetzt haben, mit welcher mehrstufigen Strategie wir die Leseleistung optimieren und wie wir unsere Zusammenarbeit mit Azure Cosmos DB skaliert haben, um eine beispiellose Nachfrage zuverlässig zu bewältigen.

Was ist Habitat?

Habitat entstand aus einer einfachen Idee: Produktentwickelnde sollten sich nicht mit der Verwaltung von Datenbanken befassen müssen. Habitat wurde erstmals zur Unterstützung von GPTs auf dem DevDay 2023 als kleine Python-Bibliothek eingeführt, die mit dem Hauptserver von ChatGPT kommunizierte. Sie unterstützte eine kleine Zahl von Vorgängen, die intern auf die Datenbankanwendung Azure Cosmos DB abgebildet wurden.

Die Bibliothek sollte Produktteams eine einfache Möglichkeit bieten, Daten zu speichern und abzurufen, ohne die zugrunde liegenden Details beherrschen zu müssen. Habitat übernahm die nötigen Aufgaben: Art und Herkunft beziehungsweise Ziel der Daten bestimmen, die Zulässigkeit der Anfrage prüfen und vieles mehr.

Produktentwickelnde müssen sich nicht mit Schemasuche, Routing, Autorisierung, Verschlüsselung, Serialisierung, Request Shaping und Verbindungspooling befassen. Sie mussten nicht einmal berücksichtigen, woher die Daten stammten: aus Azure Cosmos DB, Caches oder anderen Speichertypen.

Abbildung 02 · Habitat-Dienst

Vereinfachter Anfragefluss in Habitat

Durch die Auslagerung der Speicherlogik in einen eigenständigen Dienst schufen wir einen zentralen Kontrollpunkt für Bereitstellungen, Beobachtbarkeit und Plattformverbesserungen.

  • Anfrage
  • Antwort

Client

OpenAI

Azure Cosmos DB

Habitat-Client-SDK
envoy
  • habitat-serviceProzess 1
  • habitat-serviceProzess 2
  • habitat-serviceProzess 3
habitat-envoy
  • habitat-cosmos-db-us0
  • habitat-cosmos-db-us1
  • habitat-cosmos-db-eu0

Diese Python-Bibliothek funktionierte gut und wurde von Produktentwickelnden bei OpenAI rasch angenommen, obwohl es keine zentral gesteuerte Abkehr von selbst verwalteten Postgres- und Azure-Cosmos-DB-Instanzen gab.

Mit den wachsenden Produktanforderungen konnten Produktentwickelnde die gemeinsame Bibliothek zudem leicht um Funktionen wie clientseitiges Caching, Komprimierung oder Verschlüsselung ergänzen.

Einen Dienst zur besseren Unterstützung mehrerer komplexer Produkte entwickeln

Mitte 2025 hatte Habitat als clientseitige Implementierung seine Grenzen erreicht. Die Habitat-Schicht war komplexer und die Zahl der Dienste von OpenAI größer geworden. Abwärtskompatible Protokolländerungen waren daher nicht mehr praktikabel.

In einem Fall wollten wir die Auswirkungen des Ausfalls einer einzelnen Region auf unsere wichtigsten Datensätze begrenzen. Dazu wollten wir sie zu mehreren regional verteilten Azure-Cosmos-DB-Konten migrieren. Für diese Änderung mussten wir zusätzliche Routinglogik in den Client integrieren, sie zunächst per Feature Flag deaktivieren, die neue Version auf allen Clients bereitstellen und anschließend das Feature Flag aktivieren.

Die Koordination der Bereitstellungen über Dutzende Dienste hinweg und die Einführung mit jedem einzelnen Team dauerten mehrere Tage. Vor der Aktivierung stellten wir fest, dass wir mit Shadowing prüfen wollten, ob die Shardinglogik korrekt funktionierte. Auch die Einführung dieser Änderung dauerte mehrere Tage. Eine Fehlerbehebung für etwas, das sich als falsch erwiesen hatte? Noch einmal mehrere Tage. Schließlich konnten wir das Flag aktivieren. Doch dann setzte eines der Teams seinen Dienst aus anderen Gründen auf eine frühere, fehlerhafte Clientversion zurück und verursachte genau den Ausfall, den wir so aufwendig verhindern wollten.

Änderungen an der Clientbibliothek erforderten eine komplexe Abstimmung über Dutzende Dienste hinweg. Dieser Prozess wurde zunehmend fragil, ineffizient und anfällig für Betriebsfehler. Um diese operative Streuung bei künftigen Bereitstellungen zu verringern, beschlossen wir, Habitat in einen eigenständigen Dienst zu überführen.

Durch die Auslagerung der Speicherlogik in einen eigenständigen Dienst schufen wir einen zentralen Kontrollpunkt für Bereitstellungen, Beobachtbarkeit und Plattformverbesserungen. Statt fragmentierte Aktualisierungen zu verwalten, konnten wir Verbesserungen zentral umsetzen, sodass jedes Produkt von OpenAI sofort davon profitierte.

Ein zentraler Dienst bietet uns außerdem einen einzigen Kontrollpunkt für besonders starke grundlegende Funktionen zum Schutz und zur Sicherheit von Daten. Im Habitat-Dienst können wir Zugriffsrichtlinien zentral durchsetzen, Auditprotokolle führen und den Zugriff auf zugrunde liegende Speicherressourcen wie Azure Cosmos DB beschränken. Habitat spielt eine entscheidende Rolle beim Schutz von Nutzerdaten und verhindert unbefugte Zugriffe durch externe und interne Akteure sowie Agenten.

Einen Python-Dienst im großen Maßstab einführen

Wir wussten, dass wir einen Dienst brauchten. Trotz des zusätzlichen Aufwands von Python in einem Dienst wollten wir aber noch nicht von Python migrieren. Der Einsatz von Python für einen Dienst mit hohem Durchsatz erhöhte die Netzwerklatenz und verursachte im Vergleich zur lokalen Ausführung als Bibliothek erhebliche Skalierungskosten für CPU und Arbeitsspeicher. Zudem war uns klar, dass die Ineffizienz von Python bei einer hundertfachen Skalierung nicht mehr hinnehmbar wäre. Eine spätere Neuentwicklung war daher fast unvermeidlich.

Wir betrachteten dies jedoch als bewusste Aufnahme technischer Schulden. Unser vorrangiges Ziel war damals nicht die Optimierung von Kosten oder Ressourcen, sondern die Beseitigung von Hindernissen für Produktentwickelnde und eine stabile Plattform. Indem wir die Leistungseinbußen eines Python-Dienstes kurzfristig in Kauf nahmen, konnten wir dringendere Herausforderungen priorisieren, unsere zentralen APIs etablieren und eine robuste Infrastruktur aufbauen.

Zugleich setzten wir bewusst darauf, dass die rasche Weiterentwicklung unserer eigenen Programmiermodelle den technischen Weg künftig vereinfachen würde. Wir gingen davon aus, dass Codex und GPT die Migration bewältigbar machen würden, sobald eine vollständige Abkehr von Python erforderlich wäre. Diese Einschätzung erwies sich schließlich als richtig.

Habitat als Python-Dienst zu betreiben, war hinsichtlich der Leistung nicht optimal, aber notwendig. Mit Python können wir schnell vorankommen. Dennoch konnten wir nicht alle Vorsicht aufgeben und deutlich höhere Latenzen hinnehmen. Wenn eine durchschnittliche Nutzeranfrage Hunderte Datenbankaufrufe auslöst, spürt die Person den langsamsten davon. Unserer Erfahrung nach besteht die größte Herausforderung beim Betrieb eines Python-Dienstes in diesem Maßstab darin, diese Tail-Latenzen zu steuern.

Die asyncio-Verzögerung erfassen

Asyncio ermöglicht Python die gleichzeitige Ausführung E/A-gebundener Workloads. Es umgeht jedoch nicht den Python-GIL und ermöglicht keine CPU-Parallelität. Neben der E/A-intensiven Weiterleitung von Anfragen übernimmt Habitat viele CPU-intensive Aufgaben und Hintergrundprozesse: Routing, Komprimierung, Verschlüsselung, Prüfsummenbildung, Zustandsprüfungen nachgelagerter Systeme, Request Shadowing und Hedging.

Bei so vielen CPU-intensiven Workloads und Hintergrundaufgaben in unserem Dienst kann die Scheduling-Verzögerung von asyncio die Tail-Latenz von Anfragen leicht dominieren. Vor der Optimierung für den ersten Start unseres Dienstes zeigten Traces bei Anfragen mit einer Latenz ab p99: Der nachgelagerte Speicher antwortete zwar schnell, doch Anfragen stockten häufig, während sie darauf warteten, dass die zuständige Coroutine erneut eingeplant wurde und die Antwort verarbeiten konnte.

Abbildung 03 · Die asyncio-Verzögerung erfassen

Nebenläufigkeit ist keine CPU-Parallelität

Python asyncio ermöglicht die nebenläufige Verarbeitung von Anfragen, doch im CPU-Thread wird immer nur eine Anfrage ausgeführt. Wenn viel CPU-Arbeit anfällt, wirkt sich dies stark auf die Anfragelatenzen aus.

CPU-Verarbeitung von Anfragen/AntwortenPython-Netzwerkzugriff zum Lesen/SchreibenWarten auf Cosmos

Niedrige CPU-Last

Kurze Python-Schritte; E/A-Wartezeiten überschneiden sich

Hohe CPU-Last

Lange Python-Schritte lassen fertige Antworten warten

0.0 / 40 beispielhafte Einheiten

Bei Python-Diensten von OpenAI messen wir nicht nur die üblichen Auslastungs- und Sättigungswerte für Arbeitsspeicher, CPU, Netzwerk und Datenträger. Entscheidend ist auch, die asyncio-Schleife und ihre Auslastung zu überwachen und entsprechend zu optimieren.

Wir planen regelmäßig Hintergrundaufgaben ein und erfassen die Differenz zwischen erwarteter und tatsächlicher Ausführungszeit. So können wir die Scheduling-Verzögerung der Ereignisschleife in Echtzeit empirisch messen. Bei hoher Auslastung und vielen aufwendigen Aufgaben reichen schon wenige gleichzeitige Anfragen pro Prozess aus, um erheblichen Scheduling-Jitter zu verursachen: bis zu mehreren Hundert Millisekunden und in einigen Grenzfällen mehrere Sekunden.

Daher lassen wir jeden Prozess nur wenige gleichzeitige Anfragen bearbeiten und skalieren stattdessen die Zahl der Python-Worker-Prozesse stark horizontal.

Tail-Latenz in unseren Feature-Flag-Konfigurationen reduzieren

Beim ersten Start unseres Dienstes fanden wir durch CPU-Profiling im laufenden Betrieb eine Ursache für hohe asyncio-Verzögerungen und die daraus folgenden hohen Tail-Latenzen: das regelmäßige Parsen der JSON-Konfigurationen unserer Feature Flags über Statsig, ein Tool zur Verwaltung von Feature Flags, das unter anderem A/B-Tests ermöglicht.

Statsig war standardmäßig so konfiguriert, dass es jede Minute ohne Jitter aktualisierte Konfigurationen abfragte. Die Konfiguration enthielt sämtliche Produktivregeln aller Dienste. An anderer Stelle war aus Architekturgründen entschieden worden, bis zu acht Python-Prozesse pro Pod auszuführen, um die CPU stärker auszulasten und die Latenzen zu senken. Zusammen führte dies dazu, dass in jedem Pod einmal pro Minute alle Worker die Verarbeitung laufender Anfragen unterbrachen und ihre CPU-Zyklen stattdessen zum Parsen einer riesigen Konfigurationsdatei nutzten.

Nachdem wir die Ursache mithilfe des CPU-Profilings ermittelt hatten, war die Lösung einfach: eine kleinere, gezielte Konfiguration bereitstellen, das Aktualisierungsintervall verlängern und bei solchen Hintergrundaufgaben Jitter hinzufügen.

Lasten verteilen und Verbindungspools verwalten

Um die asyncio-Verzögerung niedrig zu halten, müssen Anfragen gut auf die Serverprozesse verteilt werden. Ohne entsprechende Abstimmung kann Verbindungspooling diesem Ziel entgegenwirken.

Bei clientseitigem Verbindungspooling richtet ein einzelner Clientprozess mit vielen gleichzeitigen Anfragen möglicherweise nur wenige Serververbindungen ein. Dadurch sendet er seine gesamte Last an nur wenige Prozesse. Bevor wir unsere Lastverteilung anpassten, schwankte die Auslastung unseres Dienstes stark. Einige Prozesse am Rand der Verteilung bearbeiteten fünf- bis zehnmal so viele gleichzeitige Anfragen wie der Durchschnitt.

Wir entdeckten dies zufällig bei einem Vorfall: Obwohl wir den Client stoppten, der einen Teil unseres Dienstes überlastete, blieb eine Gruppe von Prozessen noch lange nach der Lastspitze beeinträchtigt. Tatsächlich verschlechterte sich die Leistung dieser Prozesse unkontrolliert weiter. Sie erhielten immer mehr Anfragen, bis wir sie neu starteten. Sobald ein Pod überlastet war, sorgte ein bestimmtes Verhalten dafür, dass noch mehr Datenverkehr auf diesen Pod geleitet wurde. Einigen Personen in unserem Team war diese Fehlerklasse aus früheren Tätigkeiten gut bekannt: metastabiles Versagen(wird in einem neuen Fenster geöffnet).

Wir vermuteten den Verbindungspool als Ursache und begrenzten testweise die maximale Dauer der Verbindungswiederverwendung. Dies schwächte die Verschlechterung tatsächlich ab und bestätigte, dass unsere Untersuchung in die richtige Richtung ging. Weitere Untersuchungen ergaben, dass der aiohttp TCPConnector von Python Verbindungen standardmäßig nach LIFO wiederverwendet: Für die nächste Anfrage wird die zuletzt zurückgekehrte Verbindung ausgewählt. Normalerweise ist dies eine sinnvolle Standardeinstellung: Durch die Wiederverwendung aktueller Verbindungen können zusätzliche Verbindungen, die für Lastspitzen erstellt wurden, nach einer Leerlaufzeit geschlossen werden. Das verringert den Aufwand für ihre Aufrechterhaltung. In diesem Fall verursachte sie jedoch ein metastabiles Versagen. Während einer Lastspitze gaben langsamere, überlastete Server ihre Verbindungen später an den Pool zurück. Deshalb wählten nachfolgende Anfragen diese Verbindungen häufiger aus, wodurch sich immer mehr Datenverkehr auf den bereits beeinträchtigten Pods konzentrierte. Eine Anpassung des Verbindungspools an die FIFO-Wiederverwendung unterbrach diese Rückkopplung und verringerte zudem die Schwankungen bei Anfragen im stabilen Betrieb.

Abbildung 04A · Clientseitiges Verbindungspooling

LIFO leitet neue Arbeit zurück an den langsamen Prozess

Nach einer Lastspitze geben langsamere Server ihre Verbindungen zuletzt an den Pool zurück. LIFO sorgt dafür, dass sich mehr Arbeit auf genau diesen langsameren Servern konzentriert.

Eine anfängliche Lastspitze erreicht A, B und den langsameren Prozess C.

Abbildung 04B · Clientseitiges Verbindungspooling

FIFO unterbricht die Rückkopplung bei der Wiederverwendung von Verbindungen

FIFO hält nach einer Lastspitze mehr Verbindungen aktiv, verteilt die Workloads aber ausgewogen auf alle Server.

Eine anfängliche Lastspitze erreicht A, B und den langsameren Prozess C.

Heute nutzen wir in der Infrastruktur von OpenAI überwiegend Istio und Envoy für das Verbindungspooling und für bessere, an der Serverlast ausgerichtete Verteilungsstrategien. So vermeiden wir dieses Problem vollständig.

Nachgelagerte Ressourcen vor Überlastung schützen

Die Optimierung auf eine geringe asyncio-Verzögerung und die große Zahl von Python-Prozessen haben einen Nebeneffekt: Die enorme Zahl an Verbindungen kann nachgelagerte Abhängigkeiten leicht überlasten. Dieses Phänomen wird als „Thundering Herd“ bezeichnet.

Eine gewöhnliche tägliche Bereitstellung kann durch den ständigen Auf- und Abbau von Verbindungen erhebliche CPU-Last verursachen, wenn sie nicht bewusst langsam erfolgt. Auch ein Verbindungsleck kann durch die Sättigung des NAT-Gateways das Netzwerk lahmlegen. Solche Probleme treten auch bei anderen Diensten auf. Durch die um eine Größenordnung höhere Zahl von Prozessen sinkt die Auslöseschwelle jedoch erheblich. Häufig werden dabei Netzwerkressourcen gesättigt, deren Belastung Clients anhand des reinen Durchsatzes im stabilen Betrieb nicht erwarten.

Wir verwenden Envoy außerdem, um Verbindungen möglichst stark zu bündeln. Damit führen wir ein Upgrade der HTTP/1-Verbindungen von Python auf HTTP/2 durch, um Multiplexing zu nutzen. Anschließend bündeln wir diese Verbindungen und verlängern ihre Lebensdauer. Envoy bietet uns zudem eine zentrale Stelle für Ratenbegrenzungen und Circuit Breaker, die in jedem eigenständigen Python-Prozess weniger wirksam wären.

Abbildung 05 · Verbindungsbündelung

Dieselben Anfragen, weniger Verbindungen

Verbindungspooling und HTTP/2-Multiplexing verringern die Verbindungslast auf nachgelagerten Systemen.

AnfrageAntwortInaktive Keep-alive-Verbindung

Warum Habitat weniger leistet

Ein Grund dafür, dass wir Python so weit skalieren konnten, war die eingeschränkte API von Habitat. Sie hält die Kosten von Anfragen vorhersehbar. Statt Clients beliebige SQL-Abfragen erstellen zu lassen, die große Tabellenscans oder Joins über viele Tabellen auslösen könnten, stellt Habitat eine einfache NoSQL-API bereit. Der Verzicht auf eine leistungsstarke API ist ein bewusster Kompromiss im Design von Habitat.

Wir optimieren auf einfache, vorhersehbare Anfragen mit konstantem Arbeitsaufwand. Unserer Erfahrung nach lassen sich solche Systeme deutlich einfacher skalieren und nur schwer falsch verwenden. Anfragen mit unvorhersehbarem Fan-out sind im Betrieb gefährlich: Sie erschweren die Isolierung und Lastverteilung und verursachen abrupte Latenzsprünge, die sowohl für den Dienst als auch für seine Clients schwer zu skalieren sind.

Bevor wir zu Habitat und Azure Cosmos DB wechselten, waren die meisten Onlinedaten von OpenAI in Postgres gespeichert. Damals konnten wir alle Änderungen an Abfragen und Schemata leicht prüfen. So stellten wir vor der Bereitstellung im Produktivbetrieb sicher, dass sie sich korrekt verhielten und auf indizierte Daten zugriffen. Als Team und Produkte wuchsen, wurde dies schnell unbeherrschbar. Eine einzige neue, aufwendige Abfrage in einem stark frequentierten Pfad legte häufig die Datenbank lahm und verursachte Ausfälle.

Das Problem liegt im Kostenungleichgewicht: Teure und schwer auszuführende SQL-Abfragen lassen sich schnell und einfach schreiben. In Habitat vermeiden wir dies und machen aufwendige Abfragen auf Clientseite unübersehbar. Es gibt keine unbegrenzten Abfragen, die Habitat überlasten könnten. Bei komplexen Joins und Graphdurchläufen müssen die Produktteams einen Teil der aufwendigen Arbeit übernehmen. Dadurch wird das Gesamtdesign effizienter.

Habitat stellt eine NoSQL-API bereit, die nach dem Vorbild von TAO(wird in einem neuen Fenster geöffnet) auf clientdefinierten Objekt- und Kantentypen basiert. Clients definieren Objekte und Kanten sowie deren Beziehungen im Voraus, nicht jedoch den Inhalt der einzelnen Typen. Die entstehenden Beziehungen ähneln einem Graphen. Habitat selbst unterstützt jedoch keine üblichen Abfragen für Graphdurchläufe, sondern nur Abfragen direkter Kanten eines bestimmten Objekts.

Wir partitionieren diesen Graphen so, dass jedes Objekt und seine zugehörigen Kanten gemeinsam in einer Partition der Speicherebene liegen. Auf Datenbankebene versuchen wir jedoch nicht gezielt, Objekte gemeinsam mit den entfernten Objekten zu speichern, auf die ihre Kanten verweisen. Dadurch lässt sich das Modell für horizontale Skalierbarkeit leicht partitionieren. Graphdurchläufe sind jedoch ineffizient, da ein einzelner Schritt zwischen Objekten Daten aus zwei völlig unterschiedlichen, in verschiedenen Regionen gespeicherten Azure-Cosmos-DB-Konten abrufen kann.

Für Clients mit komplexeren Abfrageanforderungen stellen wir über Rockset eine sekundäre Offlineansicht von Habitat bereit. Wir übertragen Änderungen per Change Data Capture (CDC) nahezu in Echtzeit vom Onlinespeicher an isolierte Rockset-Instanzen. Jedes Clientteam ist selbst dafür verantwortlich, seine Rockset-Instanz für komplexe Abfragen zu skalieren.

Die Bereitstellung von Rockset verursacht für unsere Clients zusätzlichen Aufwand. Derzeit halten wir diesen Kompromiss jedoch für angemessen: Einfache Abfragen sind der Standard, während für komplexe Anforderungen ein Ausweichweg verfügbar bleibt. Dieses Design isoliert unseren Onlinespeicher von leseintensiven Analyse- und Suchworkloads.

Von Python zu Rust migrieren

Indem wir die Neuentwicklung in Python um ein Jahr verschoben, konnten wir uns während unseres rasanten Wachstums auf dringendere und wirkungsvollere Herausforderungen konzentrieren. Die Plattform war inzwischen ausgereifter und unser Wachstum beschleunigte sich weiter. Da Habitat gemessen an den CPU-Kernen der zweitgrößte Dienst bei OpenAI war und beim Envoy-Umfang auf Platz vier lag, war es schließlich Zeit, Python abzulösen. In Spitzenzeiten konnten wir mit Python mehr als 20 Millionen Anfragen pro Sekunde bearbeiten.

Im zweiten Quartal 2026 konnten wir den gesamten Dienst mit nur zwei Personen aus dem Engineering, Codex und GPT‑5.5 in Rust neu entwickeln. Der neue Rust-Dienst verarbeitet inzwischen 95 % unserer Produktivanfragen. In den kommenden Wochen werden wir Python vollständig außer Betrieb nehmen. Unsere Daten zeigen, dass der Rust-Dienst sechsmal CPU-effizienter und 15-mal speichereffizienter als die Python-Version ist. Auch die durchschnittlichen Latenzen und Tail-Latenzen sind deutlich niedriger. Weitere Erkenntnisse möchten wir in einem künftigen Blogbeitrag teilen.

Unsere Datenbankschicht Azure Cosmos DB optimieren

Der Python-Dienst, inzwischen ein Rust-Dienst, ist nur ein Teil von Habitat. Im zweiten Teil dieser Reihe darüber, wie wir unseren Onlinespeicher rasch für mehr als 1 Milliarde Menschen mit ChatGPT skaliert haben, befassen wir uns mit der Speicherschicht. Außerdem erklären wir, wie Habitat mehr als 500 Petabyte und über 70 Millionen Anfragen pro Sekunde verarbeitet.

Wenn du an OLTP-Systemen im Frontier-Maßstab und an dieser Art von Engineering arbeiten möchtest, sieh dir diese offene Stelle in unserem Team an.

Autoren

Jon Lee, Chaomin Yu und Ben Ries