35 points par GN⁺ 2025-05-24 | 2 commentaires | Partager sur WhatsApp
  • OpenAI a expliqué à la PGConf.dev 2025 comment utiliser PostgreSQL sans sharding tout en absorbant efficacement le trafic de plusieurs centaines de millions d’utilisateurs
  • Pour résoudre le problème de goulot d’étranglement sur les écritures, l’entreprise a adopté plusieurs approches, dont la répartition des écritures, l’optimisation des requêtes et la gestion du schéma
  • Parmi les principaux enjeux figurent les limites structurelles et les difficultés d’exploitation de PostgreSQL, comme le gonflement des tables/index lié au design MVCC et le retard de réplication causé par le WAL
  • Les stratégies d’optimisation des requêtes, comme la répartition de la charge de lecture, la limitation des transactions longues et la réduction de l’usage des ORM, sont au cœur de l’approche
  • OpenAI atteint 1 million de QPS grâce à plus de 40 réplicas répartis géographiquement, tout en garantissant une forte disponibilité même en cas d’incident

Le cas de montée en charge massive de PostgreSQL chez OpenAI

Contexte

  • Une grande partie des services essentiels d’OpenAI dépend de PostgreSQL
  • En cas de panne de la base de données, l’ensemble des services est directement affecté
  • OpenAI a déjà connu des interruptions de services majeurs, dont ChatGPT, à cause de problèmes liés à PostgreSQL
  • OpenAI exploite sur Azure Database managé une architecture Primary-Replica (un Primary unique + plus de 40 Replicas)
  • Dans un environnement servant 500 millions d’utilisateurs actifs par mois, la scalabilité est un facteur clé du succès de l’entreprise

Principaux défis

  • Le trafic de lecture peut être réparti sur plusieurs Replicas, mais les requêtes d’écriture se concentrent sur un Primary unique, ce qui crée un goulot d’étranglement
  • Principaux axes d’amélioration
    • Déporter et répartir toutes les écritures possibles
    • Minimiser les nouveaux accès directs au Primary DB par les nouveaux services
  • La structure MVCC (Multi-Version Concurrency Control) présente des inconvénients : gonflement des tables/index, tuning complexe du garbage collection, vérifications de visibilité des index
  • Quand le nombre de Replicas augmente, le trafic WAL (Write-Ahead Logging) grimpe lui aussi fortement, faisant de la bande passante réseau un autre facteur limitant

Réponses apportées

Répartition de la charge sur la base Primary

  • Prévision et atténuation de la charge d’écriture :
    • Déporter toutes les écritures possibles
    • Empêcher les écritures inutiles au niveau applicatif
    • Appliquer le Lazy Write et ajuster la fréquence des backfills
  • La charge de lecture est répartie autant que possible sur les Replicas ; lorsqu’un traitement sur le Primary est inévitable, une forte efficacité est exigée

Optimisation des requêtes

  • Les transactions longues monopolisent les ressources système pendant longtemps et retardent le garbage collection
  • Application de timeouts par session/requête/client, limitation des sessions Idle in transaction
  • Le texte souligne que l’usage des ORM peut accroître l’inefficacité et recommande de les utiliser avec prudence
  • Optimisation de requêtes complexes à jointures multiples (ex. : jointure sur 12 tables)

Gestion du point de défaillance unique (SPOF)

  • En cas de panne du Primary, les écritures deviennent impossibles ; les Replicas, eux, permettent de maintenir la continuité en lecture même en cas d’incidents partiels
  • Les requêtes critiques (haute priorité) sont traitées sur des Replicas dédiés afin de limiter les interférences avec les requêtes moins prioritaires

Gestion du schéma

  • La création de nouvelles tables et l’introduction de nouvelles charges de travail sont limitées sur le cluster
  • L’ajout/suppression de colonnes n’est autorisé que pour des opérations légères tenant dans une limite de 5 secondes ; les opérations imposant une réécriture complète de table sont interdites
  • La création/suppression d’index n’est autorisée qu’avec l’option CONCURRENTLY
  • Des requêtes longues de plus d’1 seconde bloquent en continu les changements de schéma ; il faut donc optimiser ou déporter ces requêtes au niveau applicatif

Résultats opérationnels

  • 1 million de QPS (lecture + écriture) traités sur l’ensemble du cluster, au service des principaux produits d’OpenAI
  • Aucune augmentation du retard de réplication malgré l’ajout d’une quarantaine de Replicas
  • Déploiement de Read-only Replicas dans différentes régions, avec maintien d’une faible latence
  • Une seule panne SEV0 liée à PostgreSQL au cours des 9 derniers mois
  • Une capacité suffisante a été sécurisée pour absorber la croissance future

