Lumaktaw sa pangunahing content
OpenAI

Enero 22, 2026

Engineering

Pag-scale ng PostgreSQL para sa 800M na user ng ChatGPT

Ni Bohan Zhang, Miyembro ng Technical Staff

Naglo-load…

Sa loob ng maraming taon, isa sa mga pinakamahalagang data system ang PostgreSQL na nagpapagana sa mga pangunahing produkto tulad ng ChatGPT at OpenAI API. Habang mabilis na lumalaki ang aming user base, tumaas din nang husto ang mga pangangailangan sa aming mga database. Sa nakaraang taon, lumago nang higit sa 10 beses ang aming PostgreSQL load, at patuloy itong tumataas nang mabilis.

Ang aming mga pagsisikap na paunlarin ang aming imprastraktura sa produksyon para mapanatili ang paglaking ito ay nagbunyag ng bagong pananaw: maaaring i-scale ang PostgreSQL para maaasahang suportahan ang mas malalaking read-heavy na mga workload kaysa sa dati'y inaakala ng marami na posible. Nagbigay-daan sa amin (unang nilikha ng team ng mga siyentipiko sa University of California, Berkeley) na suportahan ang napakalaking pandaigdigang trapiko gamit ang isang primary Azure PostgreSQL flexible server instance(magbubukas sa bagong window) at halos 50 read replica na nakakalat sa iba't ibang rehiyon sa buong mundo. Ito ang kuwento kung paano namin pinalawak ang PostgreSQL sa OpenAI para suportahan ang milyun-milyong query kada segundo para sa 800 milyong user sa pamamagitan ng mahigpit na pag-optimize at matibay na engineering; tatalakayin din namin ang mahahalagang aral na natutunan namin sa proseso.

Mga crack sa aming paunang disenyo

Matapos ilunsad ang ChatGPT, lumago ang traffic sa hindi pa naganap na bilis. Para masuportahan ito, mabilis naming ipinatupad ang malawakang mga pag-optimize sa mga layer ng application at PostgreSQL database, lumawak sa pamamagitan ng pagtaas ng laki ng instance, at lumawag sa pamamagitan ng pagdaragdag ng mas maraming read replica. Matagal na kaming napagsilbihan nang maayos ng arkitekturang ito. Sa patuloy na mga pagpapabuti, patuloy itong nagbibigay ng sapat na landas para sa paglago sa hinaharap.

Maaaring nakakagulat na kayang matugunan ang single-primary architecture ang mga pangangailangan ng lawak ng OpenAI; gayunpaman, hindi simple ang pagsasakatuparan nito sa aktwal. Nakakita na kami ng ilang SEV na dulot ng Postgres overload, at kadalasan ay pare-pareho ang pattern: may upstream issue na nagdudulot ng biglaang pagtaas ng database load—gaya ng malawakang cache misses dahil sa pagkabigo ng caching layer, pagdami ng mabibigat na multi-way join na sumasagad sa CPU, o write storm mula sa paglulunsad ng bagong feature. Habang tumataas ang paggamit ng mapagkukunan, tumataas ang latency ng query at nagsisimulang mag-time out ang mga kahilingan. Lalo pang nagpapalaki ng load ang mga muling pagsubok, na nagti-trigger ng mabisyong cycle na may potensyal na pababain ang buong serbisyo ng ChatGPT at API.

Diagram ng pag-scale ng load

Bagama't mahusay ang pag-scale ng PostgreSQL para sa aming mga workload na mas mabigat sa pagbasa, nakakaranas pa rin kami ng mga hamon sa mga panahon ng mataas na trapiko ng pagsusulat. Ito ay pangunahing dahil sa implementasyon ng PostgreSQL ng multiversion concurrency control (MVCC), na nagpapababa ng kahusayan nito sa mga write-heavy na workload. Halimbawa, kapag nag-a-update ang query ng isang tuple o kahit isang field, kinokopya ang buong row para gumawa ng bagong bersyon. Sa ilalim ng mabibigat na load ng pagsusulat, nagreresulta ito sa makabuluhang pagtaas ng pagsusulat. Pinapataas din nito ang read amplification, dahil kailangang mag-scan ang mga query sa maraming bersyon ng tuple (mga patay na tuple) para makuha ang pinakabago. Nagpapakilala ang MVCC ng mga karagdagang hamon tulad ng paglobo ng table at index, mas mataas na overhead sa pagpapanatili ng index, at masalimuot na pag-tune ng autovacuum. (Makikita mo ang malalimang talakayan tungkol sa mga isyung ito sa blog na isinulat ko kasama si Prof. Andy Pavlo sa Carnegie Mellon University na pinamagatang The Part of PostgreSQL We Hate the Most(magbubukas sa bagong window), binanggit(magbubukas sa bagong window) sa pahina ng PostgreSQL sa Wikipedia.)

