Как OpenAI крутит PostgreSQL на 800M пользователей и миллионы QPS
Привет, %username%! Статья от OpenAI — это довольно любопытный пример того, как не городить зоопарк баз, а выжать максимум из одного PostgreSQL, понимая его сильные и слабые стороны.
Что по сути сделали OpenAI:
- Оставили один primary PostgreSQL без шардинга, но навесили почти 50 read‑реплик по регионам, чтобы разрулить гигантский read‑трафик и держать низкие задержки.
- Все, что можно шардинровать и что много пишет, уехало в Cosmos DB и другие шардированные системы — Postgres перестали использовать как универсальный молоток для любых нагрузок.
- Жёстко оптимизировали запросы: убирали монструозные joins (например, на 12 таблиц), ломали ORM‑магию, разбивали тяжелую логику по слоям, настраивали таймауты и следили за long‑running / idle‑транзакциями.
- Боролись с MVCC‑болью (bloat, dead tuples, write amplification) через снижение лишних записей, lazy writes, аккуратный backfill с rate‑limit'ами и перенос write‑heavy кейсов из PostgreSQL.
- Защитились от "шумных соседей": развели high‑priority и low‑priority трафик по разным инстансам, чтобы новая фича с кривыми запросами не ложила критичные пути.
- Везде, где можно, поставили PgBouncer (statement/transaction pooling), чтобы не умереть от connection storm при лимите в 5000 коннектов на инстанс.
- Снизили риск SEV‑0 от падения primary: HA с hot‑standby, быстрый failover, максимум критичных чтений — с реплик, чтобы при проблемах с записью сервис хотя бы читал.
- Поверх этого — rate limiting и load shedding на всех уровнях: приложение, пулер, прокси, конкретные query digests в ORM, плюс защита от retry storm'ов.
- Сильно ограничили эволюцию схемы: только лёгкие изменения, 5‑секундный timeout на DDL, без full table rewrite; новые таблицы — уже не в этом Postgres, а в шардированных системах.
В результате — миллионы QPS, p99 в низких десятках миллисекунд и около пяти девяток доступности, при этом за год только один SEV‑0 инцидент на Postgres, и тот во время дикого роста (ImageGen, +100M новых юзеров за неделю).
Что можно утащить к себе
- Не пытаться "передумать" базу: принять ограничения PostgreSQL (один writer, MVCC, bloat) и строить архитектуру вокруг этого, а не против этого.
- Относиться к read‑репликам как к основному инструменту масштабирования, а к primary — как к самому дорогому и охраняемому ресурсу.
- Ввести жёсткие правила для схемы и DDL: никакого "ALTER в прайм‑тайм прямо в прод", только безопасные паттерны миграций, троттлинг backfill’ов и чёткие SLO на операции с данными.
- Отдельно думать про защиту от кэш‑штормов: cache locking/lease, чтобы не просадить базу, когда Redis/мемкэш внезапно "забывает" ключи.
Вопросы к размышлению
1. Узнаешь ли ты свои продовые боли в описанных кейсах? Где у тебя узкое место — write‑нагрузка, длинные запросы, connection storm, кэш‑шторма? 2. Что ты сейчас используешь для изоляции "шумных соседей": отдельные БД, dedicated инстансы, resource groups, QoS на уровне запросов? 3. Есть ли у вас формальные правила для миграций схемы и кто их реально стопорит, когда хочется "просто добавить колонку"? 4. Насколько ты доверяешь read‑репликам — используешь ли их агрессивно, как OpenAI, или всё ещё боишься lag'а и читаешь почти всё с primary?
Делись в комментах кейсами и анти‑паттернами — особенно интересно, где вы сознательно не стали шардинговать Postgres, а выжали максимум из одной инстанции.
#PostgreSQL #SRE #DevOps #HighLoad #ChatGPT #Scalability #DatabaseReliability #DistributedSystems #Caching #Replication