Exemples d’incidents

  • Échec du cache entraînant un effet de cascade
  • Bug où, sous forte charge CPU, le processus WALSender cesse de transmettre le WAL et entre dans une boucle → retard de réplication

Demandes d’amélioration proposées à PostgreSQL

  1. Gestion des index : proposition d’une fonction de désactivation sûre des index inutiles, afin de réduire le risque avant suppression
  2. Observabilité : demande d’indicateurs basés sur des histogrammes/quantiles de latence, comme p95 et p99
  3. Historique des changements de schéma : besoin d’une fonction d’enregistrement des modifications de schéma telles que les DDL
  4. Clarification de la signification des vues de monitoring : questions sur les causes et les réponses à apporter lorsqu’une session reste longtemps en état ClientRead
  5. Optimisation des paramètres par défaut : les valeurs par défaut de PostgreSQL sont jugées trop conservatrices ; demande de meilleurs paramètres par défaut ou de nouvelles heuristiques

Commentaire de Lao Feng

  • La stratégie de montée en charge d’OpenAI dans un environnement aussi extrême constitue un cas d’usage concret précieux pour les développeurs core de PostgreSQL
  • Des services à très grande échelle comme Tantan en Chine ont connu des expériences similaires (33 Replicas, 400 000 QPS, sharding côté application)
  • Avec le matériel haute performance actuel, l’exemple d’OpenAI suggère qu’une montée en charge agressive reste possible avec un seul cluster PostgreSQL, sans qu’une base distribuée soit systématiquement nécessaire
  • OpenAI utilise Azure PostgreSQL managé, plus de 40 Replicas, un déploiement cross-region, ainsi que Kubernetes + PgBouncer
  • Malgré le soutien étroit de l’équipe Azure PostgreSQL, la compétence opérationnelle côté application/DBA et l’observabilité restent indispensables
  • Mention du monitoring via Datadog, ainsi que de son coût et de sa charge en performances
  • Le savoir-faire d’exploitation, les retours d’échec et les actifs DBA sont essentiels à la qualité de service

Q&R de Lao Feng

Fonction de désactivation des index

  • En interne, PostgreSQL permet de désactiver un index via le champ indisvalid (mais des droits superuser sont nécessaires, et l’usage est limité dans un environnement RDS)
  • En pratique, l’alternative consiste à vérifier l’utilisation des index via le monitoring avant de les supprimer en toute sécurité

Extension de l’observabilité : latence P95/P99

  • Le support des métriques par quantiles dans pg_stat_statements est difficile en raison du surcoût mémoire ; il existe toutefois des solutions de contournement comme pg_stat_monitor, eBPF ou le monitoring de latence au niveau applicatif
  • Dans l’environnement PostgreSQL managé d’Azure, certaines options (accès serveur, eBPF, etc.) ne sont pas prises en charge

Historique des changements de schéma

  • Il est possible d’utiliser les fichiers de logs, pgaudit, CREATE EVENT TRIGGER, pg_ddl_historization, etc. (mais des droits superuser sont nécessaires, avec des restrictions sur Azure RDS)
  • La demande porte sur un historique stocké sous forme de vue système/table interrogeable

Signification des vues de monitoring

  • La combinaison State=Active + WaitEvent=ClientRead signifie qu’une requête attend une entrée du client pendant l’exécution du statement ; diverses causes sont possibles et il ne s’agit pas forcément d’un bug
  • Il est possible de limiter les effets indésirables via une limite sur la durée de maintien des connexions (expiration au niveau réseau via HAProxy, gestion de la durée de vie dans le pool de connexions client, etc.), mais la prise en charge de ces mécanismes sur Azure n’est pas certaine

Paramètres par défaut

  • Les valeurs par défaut de PostgreSQL sont trop conservatrices, mais cela peut être compensé par des heuristiques fines par service ou par du tuning automatisé des paramètres (RDS, Pigsty, etc.)
  • Si les outils PostgreSQL intègrent à l’avenir une détection automatique du matériel et l’application correspondante des paramètres, la charge sur le terrain pourrait être allégée

Option d’exploitation en propre (self-hosting)

  • En pratique, une grande partie des problèmes d’exploitation provient moins de PostgreSQL lui-même que des limites du service managé Azure
  • Dans un environnement IaaS, construire soi-même un cluster PostgreSQL sur SSD NVMe (avec Pigsty, par exemple) apporte davantage de souplesse fonctionnelle et opérationnelle
  • Des solutions comme Pigsty peuvent résoudre de manière préventive la plupart des exigences d’OpenAI ; leur adoption peut donc être envisagée selon l’échelle et les besoins