Pag-scale ng PostgreSQL sa milyun-milyong QPS

Para mabawasan ang mga limitasyong ito at mabawasan ang pressure sa pagsusulat, nag-migrate kami, at patuloy na mag-migrate, ng mga shardable (hal. mga workload na puwedeng pahalang na nahahati), write-heavy workload sa mga sharded system tulad ng Azure Cosmos DB, pag-optimize ng lohika ng application para mabawasan ang mga hindi kinakailangang pagsulat. Hindi na rin namin pinapayagan ang pagdaragdag ng mga bagong talahanayan sa kasalukuyang pag-deploy ng PostgreSQL. Awtomatikong itinatalaga sa mga sharded system ang mga bagong workload.

Kahit na umunlad ang ating imprastraktura, nanatiling hindi na-shard ang PostgreSQL, na may iisang pangunahing instance na nagsisilbi sa lahat ng mga pagsulat. Ang pangunahing dahilan ay magiging lubhang kumplikado at matagal ang pag-shard ng mga kasalukuyang workload ng application, na mangangailangan ng mga pagbabago sa daan-daang endpoint ng application at posibleng tumagal ng mga buwan o kahit mga taon. Dahil pangunahing nakatuon sa pagbasa ang aming mga workload, at nagpatupad kami ng malawakang mga pag-optimize, nagbibigay pa rin ng sapat na puwang ang kasalukuyang arkitektura para suportahan ang patuloy na paglago ng trapiko. Bagaman hindi namin isinasantabi ang pag-shard ng PostgreSQL sa hinaharap, hindi ito panandaliang priyoridad dahil sa sapat na landas na mayroon tayo para sa kasalukuyan at sa hinaharap na paglago.

Sa mga sumusunod na seksyon, tatalakayin namin nang mas malalim ang mga hamon na hinarap namin at ang malawakang mga pag-optimize na ipinatupad namin para matugunan ang mga ito at maiwasan ang mga outage sa hinaharap, itinutulak ang PostgreSQL hanggang sa mga limitasyon nito at pinalalawak ito para umabot sa milyun-milyong query bawat segundo (QPS).

Pagbawas ng load sa primary

Hamon: Sa iisang manunulat lang, hindi kayang i-scale ng single-primary setup ang mga pagsusulat. Ang matitinding spike sa pagsusulat ay maaaring mabilis na mag-overload sa primary at makaapekto sa mga serbisyo tulad ng ChatGPT at sa aming API.

Solusyon: Pinaliliit namin ang load sa primary hangga’t maaari—sa pagbabasa at pagsusulat—para matiyak na may sapat itong kapasidad para pangasiwaan ang mga biglaang pagtaas ng pagsusulat. Inililipat ang trapikong nabasa sa mga replika hangga't maaari. Gayunpaman, dapat manatili sa primary ang ilang read query dahil bahagi ang mga ito ng mga pagsulat ng transaksyon. Para sa mga iyon, nakatuon kami sa pagtiyak na mas mahusay ang mga ito at maiwasan ang mababagal na mga query. Para sa traffic sa pagsulat, inilipat namin ang mga shardable at mabibigat sa pagsulat na workload sa mga sharded system tulad ng Azure CosmosDB. Ang mga workload na mas mahirap i-shard pero patuloy na gumagawa ng mataas na write volume ay mas matagal ilipat, at kasalukuyang nagpapatuloy pa rin ang prosesong ito. Agresibo rin naming in-optimize ang aming mga application para mabawasan ang write load; halimbawa, inayos namin ang mga bug sa application na nagdulot ng mga redundant na pagsulat at nagpakilala ng tamad na pagsulat, kung naaangkop, para gawing smooth ang mga pagtaas ng traffic. Bukod pa rito, kapag nagba-backfill ng mga field ng talahanayan, mahigpit naming ipinapatupad ang mga limitasyon sa rate para maiwasan ang labis na presyon sa pagsusulat.

Pag-optimize ng query

Hamon: Natukoy namin ang ilang mamahaling query sa PostgreSQL. Noong nakaraan, ang biglaang pagtaas ng volume sa mga query na ito ay kumokonsumo ng malalaking halaga ng CPU, na nagpapabagal sa ChatGPT at mga kahilingan sa API.

