Негізгі мазмұнға өту
OpenAI

2026 ж. 22 қаңтар

Инженерия

800 млн ChatGPT пайдаланушысына қызмет ететін PostgreSQL масштабы

Бохан Чжан, техникалық штат мүшесі

Жүктелуде…

Көп жылдар бойы PostgreSQL ChatGPT және OpenAI API-і сияқты негізгі өнімдерді қамтамасыз ететін ең маңызды ішкі дерек жүйелерінің бірі болды. Пайдаланушыларымыздың саны тез өсіп жатқандықтан, дерекқорларымызға түсетін жүктеме де экспоненциалды түрде артты. Соңғы бір жылда PostgreSQL жүктемеміз 10 еседен астам өсті және әлі де жылдам өсіп келеді.

Осы өсімді ұстап тұру үшін өндірістік инфрақұрылымды жетілдіру барысында біз жаңа түсінікке келдік: PostgreSQL-ды бұрын көпшілік ойлағаннан әлдеқайда үлкен, негізінен оқуға бағытталған жүктемелерді сенімді қолдайтындай етіп масштабтауға болады. Бұл жүйе (алғашында Калифорния университеті, Беркли ғалымдарының командасы жасаған) бізге бір негізгі Azure PostgreSQL flexible server instance(жаңа терезеде ашылады) және әлемнің бірнеше өңіріне таралған 50-ге жуық оқу репликасы арқылы орасан зор жаһандық трафикті қолдауға мүмкіндік берді. Бұл — OpenAI-де PostgreSQL-ды қатаң оңтайландыру мен мықты инженерияның арқасында 800 миллион пайдаланушы үшін секундына миллиондаған сұрауды қолдайтындай етіп қалай масштабтағанымыздың тарихы; сонымен қатар осы жолда алған негізгі сабақтарымызды да бөлісеміз.

Бастапқы дизайнымыздағы әлсіз тұстар

ChatGPT іске қосылғаннан кейін трафик бұрын-соңды болмаған қарқынмен өсті. Оны қолдау үшін біз қолданба деңгейінде де, PostgreSQL дерекқоры деңгейінде де ауқымды оңтайландыруларды жедел енгіздік, instance өлшемін ұлғайту арқылы тігінен және көбірек оқу репликаларын қосу арқылы көлденеңінен масштабтадық. Бұл архитектура бізге ұзақ уақыт бойы жақсы қызмет етті. Үздіксіз жетілдірулердің арқасында ол болашақ өсімге әлі де жеткілікті мүмкіндік береді.

Бір primary-і бар архитектура OpenAI ауқымының талаптарын орындай алатыны таңғаларлық естілуі мүмкін; алайда мұны практикада іске асыру оңай емес. Біз Postgres шамадан тыс жүктелуінен туындаған бірнеше SEV жағдайын көрдік, және олар көбіне бір үлгімен қайталанады: жоғары жақтағы мәселе дерекқор жүктемесінің күрт өсуіне әкеледі, мысалы кэш қабаты істен шыққанда жаппай cache miss болуы, CPU-ды толық жүктейтін қымбат көпжақты join-дардың көбеюі немесе жаңа функция іске қосылғанда write storm пайда болуы. Ресурс пайдалануы артқан сайын, сұрау кідірісі ұлғаяды және сұраулар timeout-қа ұшырай бастайды. Қайта жіберулер жүктемені одан әрі күшейтіп, бүкіл ChatGPT және API қызметтерінің сапасын нашарлатуы мүмкін тұйық шеңберді тудырады.

Жүктемені масштабтау диаграммасы

PostgreSQL негізінен оқуға бағытталған жүктемелерімізде жақсы масштабталғанымен, жазу трафигі жоғары кезеңдерде біз әлі де қиындықтарға кезігеміз. Бұл көбіне PostgreSQL-дың multiversion concurrency control (MVCC) іске асырылуына байланысты, ол оны жазуға бағытталған жүктемелер үшін азырақ тиімді етеді. Мысалы, сұрау tuple-ды не тіпті бір ғана өрісті жаңартқанда, жаңа нұсқа жасау үшін бүкіл жол көшіріледі. Жазу жүктемесі жоғары болғанда, бұл write amplification-ды едәуір арттырады. Сондай-ақ ол read amplification-ды да өсіреді, өйткені соңғы нұсқаны алу үшін сұраулар бірнеше tuple нұсқасын (dead tuples) сканерлеуі керек. MVCC кесте мен индекс көлемінің ұлғаюы, индекстерге қызмет көрсету шығынының артуы және autovacuum-ды күрделі баптау сияқты қосымша қиындықтар енгізеді. (Бұл мәселелерді Carnegie Mellon University-дегі проф. Andy Pavlo-мен бірге жазған PostgreSQL-дың біз ең жек көретін бөлігі(жаңа терезеде ашылады) атты блогта терең талдадық; ол PostgreSQL Wikipedia бетінде де дәйектелген(жаңа терезеде ашылады).)

