PostgreSQL کو 800 ملین ChatGPT صارفین کو طاقت دینے کے لیے بڑھانا
منجانب بوہان ژانگ، تکنیکی عملے کے رکن
کئی سالوں سے، PostgreSQL ان انتہائی اہم، پس پردہ ڈیٹا سسٹمز میں سے ایک رہا ہے جو ChatGPT اور OpenAI کے API جیسی بنیادی مصنوعات کو تقویت دیتا ہے. جیسے جیسے ہمارے صارفین کی تعداد تیزی سے بڑھ رہی ہے، ہمارے ڈیٹابیسز پر مطالبات بھی تیزی سے بڑھ رہے ہیں. گزشتہ سال کے دوران، ہمارے PostgreSQL لوڈ میں 10 گنا سے زیادہ اضافہ ہوا ہے اور یہ تیزی سے بڑھتا جا رہا ہے.
اس نمو کو برقرار رکھنے کے لیے ہماری اپنے پروڈکشن انفراسٹرکچر کو آگے بڑھانے کی کوششوں نے ایک نئی بصیرت ظاہر کی: PostgreSQL کو اس طرح اسکیل کیا جا سکتا ہے کہ وہ قابلِ اعتماد طور پر بہت بڑے ریڈ-ہیوی ورک لوڈز کو سپورٹ کرے، جتنا کہ بہت سے لوگ پہلے ممکن سمجھتے تھے. یہ نظام (ابتدائی طور پر یونیورسٹی آف کیلیفورنیا، برکلے کے سائنس دانوں کی ایک ٹیم کی جانب سے تخلیق کیا گیا تھا) نے ہمیں ایک واحد بنیادی Azure PostgreSQL فلیکسیبل سرور انسٹینس(نئی ونڈو میں کھلتا ہے) اور دنیا بھر میں مختلف خطوں میں پھیلی ہوئی تقریباً 50 ریڈ ریپلیکا کے ساتھ بڑے پیمانے پر عالمی ٹریفک کی حمایت کرنے کے قابل بنایا ہے. یہ کہانی ہے کہ ہم نے OpenAI میں PostgreSQL کو کیسے اسکیل کیا تاکہ شاندار احسن کاریوں اور مضبوط انجینئرنگ کی مدد سے 800 ملین صارفین کے لیے فی سیکنڈ لاکھوں کوئریز کی حمایت کی جا سکے؛ ہم راستے میں سیکھے گئے اہم نکات بھی بیان کریں گے.
ChatGPT کے لانچ کے بعد، ٹریفک بے مثال رفتار سے بڑھا. اسے سپورٹ کرنے کے لیے، ہم نے ایپلیکیشن اور PostgreSQL ڈیٹابیس لیئرز پر تیزی سے وسیع آپٹیمائزیشنز نافذ کیں، انسٹینس سائز بڑھا کر اسکیل اپ کیا اور مزید ریڈ ریپلیکا شامل کر کے اسکیل آؤٹ کیا. یہ آرکیٹیکچر طویل عرصے سے ہمارے لیے مؤثر ثابت ہوا ہے. مسلسل بہتریوں کے ساتھ، یہ مستقبل کی ترقی کے لیے کافی مواقع فراہم کرتا رہتا ہے.
یہ سن کر حیرت ہو سکتی ہے کہ ایک سنگل-پرائمری فن تعمیر OpenAI کے پیمانے کے تقاضوں کو پورا کر سکتا ہے؛ تاہم، عملی طور پر اسے کارآمد بنانا آسان نہیں ہے. ہم نے Postgres کے اوورلوڈ کی وجہ سے کئی SEVs دیکھے ہیں اور وہ اکثر ایک ہی پیٹرن کو فالو کرتے ہیں: اپ اسٹریم مسئلہ ڈیٹابیس لوڈ میں اچانک اضافہ کر دیتا ہے، جیسا کہ کیشنگ-لیئر کی ناکامی سے وسیع پیمانے پر کیشے مس ہونا، مہنگے ملٹی-وے جوائنز کی اونچی لہر جو CPU کو سیراب کر دے، یا نئی فیچر کے اجراء سے رائٹ کا طوفان آنا. جب وسائل کے استعمال میں اضافہ ہوتا ہے، تو کوئری کی تاخیر بڑھ جاتی ہے اور ریکوئسٹس ٹائم آؤٹ ہونے لگتی ہیں. ری ٹرائیز پھر لوڈ کو مزید بڑھا دیتے ہیں، جس سے ایک شیطانی چکر شروع ہو جاتا ہے جو پوری ChatGPT اور API خدمات کی کارکردگی کو متاثر کرنے کی صلاحیت رکھتا ہے.
اگرچہ PostgreSQL ہمارے ریڈ-ہیوی ورک لوڈز کے لیے اچھی طرح اسکیل کرتا ہے، لیکن ہمیں زیادہ رائٹ ٹریفک کے ادوار میں چیلنجز کا سامنا کرنا پڑتا ہے. یہ بڑی حد تک PostgreSQL کے ملٹی ورژن کنکرنسی کنٹرول (multiversion concurrency control, MVCC) کے نفاذ کی وجہ سے ہے، جو اسے رائٹ-ہیوی ورک لوڈز کے لیے کم مؤثر بناتا ہے. مثال کے طور پر، جب کوئی کوئری کسی ٹپل یا حتیٰ کہ کسی ایک فیلڈ کو اپ ڈیٹ کرتی ہے، تو ایک نئی ورژن بنانے کے لیے پوری صف کو کاپی کیا جاتا ہے. زیادہ رائٹ کے بوجھ کے تحت، اس کے نتیجے میں رائٹ کی نمایاں تحریری اضافہ ہوتا ہے. یہ ریڈ ایمپلیفیکیشن میں بھی اضافہ کرتا ہے، کیونکہ کوئریز کو تازہ ترین ورژن حاصل کرنے کے لیے متعدد ٹوپل ورژنز (ڈیڈ ٹوبلز) کے ذریعے اسکین کرنا پڑتا ہے. MVCC اضافی چیلنجز متعارف کراتا ہے، جیسے ٹیبل اور انڈیکس کا پھول جانا، انڈیکس کی دیکھ بھال کے اضافی اوورہیڈ میں اضافہ اور پیچیدہ آٹوویکیوم ٹیوننگ. (آپ ان مسائل پر تفصیلی جائزہ اس بلاگ میں دیکھ سکتے ہیں جو میں نے کارنیگی میلن یونیورسٹی میں پروفیسر اینڈی پاولو کے ساتھ لکھا تھا، جس کا عنوان ہے PostgreSQL کا وہ حصہ جس سے ہم سخت نفرت کرتے ہیں(نئی ونڈو میں کھلتا ہے)، جس کا حوالہ دیا گیا(نئی ونڈو میں کھلتا ہے) PostgreSQL کے ویکیپیڈیا صفحے میں موجود ہے.)
ان حدود کو کم کرنے اور رائٹ کے دباؤ کو کم کرنے کے لیے، ہم نے قابل تقسیم حصوں کو منتقل کیا ہے اور منتقل کرنا جاری رکھتے ہیں، (یعنی ایسے کام کے بوجھ جو افقی طور پر تقسیم کیے جا سکتے ہیں، جیسے Azure Cosmos DB جیسے شارڈڈ سسٹمز کے لیے زیادہ رائٹ والے کام کے بوجھ، غیر ضروری لکھائیوں کو کم سے کم کرنے کے لیے ایپلیکیشن لاجک کو بہتر بنانا. ہم اب موجودہ PostgreSQL تعیناتی میں نئے جدول شامل کرنے کی بھی اجازت نہیں دیتے. نئے کام کے بوجھ پہلے سے طے شدہ طور پر شارڈڈ سسٹمز پر ہوتے ہیں.
اگرچہ ہمارا انفراسٹرکچر ترقی کر چکا ہے، PostgreSQL غیر شارڈڈ ہی رہا ہے اور ایک ہی پرائمری انسٹینس تمام تحریریں سنبھال رہا ہے. بنیادی وجہ یہ ہے کہ موجودہ ایپلیکیشن ورک لوڈز کو شارڈ کرنا انتہائی پیچیدہ اور وقت طلب ہوگا، جس کے لیے سینکڑوں ایپلیکیشن اینڈپوائنٹس میں تبدیلیاں درکار ہوں گی اور ممکنہ طور پر اس میں مہینے یا حتیٰ کہ سال لگ سکتے ہیں. چونکہ ہمارے ورک لوڈز بنیادی طور پر ریڈ پر مبنی ہیں اور ہم نے وسیع پیمانے پر اصلاحات نافذ کی ہیں، اس لیے موجودہ آرکیٹیکچر اب بھی مسلسل ٹریفک میں اضافے کی حمایت کے لیے کافی گنجائش فراہم کرتا ہے. اگرچہ ہم مستقبل میں PostgreSQL کی شارڈنگ کو خارج از امکان نہیں سمجھتے، لیکن موجودہ اور آئندہ ترقی کے لیے ہمارے پاس جو کافی گنجائش ہے اس کے پیش نظر یہ قریب المدت ترجیح نہیں ہے.
اگلے حصوں میں، ہم ان چیلنجز کا جائزہ لیں گے جن کا ہمیں سامنا کرنا پڑا اور ان کے حل کے لیے جو وسیع اصلاحات ہم نے کیں، تاکہ مستقبل میں رکاوٹوں کو روکا جا سکے، PostgreSQL کو اس کی حدوں تک لے جاتے ہوئے اور اسے فی سیکنڈ لاکھوں کوئریز (QPS) تک بڑھاتے ہوئے.
چیلنج: صرف ایک رائٹر کے ساتھ، سنگل-پرائمری سیٹ اپ رائٹ کی صلاحیت کو بڑھا نہیں سکتا. بھاری رائٹ کے اچانک اضافے تیزی سے پرائمری کو اوورلوڈ کر سکتے ہیں اور ChatGPT اور ہماری API جیسی خدمات کو متاثر کر سکتے ہیں.
حل: ہم پرائمری پر لوڈ کو جتنا ممکن ہو کم کرتے ہیں—ریڈ اور رائٹ دونوں کو—تاکہ یہ رائٹ کے اچانک بڑھنے والے بوجھ کو سنبھالنے کے لیے کافی گنجائش رکھے. ریڈ کی ٹریفک کو جہاں ممکن ہو ریپلیکاز پر منتقل کیا جاتا ہے. تاہم، کچھ ریڈ کوئریز کو پرائمری پر ہی رہنا چاہیے کیونکہ وہ رائٹ کی ٹرانزیکشنز کا حصہ ہوتی ہیں. ان کے لیے، ہم اس بات کو یقینی بنانے پر توجہ مرکوز کرتے ہیں کہ وہ مؤثر ہوں اور سست کوئریز سے بچیں. رائٹ کی ٹریفک کے لیے، ہم نے شارڈ کیے جانے کے قابل، رائٹ کے بھاری ورک لوڈز کو Azure CosmosDB جیسے شارڈڈ سسٹمز میں منتقل کر دیا ہے. وہ ورک لوڈز جنہیں شارڈ کرنا مشکل ہوتا ہے لیکن پھر بھی زیادہ رائٹ کا حجم پیدا کرتے ہیں، ان کی منتقلی میں زیادہ وقت لگتا ہے اور یہ عمل ابھی بھی جاری ہے. ہم نے اپنی ایپلیکیشنز کو رائٹ لوڈز کم کرنے کے لیے جارحانہ طور پر بہتر بنایا؛ مثال کے طور پر، ہم نے ایپلیکیشن کی وہ خرابیاں درست کیں جن کی وجہ سے غیر ضروری لکھائی ہو رہی تھی اور جہاں مناسب ہو وہاں سست لکھائی متعارف کرائی، تاکہ ٹریفک کے دباؤ کو ہموار کیا جا سکے. مزید برآں، جب جدول کے فیلڈز کو بیک فل کیا جاتا ہے، تو ہم سخت شرح کی حدیں نافذ کرتے ہیں تاکہ ضرورت سے زیادہ رائٹ کے دباؤ کو روکا جا سکے.
چیلنج: ہم نے PostgreSQL میں کئی مہنگی کوئریز کی نشاندہی کی. ماضی میں، ان کوئریز کے حجم میں اچانک اضافہ CPU کی بڑی مقدار استعمال کر لیتا تھا، جس سے ChatGPT اور API ریکوئسٹس دونوں سست ہو جاتی تھیں.
حل: چند مہنگی کوئریز، جیسے کہ وہ جو کئی ٹیبلز کو ایک ساتھ جوڑتی ہیں، کارکردگی کو نمایاں طور پر کم کر سکتی ہیں یا حتیٰ کہ پوری سروس کو بھی بند کر سکتی ہیں. ہمیں PostgreSQL کوئریز کو مسلسل بہتر بنانا چاہیے تاکہ وہ مؤثر رہیں اور عام آن لائن ٹرانزیکشن پروسیسنگ (OLTP) اینٹی-پیٹرنز سے بچا جا سکے. مثال کے طور پر، ہم نے ایک بار ایک انتہائی مہنگی کوئری کی نشاندہی کی تھی جو 12 ٹیبلز کو جوڑتی تھی، جہاں اس کوئری میں آنے والے اسپائکس ماضی کے ہائی سیویریٹی SEVs کے ذمہ دار تھے. جب بھی ممکن ہو، ہمیں پیچیدہ ملٹی-ٹیبل جوائنز سے گریز کرنا چاہیے. اگر جوائنز ضروری ہوں، تو ہم نے یہ سیکھا کہ کوئری کو حصوں میں تقسیم کرنے پر غور کریں اور پیچیدہ جوائن لوجک کو اس کے بجائے ایپلیکیشن لئیر میں منتقل کریں. ان میں سے بہت سے مسئلہ پیدا کرنے والے سوالات اوبجیکٹ-ریلیشنل میپنگ فریم ورکس (ORMs) کے ذریعے تیار کیے جاتے ہیں، اس لیے ضروری ہے کہ وہ جو SQL تیار کرتے ہیں اس کا بغور جائزہ لیں اور یہ یقینی بنائیں کہ وہ توقعات کے مطابق کام کرتا ہے. PostgreSQL میں طویل عرصے تک چلنے والی غیر فعال کوئریز کا ملنا بھی عام بات ہے. idle_in_transaction_session_timeout جیسے ٹائم آؤٹس کو تشکیل دینا ضروری ہے تاکہ وہ آٹوویکیوم کو بلاک نہ کریں.
چیلنج: اگر کوئی ریڈ ریپلیکا ناکام ہو جائے، تو ٹریفک پھر بھی دیگر ریپلیکاز کی طرف منتقل کی جا سکتی ہے. تاہم، ایک ہی مصنف پر انحصار کرنے کا مطلب یہ ہے کہ ناکامی کا ایک ہی نقطہ ہو—اگر وہ ناکام ہو جائے، تو پوری سروس متاثر ہوتی ہے.
حل: زیادہ تر اشد ضروری ریکوئسٹس صرف ریڈ کی کوئریز پر مشتمل ہوتی ہیں. بنیادی میں سنگل پوائنٹ آف فیلیر کو کم کرنے کے لیے، ہم نے وہ ریڈز رائٹر سے ریپلیکا پر منتقل کر دیئے، تاکہ یہ یقینی بنایا جا سکے کہ اگر بنیادی ڈاؤن ہو جائے تو بھی وہ ریکوئسٹس جاری رہ سکیں. اگرچہ رائٹ کی کارروائیاں اب بھی ناکام ہوں گی، لیکن اثر کم ہو گیا ہے؛ یہ اب SEV0 نہیں رہا کیونکہ ریڈ کی کارروائیاں دستیاب ہیں.
بنیادی ناکامیوں کو کم کرنے کے لیے، ہم بنیادی کو اعلٰی-دستیابی (High-Availability, HA) موڈ میں ایک ہاٹ اسٹینڈبائی کے ساتھ چلاتے ہیں، جو ایک مسلسل ہم آہنگ شدہ نقل ہے اور ہمیشہ ٹریفک کی خدمت سنبھالنے کے لیے تیار رہتی ہے. اگر پرائمری ڈاؤن ہو جائے یا دیکھ بھال کے لیے اسے آف لائن کرنا پڑے، تو ہم تعطل کو کم سے کم کرنے کے لیے اسٹینڈ بائی کو فوری طور پر فعال کر سکتے ہیں. Azure PostgreSQL ٹیم نے اس بات کو یقینی بنانے کے لیے نمایاں کام کیا ہے کہ یہ فیل اوورز بہت زیادہ لوڈ کے تحت بھی محفوظ اور قابلِ اعتماد رہیں. ریڈ ریپلیکا کی ناکامیوں کو سنبھالنے کے لیے، ہم ہر علاقے میں کافی صلاحیت کے ہیڈ روم کے ساتھ متعدد ریپلیکاز تعینات کرتے ہیں، تاکہ ایک واحد ریپلیکا کی ناکامی علاقائی بندش کا سبب نہ بنے.
چیلنج: ہم اکثر ایسی صورتحال کا سامنا کرتے ہیں جہاں کچھ ریکوئسٹس PostgreSQL انسٹینسز پر وسائل کی غیر متناسب مقدار استعمال کرتی ہیں. اس سے انہی انسٹینسز پر چلنے والے دیگر ورک لوڈز کی کارکردگی میں کمی آ سکتی ہے. مثال کے طور پر، کسی نئے فیچر کا آغاز غیر مؤثر کوئریز متعارف کروا سکتا ہے جو 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.
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.
ہر ریڈ ریپلیکا کی اپنی Kubernetes تعین کاری ہوتی ہے جو متعدد PgBouncer پوڈز چلا رہی ہوتی ہیں. ہم ایک ہی Kubernetes سروس کے پیچھے متعدد Kubernetes تعین کاریاں چلاتے ہیں، جو پوڈز کے درمیان ٹریفک کو متوازن کرتا ہے.
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.
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.
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.
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.
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.
مصنف
اظہار تشکر
اس پوسٹ میں تعاون کرنے والے جون لی، سیچینگ لیو، چاؤمین یو اور چینگلونگ ہاؤ کا خصوصی شکریہ اور PostgreSQL کو اسکیل کرنے میں مدد کرنے والی پوری ٹیم کا بھی شکریہ. ہم ان کی مضبوط شراکت داری کے لیے Azure PostgreSQL ٹیم کا بھی شکریہ ادا کرنا چاہیں گے.