2 commentaires

 
GN⁺ 2025-05-24
Commentaires Hacker News
  • J’ai assisté à la PGConf la semaine dernière, et j’ai été frappé de voir que cette présentation faisait partie des sessions les plus fréquentées, d’autant plus que la plupart des autres étaient centrées de manière assez introspective sur le développement de Postgres lui-même. Ce retour d’expérience apportait donc quelque chose de rafraîchissant. Il faut toujours garder à l’esprit que beaucoup d’équipes ne savent pas vraiment, en profondeur, comment faire passer certaines parties de leur stack à l’échelle quand leur produit commence à vraiment décoller. Cette présentation a été jugée comme une belle histoire montrant comment une petite équipe apprend en surmontant les problèmes. Plutôt qu’une réaction simpliste du type « pourquoi ne pas faire comme ceci ? », elle donnait à voir de vrais retours d’utilisateurs, rendant très concret le processus de croissance et la forte popularité du produit. En ce sens, c’était une session parfaitement adaptée à un événement surtout tourné vers les développeurs internes. Le message central de la présentation était que, tant que les écritures restent limitées, Postgres peut monter à une capacité de lecture énorme avec seulement des read replicas et une architecture à maître unique. Et ce message s’applique, selon lui, à la majorité des applications. Pendant la séance de questions-réponses, les questions venaient surtout de développeurs du cœur de Postgres cherchant à mieux comprendre le cas d’usage, avec très peu d’intention critique ; impression générale d’une communauté Postgres vraiment bienveillante et ouverte

    • À propos du message « si les écritures sont limitées, on peut fortement augmenter le débit de lecture de Postgres avec un maître unique et des réplicas en lecture seule » : en faisant passer des entretiens de design système, j’ai constaté que trop de candidats veulent introduire d’emblée une énorme architecture distribuée ou un système qui finit par casser la cohérence, même pour un système simple à 5 lectures par seconde. Dix millions d’utilisateurs, en réalité, ce n’est pas une échelle si énorme. Pendant que tout le secteur se focalise sur le scale horizontal, davantage de gens devraient réaliser que le matériel réel est devenu bien plus rapide et plus massif qu’on ne l’imagine. On vit dans un monde où l’on peut louer chez Amazon des serveurs avec 32 To de RAM. Et même à grande échelle, les garanties ACID restent bien trop précieuses

    • Merci, c’était vraiment le message clé que la présentation voulait transmettre (Bohan)

    • Question sur l’existence d’un lien vers les slides ou l’enregistrement de cette présentation

    • Impression que ce fil est un peu dur avec l’équipe concernée. Les utilisateurs HN les plus expérimentés dans ce domaine s’intéressent à la manière dont un service massif comme ChatGPT a été mis à l’échelle sur le plan architectural, et à la façon dont une entreprise aux ressources quasiment illimitées recrute. Le fait que le message de la présentation soit notamment « attention, les ORM peuvent facilement produire des requêtes inefficaces » est interprété comme un signe que cette équipe a encore peu d’expérience dans l’exploitation d’une infrastructure de cette taille

  • Du point de vue de la flexibilité, l’auto-hébergement de Postgres est séduisant (droits superuser, usage de fonctionnalités avancées, etc.), mais l’idée de l’exploiter soi-même reste un peu inquiétante. Souhait que les fournisseurs cloud proposent de façon standard un mécanisme permettant de désactiver un index côté query planner avant de le supprimer réellement. Pour une grande entreprise, choisir l’auto-hébergement pour personnaliser sa stack semble tout à fait raisonnable

    • Explication qu’il existe déjà plusieurs moyens dans Postgres de forcer ou de désactiver l’usage d’un index, y compris sur des instances Postgres managées dans le cloud. Par exemple en ajustant les paramètres du query planner requête par requête (ex. enable_indexscan=off), en ajoutant une simple opération arithmétique dans la clause where pour empêcher volontairement l’usage de l’index, ou encore via l’extension pg_hintplan (qui permet d’indiquer en commentaire quel index utiliser, voir : https://pg-hint-plan.readthedocs.io/en/latest/hint_table.html#hints-for-scan-methods)

    • (En précisant faire partie de l’équipe Azure Postgres) OpenAI n’utilise pas de self-hosting mais PostgreSQL managé d’Azure (Flexible Server)

    • L’intervenant OpenAI (Bohan) l’a confirmé directement : ils n’utilisent pas un environnement self-hosted mais Azure Database for PostgreSQL. Il s’excuse de ne pas avoir été plus clair sur le fait qu’il s’agit d’un service géré par Microsoft, même s’il a bien mentionné plusieurs fois « Azure Postgres » dans la présentation

    • Avis selon lequel il est surprenant que Postgres n’ait pas de DDL équivalent à MySQL ou MariaDB, qui permettent de rendre un index INVISIBLE ou IGNORED pour qu’il soit ignoré par le query planner

    • Citation seule de la phrase d’origine : « Self-hosting postgres a pour avantage la flexibilité… »

  • En réponse à une demande de fonctionnalité pour enregistrer l’historique des événements de modification de schéma (ajout/suppression de colonnes, etc.), il est indiqué que cela peut déjà être implémenté en temps réel via EVENT TRIGGER, avec comme exemple Aquameta (https://github.com/aquametalabs/aquameta)

    • Explication qu’eux aussi sont en train d’implémenter une gestion de l’historique des changements DDL dans leur propre environnement Postgres. Postgres étant très puissant, cela peut être fait de nombreuses manières, mais l’historisation et les journaux d’exploitation pour des bases volumineuses ou critiques sont aussi des besoins extrêmement courants. La plupart des gens ne comprennent leur importance qu’après l’avoir appris à leurs dépens. Et il ne s’agit pas seulement des changements DDL : quand des politiques métier importantes changent (par exemple le modèle tarifaire, des personnalisations de SKU ou de prix), il faut absolument garantir une « auditabilité ». Lorsqu’on conçoit un modèle pleinement relationnel, on constate qu’en pratique seules quelques tables changent fréquemment dans l’application, tandis que la majorité sont des tables « statiques » qui évoluent très peu ; quand elles changent, il faut conserver un historique précis pour mieux interpréter les données passées ou faciliter un rollback

    • Chez nous (Xata), pgroll (https://github.com/xataio/pgroll) et pgstream (https://github.com/xataio/pgstream) utilisent tous deux EVENT TRIGGER pour détecter les changements DDL, conserver l’historique des migrations de schéma ou inclure les événements de changement de schéma dans le flux de réplication logique. En revanche, la plupart des DBaaS basés sur Postgres limitent en partie EVENT TRIGGER à cause des privilèges superuser ; RDS/Aurora et Xata le prennent en charge, et Supabase s’y prépare aussi

    • Merci de se souvenir d’Aquameta, avec un petit teaser annonçant l’arrivée prochaine d’une nouvelle fonctionnalité sympa

  • Selon cet avis, tout ce qui est évoqué ici (création concurrente d’index à grande échelle, évitement des table rewrites, répartition du trafic, transaction timeouts, read replicas, etc.) est en réalité presque indispensable — ou relève du bon sens — même à des échelles bien plus petites que celle d’OpenAI. Les demandes adressées à Postgres sont d’ailleurs des demandes que tout le monde formule depuis longtemps. Le titre parle de « Next Level », mais en pratique cela ressemble plutôt à un système qui essaie désespérément de continuer à scaler en maître unique, sous la contrainte d’un nouveau workload limité. Le point principal est de supporter sans douleur une très forte charge en lecture, ce qui correspond simplement à l’usage classique des réplicas de lecture et du scale horizontal. La méthode consistant à désactiver un index en manipulant un champ interne (indisvalid) n’est pas officiellement fournie et reste une astuce risquée ; ce type de modification du catalogue système est dangereux. L’idée de s’appuyer sur les vues de monitoring pour décider quels index supprimer n’est pas non plus une solution parfaite ; pour déterminer de manière fiable quels index sont utiles ou non, il faut aussi examiner les query plans

    • Le TFA (article d’origine) indique qu’OpenAI traite un million de requêtes par seconde sur Azure, ce qui est interprété comme assez impressionnant en environnement cloud réel, surtout avec du stockage réseau. Cela dit, la charge semble répartie sur environ 40 réplicas de lecture, soit autour de 25 000 QPS par instance, ce qui paraît moins spectaculaire. Quant au débat sur l’usage des index, il est expliqué qu’avec des statistiques à jour et une bonne compréhension des caractéristiques de la base, il suffit en général de vérifier quel index est adapté et si les conditions/projections de la requête respectent bien le left-most prefix de l’index

    • Il est reproché à OpenAI de ne donner absolument aucune explication sur l’absence de sharding Postgres, ce qui est jugé frustrant. Un sharding par utilisateur semblerait pourtant beaucoup plus simple pour résoudre le problème, d’où l’interrogation sur ce maintien du maître unique

  • Il semble qu’ils utilisent la réplication physique ; de mon côté, j’envisage actuellement un passage à la réplication logique pour réduire les coûts (notamment le trafic sortant inter-régions). Depuis Postgres 17, la réplication logique native semble avoir beaucoup progressé, et je serais curieux d’avoir des retours sur sa viabilité en production

  • Remarque selon laquelle ils doivent probablement déjà utiliser en parallèle d’autres moteurs de stockage pour répondre à différents types de requêtes (clé-valeur, recherche, recherche vectorielle, cache, etc.), et qu’il est étrange que la présentation se concentre uniquement sur Postgres. Supposition qu’en interne ils appliquent sans doute plusieurs autres stratégies de répartition de trafic et de charge

  • Réflexion sur la possibilité d’obtenir de meilleures performances en auto-hébergeant uniquement l’instance d’écriture sur un serveur dédié équipé de SSD locaux rapides, tout en laissant les lectures sur un service managé

  • Position très tranchée : « faites du sharding de la base ». Un simple sharding par utilisateur ou par organisation permettrait, selon cet avis, de résoudre facilement les principaux problèmes actuels. Le fait de tenter plusieurs contournements complexes donnerait surtout l’impression de faire un détour inutile

    • La présentation voulait justement montrer qu’il est possible d’atteindre un débit énorme avec une architecture à maître unique, sans forcément passer par le sharding ; celui-ci a bien sûr été envisagé, mais le compromis n’était pas favorable et l’architecture actuelle scale déjà correctement

    • Réponse directe du présentateur d’OpenAI (Bohan) : le sharding du workload n’est pas un problème simple dans leur cas. Les workloads déjà fortement chargés en écriture ont été sortis de PostgreSQL pour être traités séparément sous forme shardée, et ce qui reste est presque entièrement en lecture seule ; introduire du sharding ici demanderait donc un effort énorme. Pour l’instant, Azure Database for PostgreSQL leur donne déjà suffisamment de scalabilité et de marge pour l’avenir. Cela dit, ils n’excluent pas complètement le sharding à long terme, mais ce n’est pas une priorité de court terme

    • Argument selon lequel le sharding n’est pas aussi simple qu’il n’y paraît. Si l’on choisit une base puissante, c’est parce qu’elle permet des analyses et des requêtes complexes ; si l’objectif était seulement de stocker et répartir des données, plusieurs montages NFS seraient plus simples

    • Retour plus réaliste : demander d’appliquer « simplement » du sharding à une base qui encaisse un million de requêtes par seconde n’a rien d’évident. Une clé de shard par organisation peut sembler naturelle, mais à cette échelle plus rien n’est vraiment simple

    • Réaction marquant un fort accord avec l’argument précédent

  • À propos de la recommandation de faire attention aux ORM, l’auteur explique considérer que tous les ORM — en particulier ceux pensés pour être compatibles avec plusieurs bases — posent problème. En pratique, ils poussent à penser les patterns de données uniquement au niveau du code applicatif et empêchent d’exploiter réellement les fonctionnalités puissantes propres à chaque base. Lui n’utilise aucun ORM, tire activement parti des requêtes et fonctionnalités spécifiques à Postgres, et estime qu’il vaut bien mieux se concentrer sur la puissance de la base que sur le langage ou la commodité. Conclusion : écrire un bon SQL à la main apporte plus de bonheur à l’ensemble du système

    • Lors d’une migration passée de DB2 vers psql, un ORM a au contraire été d’une grande aide pour minimiser le downtime. Grâce à lui, le changement de base a été transparent et la majeure partie de la logique n’a presque pas eu besoin d’être modifiée. Par ailleurs, tous les développeurs ne sont pas à l’aise avec l’écriture directe de requêtes, et lorsque les requêtes sont mélangées au code, le refactoring et la compréhension peuvent devenir très difficiles. Au final, SQL aussi sera abstrait sous forme de bibliothèque

    • Après de longues années avec Django ORM, jugé comme un logiciel vraiment remarquable, l’auteur dit qu’en utilisant récemment sqlc, qui transforme directement des requêtes en code Go, il a eu le sentiment d’un compromis idéal entre ORM et SQL brut

    • Position selon laquelle le problème vient peut-être simplement du fait de ne jamais avoir utilisé un très bon ORM (par exemple Entity Framework Core)

  • Petit retour léger : le vrai titre de la présentation semblait plutôt être « Scaling PostgreSQL to the Next Level at OpenAI »

 
ddogi 2025-05-25

On dirait que des produits commerciaux avec écriture multi-nœud, comme Oracle RAC ou DB2 pureScale, ne sont même pas envisagés.