PostgreSQL-ды миллиондаған QPS-ке масштабтау

Осы шектеулерді азайтып, жазу қысымын төмендету үшін біз shard-теуге болатын (яғни көлденеңінен бөлуге болатын) жазуға бағытталған жүктемелерді Azure Cosmos DB сияқты shard-талған жүйелерге көшірдік және көшіруді жалғастырып келеміз, сонымен бірге қажетсіз жазуларды азайту үшін қолданба логикасын оңтайландырдық. Сондай-ақ қазіргі PostgreSQL deployment-ына жаңа кестелер қосуды енді рұқсат етпейміз. Жаңа жүктемелер әдепкі бойынша shard-талған жүйелерге жіберіледі.

Инфрақұрылымымыз дамып жатқанымен, PostgreSQL shard-талмаған күйде қалды, барлық жазуды бір primary instance атқарады. Мұның басты себебі — бар қолданба жүктемелерін shard-тау өте күрделі әрі уақытты көп алады: ол жүздеген қолданба соңғы нүктесін өзгертуді талап етеді және айлар, тіпті жылдар алуы мүмкін. Біздің жүктемелеріміз негізінен оқуға бағытталғандықтан және біз кең ауқымды оңтайландырулар енгізгендіктен, қазіргі архитектура трафиктің әрі қарай өсуін қолдауға әлі де жеткілікті қор береді. Болашақта PostgreSQL-ды shard-тауды жоққа шығармасақ та, қазіргі және алдағы өсімге жеткілікті мүмкіндік бар болғандықтан, бұл жақын мерзімдегі басымдық емес.

Келесі бөлімдерде біз кездескен қиындықтарды және оларды шешу мен болашақтағы істен шығулардың алдын алу үшін енгізген ауқымды оңтайландыруларды тереңірек қарастырамыз; осылайша PostgreSQL-ды шегіне дейін жеткізіп, оны секундына миллиондаған сұрауға (QPS) масштабтадық.

Primary-ге түсетін жүктемені азайту

Қиындық: Жалғыз writer болғанда, single-primary конфигурациясы жазуды масштабтай алмайды. Жазудың күрт өсуі primary-ді тез шамадан тыс жүктеп, ChatGPT және API сияқты қызметтерге әсер етуі мүмкін.

Шешім: Жазу шарықтауларын өңдеуге жеткілікті сыйымдылық қалуы үшін біз primary-ге түсетін жүктемені — оқу да, жазу да — барынша азайтамыз. Мүмкін болғанның бәрінде оқу трафигі репликаларға ауыстырылады. Дегенмен кейбір оқу сұраулары primary-де қалуы керек, өйткені олар жазу транзакцияларының бөлігі. Мұндай жағдайда олардың тиімді болуына және баяу сұраулардан қашуға назар аударамыз. Жазу трафигі бойынша біз shard-теуге болатын, жазуға бағытталған жүктемелерді Azure CosmosDB сияқты shard-талған жүйелерге көшірдік. Shard-тауы қиынырақ, бірақ әлі де жоғары жазу көлемін тудыратын жүктемелерді көшіруге көбірек уақыт керек, және бұл процесс әлі жалғасып жатыр. Сонымен қатар қолданбаларымызды жазу жүктемесін азайту үшін белсенді түрде оңтайландырдық; мысалы, артық жазуларға әкелген қателерді түзеттік және орынды жерлерде lazy write енгізіп, трафик шарықтауларын тегістедік. Бұған қоса, кесте өрістерін backfill еткенде, шамадан тыс жазу қысымын болдырмау үшін қатаң rate limit қолданамыз.

Сұрауларды оңтайландыру

Қиындық: Біз PostgreSQL-да бірнеше қымбат сұрауды анықтадық. Бұрын бұл сұраулар көлемінің кенет өсуі CPU-дың үлкен бөлігін тұтынып, ChatGPT пен API сұрауларын баяулататын.