Solusyon: Ang ilang mamahaling query, gaya ng mga nag-uugnay ng maraming talahanayan, ay maaaring makapagpababa nang malaki sa performance o kaya magpabagsak sa buong serbisyo. Kailangan naming patuloy na i-optimize ang mga query sa PostgreSQL para matiyak na mahusay ang mga ito at maiwasan ang mga karaniwang anti-pattern sa Online Transaction Processing (OLTP). Halimbawa, minsan naming natukoy ang napakamahal na query na nag-join ng 12 talahanayan, kung saan ang mga spike sa query na ito ang naging sanhi ng mga nakaraang high-severity SEV. Dapat nating iwasan ang mga kumplikadong multi-table na pagsali hangga't maaari. Kung kinakailangan ang mga pagsali, natutunan naming isaalang-alang ang paghahati-hati ng query at sa halip ilipat ang kumplikadong lohika ng pagsali sa application layer. Marami sa mga problematikong query na ito ay nabubuo ng mga Object-Relational Mapping framework (ORM), kaya mahalagang maingat na suriin ang SQL na kanilang nililikha at tiyaking umaakma ito sa inaasahan. Karaniwan ding makahanap ng mga pangmatagalang idle query sa PostgreSQL. Mahalaga ang pag-configure ng mga timeout tulad ng idle_in_transaction_session_timeout para maiwasan ang pagharang ng mga ito sa autovacuum.

Pagbawas ng panganib sa iisang punto ng pagkabigo

Hamon: Kung bumagsak ang read replica, puwede pa ring i-route ang trapiko sa iba pang mga replica. Gayunpaman, ang pag-asa sa iisang manunulat ay nangangahulugan ng pagkakaroon ng iisang punto ng pagkabigo—kung bumagsak ito, maaapektuhan ang buong serbisyo.

Solusyon: Karamihan sa mga pinakamahalagang kahilingan ay kinasasangkutan lang ng mga read query. Para mabawasan ang iisang punto ng pagkabigo sa primary, inilipat namin ang mga pagbasa na iyon mula sa writer papunta sa mga replica, na tinitiyak na makakapagpatuloy ang pagseserbisyo ng mga kahilingan na iyon kahit bumagsak ang primary. Bagaman mabigo pa rin ang mga operasyon sa pagsulat, nababawasan ang epekto; hindi na ito SEV0 dahil nananatiling available ang mga pagbasa.

Para mabawasan ang mga pangunahing pagkabigo, pinapatakbo namin ang pangunahing system sa High-Availability (HA) mode na may hot standby, isang tuloy-tuloy na naka-synchronize na replika na laging handang pumalit sa pagseserbisyo ng trapiko. Kung bumagsak ang pangunahing server o kailangang i-offline para sa pagpapanatili, puwede naming agad na i-promote ang standby para mabawasan ang downtime. Nagsagawa ang Azure PostgreSQL team ng makabuluhang trabaho para matiyak na mananatiling ligtas at maaasahan ang mga failover na ito kahit sa ilalim ng napakataas na load. Para matugunan ang mga pagkabigo ng read replica, nagde-deploy kami ng maraming replica sa bawat rehiyon na may sapat na reserbang kapasidad, na tinitiyak na ang hindi hahantong sa pangrehiyong outage ang pagkabigo ng isang replica.

Paghiwalay ng mga workload

Hamon: Madalas naming nararanasan ang mga sitwasyon kung saan ang ilang partikular na kahilingan ay kumokonsumo ng hindi proporsyonal na dami ng mga mapagkukunan sa mga PostgreSQL instance. Puwede itong magdulot ng pagbaba ng pagganap para sa iba pang mga gawain na tumatakbo sa parehong mga instance. Halimbawa, maaaring magpakilala ang paglulunsad ng bagong feature ng mga hindi episyenteng query na malakas kumonsumo ng PostgreSQL CPU, na nagpapabagal sa mga kahilingan para sa iba pang mahahalagang feature.

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.

Diagram ng postgreSQL proxy

Ang bawat read replica ay may sariling Kubernetes deployment na nagpapatakbo ng maraming PgBouncer pod. Nagpapatakbo kami ng maramihang Kubernetes deployment sa likod ng iisang Kubernetes Service, na nagba-balanse ng trapiko sa mga pod.

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(magbubukas sa bagong window), 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.

Diagram ng pag-cascade ng replication ng 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(magbubukas sa bagong window). 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(magbubukas sa bagong window) 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.

May-akda

Bohan Zhang

Mga Pagkilala

Espesyal na pasasalamat kina Jon Lee, Sicheng Liu, Chaomin Yu, at Chenglong Hao, na nag-ambag sa post na ito, at sa buong koponan na tumulong sa pag-scale ng PostgreSQL. Gusto din naming pasalamatan ang Azure PostgreSQL team para sa kanilang matibay na pakikipagtulungan.