Шешім: Көп кестені біріктіретін кейбір қымбат сұраулар бүкіл қызметті айтарлықтай нашарлатуы, тіпті істен шығаруы мүмкін. Сұраулардың тиімді болуын және Online Transaction Processing (OLTP) жүйелеріндегі кең таралған антиүлгілерден аулақ болуын қамтамасыз ету үшін PostgreSQL сұрауларын үздіксіз оңтайландырып отыруымыз керек. Мысалы, біз бір кезде 12 кестені біріктіретін өте қымбат сұрауды анықтадық, және дәл осы сұраудың шарықтауы өткендегі жоғары маңыздылықтағы SEV жағдайларына себеп болған. Мүмкіндігінше күрделі көп кестелі join-дардан аулақ болуымыз керек. Егер join қажет болса, сұрауды бөліктерге ажыратып, күрделі join логикасын қолданба қабатына көшіруді қарастыру керегін түсіндік. Осындай проблемалы сұраулардың көбі Object-Relational Mapping фреймворктері (ORM) арқылы жасалады, сондықтан олардың шығаратын SQL-ын мұқият қарап, күткендей жұмыс істейтініне көз жеткізу маңызды. PostgreSQL-да ұзақ уақыт бос тұрған сұрауларды да жиі кездестіруге болады. Олардың autovacuum-ды бөгеп тастамауы үшін idle_in_transaction_session_timeout сияқты timeout-тарды баптау аса маңызды.

Бір нүктелі ақауды азайту

Қиындық: Егер оқу репликасы істен шықса, трафикті басқа репликаларға бағыттауға болады. Алайда жалғыз writer-ге сүйену бір нүктелі ақау дегенді білдіреді — егер ол істен шықса, бүкіл қызметке әсер етеді.

Шешім: Ең маңызды сұраулардың көбі тек оқу сұрауларын қамтиды. Primary-дегі бір нүктелі ақау қаупін азайту үшін біз бұл оқуларды writer-ден репликаларға ауыстырдық, осылайша primary істен шықса да бұл сұраулар қызмет көрсетуді жалғастыра алады. Жазу операциялары бәрібір сәтсіз болады, бірақ әсері азаяды; оқулар қолжетімді болып қалатындықтан, бұл енді SEV0 емес.

Primary ақауларын азайту үшін біз primary-ді High-Availability (HA) режимінде hot standby-пен бірге іске қосамыз — бұл трафикті қабылдауға әрдайым дайын, үздіксіз синхрондалып тұратын реплика. Егер primary істен шықса немесе техникалық қызмет үшін офлайнға шығарылса, downtime-ды азайту үшін standby-ді тез promotion жасай аламыз. Azure PostgreSQL командасы бұл failover-лардың өте жоғары жүктеме кезінде де қауіпсіз әрі сенімді болып қалуын қамтамасыз ету үшін көп жұмыс атқарды. Оқу репликаларының ақауларын өңдеу үшін біз әр өңірде жеткілікті сыйымдылық қоры бар бірнеше реплика орналастырамыз, осылайша бір репликаның істен шығуы өңірлік outage-ке әкелмейді.

Жүктемені оқшаулау

Қиындық: Біз PostgreSQL instance-тарында кейбір сұраулар ресурстардың шамадан тыс көп бөлігін тұтынатын жағдайларды жиі көреміз. Бұл сол instance-тарда жұмыс істейтін басқа жүктемелердің өнімділігін нашарлатуы мүмкін. Мысалы, жаңа функцияны іске қосу PostgreSQL CPU-ын қатты тұтынатын тиімсіз сұрауларды әкеліп, басқа маңызды функциялар сұрауларын баяулатуы мүмкін.

Solution: To mitigate the “noisy neighbor” problem, we isolate workloads onto dedicated instances to ensure that sudden spikes in resource-intensive requests don’t impact other traffic. Specifically, we split requests into low-priority and high-priority tiers and route them to separate instances. This way, even if a low-priority workload becomes resource-intensive, it won’t degrade the performance of high-priority requests. We apply the same strategy across different products and services as well, so that activity from one product does not affect the performance or reliability of another.

Connection pooling

Challenge: Each instance has a maximum connection limit (5,000 in Azure PostgreSQL). It’s easy to run out of connections or accumulate too many idle ones. We’ve previously had incidents caused by connection storms that exhausted all available connections.

Solution: We deployed PgBouncer as a proxy layer to pool database connections. Running it in statement or transaction pooling mode allows us to efficiently reuse connections, greatly reducing the number of active client connections. This also cuts connection setup latency: in our benchmarks, the average connection time dropped from 50 milliseconds (ms) to 5 ms. Inter-region connections and requests can be expensive, so we co-locate the proxy, clients, and replicas in the same region to minimize network overhead and connection use time. Moreover, PgBouncer must be configured carefully. Settings like idle timeouts are critical to prevent connection exhaustion.

PostgreSQL прокси диаграммасы

Әрбір оқу репликасының бірнеше PgBouncer подын іске қосатын өз Kubernetes deployment-ы бар. Біз бір Kubernetes Service артында бірнеше Kubernetes deployment-ын іске қосамыз, ол трафикті подтар арасында тең бөледі.

Caching

Challenge: A sudden spike in cache misses can trigger a surge of reads on the PostgreSQL database, saturating CPU and slowing user requests.

Solution: To reduce read pressure on PostgreSQL, we use a caching layer to serve most of the read traffic. However, when cache hit rates drop unexpectedly, the burst of cache misses can push a large volume of requests directly to PostgreSQL. This sudden increase in database reads consumes significant resources, slowing down the service. To prevent overload during cache-miss storms, we implement a cache locking (and leasing) mechanism so that only a single reader that misses on a particular key fetches the data from PostgreSQL. When multiple requests miss on the same cache key, only one request acquires the lock and proceeds to retrieve the data and repopulate the cache. All other requests wait for the cache to be updated rather than all hitting PostgreSQL at once. This significantly reduces redundant database reads and protects the system from cascading load spikes.

Scaling read replicas

Challenge: The primary streams Write Ahead Log (WAL) data to every read replica. As the number of replicas increases, the primary must ship WAL to more instances, increasing pressure on both network bandwidth and CPU. This causes higher and more unstable replica lag, which makes the system harder to scale reliably.

Solution: We operate nearly 50 read replicas across multiple geographic regions to minimize latency. However, with the current architecture, the primary must stream WAL to every replica. Although it currently scales well with very large instance types and high-network bandwidth, we can’t keep adding replicas indefinitely without eventually overloading the primary. To address this, we’re collaborating with the Azure PostgreSQL team on cascading replication(жаңа терезеде ашылады), where intermediate replicas relay WAL to downstream replicas. This approach allows us to scale to potentially over a hundred replicas without overwhelming the primary. However, it also introduces additional operational complexity, particularly around failover management. The feature is still in testing; we’ll ensure it’s robust and can fail over safely before rolling it out to production.

PostgreSQL каскадты репликация диаграммасы

Rate limit

Challenge: A sudden traffic spike on specific endpoints, a surge of expensive queries, or a retry storm can quickly exhaust critical resources such as CPU, I/O, and connections, which causes widespread service degradation.

Solution: We implemented rate-limiting across multiple layers—application, connection pooler, proxy, and query—to prevent sudden traffic spikes from overwhelming database instances and triggering cascading failures. It’s also crucial to avoid overly short retry intervals, which can trigger retry storms. We also enhanced the ORM layer to support rate limiting and when necessary, fully block specific query digests. This targeted form of load shedding enables rapid recovery from sudden surges of expensive queries.

Schema Management

Challenge: Even a small schema change, such as altering a column type, can trigger a full table rewrite(жаңа терезеде ашылады). We therefore apply schema changes cautiously—limiting them to lightweight operations and avoiding any that rewrite entire tables.

Solution: Only lightweight schema changes are permitted, such as adding or removing certain columns that do not trigger a full table rewrite. We enforce a strict 5-second timeout on schema changes. Creating and dropping indexes concurrently is allowed. Schema changes are restricted to existing tables. If a new feature requires additional tables, they must be in alternative sharded systems such as Azure CosmosDB rather than PostgreSQL. When backfilling a table field, we apply strict rate limits to prevent write spikes. Although this process can sometimes take over a week, it ensures stability and avoids any production impact.

Results and the road ahead

This effort demonstrates that with the right design and optimizations, Azure PostgreSQL can be scaled to handle the largest production workloads. PostgreSQL handles millions of QPS for read-heavy workloads, powering OpenAI’s most critical products like ChatGPT and the API platform. We added nearly 50 read replicas, while keeping replication lag near zero, maintained low-latency reads across geo-distributed regions, and built sufficient capacity headroom to support future growth.

This scaling works while still minimizing latency and improving reliability. We consistently deliver low double-digit millisecond p99 client-side latency and five-nines availability in production. And over the past 12 months, we’ve had only one SEV-0 PostgreSQL incident (it occurred during the viral launch(жаңа терезеде ашылады) of ChatGPT ImageGen, when write traffic suddenly surged by more than 10x as over 100 million new users signed up within a week.)

While we’re happy with how far PostgreSQL has taken us, we continue to push its limits to ensure we have sufficient runway for future growth. We’ve already migrated the shardable write-heavy workloads to our sharded systems like CosmosDB. The remaining write-heavy workloads are more challenging to shard—we’re actively migrating those as well to further offload writes from the PostgreSQL primary. We’re also working with Azure to enable cascading replication so we can safely scale to significantly more read replicas.

Looking ahead, we’ll continue to explore additional approaches to further scale, including sharded PostgreSQL or alternative distributed systems, as our infrastructure demands continue to grow.

Автор

Bohan Zhang

Алғыс

Осы жазбаға үлес қосқан Jon Lee, Sicheng Liu, Chaomin Yu және Chenglong Hao-ға, сондай-ақ PostgreSQL-ды масштабтауға көмектескен бүкіл командаға ерекше алғыс айтамыз. Сондай-ақ мықты серіктестігі үшін Azure PostgreSQL командасына алғыс білдіреміз.