PostgreSQL редко становится «героем» публичных историй, но именно он годами был одной из ключевых внутренних систем данных, на которых держатся ChatGPT и OpenAI API. По мере роста аудитории нагрузки на базы выросли взрывными темпами: OpenAI отмечает, что за последний год нагрузка на PostgreSQL увеличилась более чем в 10 раз и продолжает быстро расти.
В этом материале разберём подход OpenAI к масштабированию Postgres: как они справляются со всплесками чтения и записи, почему не спешат с шардированием, и какие инженерные практики можно применить в обычных продуктах — от SaaS до e-commerce и финтеха.
Почему PostgreSQL «начинает трещать» на гиперросте
Когда пользователей становится на порядок больше, проблемы часто выглядят одинаково:
- Сбой или промах кэша приводит к лавине запросов напрямую в базу.
- Дорогие запросы (CPU/IO) внезапно становятся «самыми частыми» и перегружают систему.
- Write storm после релиза — резкий рост записей, который упирается в возможности primary.
- Retry storm: таймауты вызывают ретраи, ретраи увеличивают нагрузку, нагрузка ухудшает таймауты.
OpenAI прямо описывает такой сценарий как типичный паттерн серьёзных инцидентов: рост задержек провоцирует ретраи, а ретраи усугубляют перегрузку.
Архитектура OpenAI: один primary и десятки read-реплик
Один из самых интересных тезисов: OpenAI долго держится за модель single-primary (один primary на запись) и масштабирует систему в ширину через чтение. В статье упоминается почти 50 read-реплик, распределённых по регионам, а базовая платформа — Azure Database for PostgreSQL Flexible Server.
Почему не шардировать сразу:
- Шардирование существующего продукта означает изменения во множестве сервисов и эндпоинтов — это месяцы или годы работ.
- Профиль нагрузки в значительной степени read-heavy, а чтения проще масштабировать репликами.
При этом OpenAI постепенно выносит новые write-heavy и хорошо шардируемые нагрузки в отдельные распределённые хранилища (например, Azure Cosmos DB). Более того, они отмечают подход: новые таблицы в текущий Postgres больше не добавляют, а новые нагрузки по умолчанию проектируют под шардированные системы.
Главная сложность больших записей: MVCC, bloat и вакуум
PostgreSQL использует MVCC, и на больших объёмах это проявляется особенно заметно:
- Обновление строки создаёт новую версию строки — растёт write amplification.
- Появляются «мёртвые» версии (dead tuples) — растёт read amplification.
- Ускоряется раздувание таблиц и индексов (bloat).
- Настройка autovacuum и обслуживание индексов становятся критичными для стабильной латентности.
Отсюда стратегический вывод: беречь primary — и по записи, и по чтению (по возможности).
9 практик масштабирования, которые OpenAI называет ключевыми
1) Снижать нагрузку на primary
- Максимально отправлять чтения на реплики.
- Находить и устранять лишние записи (дубли, баги, «болтливые» события).
- Использовать «ленивые» записи (lazy writes), чтобы сглаживать пики.
- Ограничивать backfill и любые операции, способные вызвать write storm.
2) Постоянно оптимизировать запросы и избегать «JOIN-монстров»
OpenAI приводит показательный пример: запрос с JOIN по 12 таблицам стал причиной серьёзной деградации под всплеском частоты. Вывод простой: в OLTP-сценариях такие запросы часто нужно упрощать, разбивать на этапы или переносить часть логики в приложение.
3) Делать деградацию «мягкой» при проблемах primary
- Критичные чтения направлять на реплики, чтобы сервис продолжал работать даже при проблемах primary.
- Использовать HA с hot standby, который можно быстро промотировать.
- Держать в регионе несколько реплик, чтобы падение одной не становилось региональной аварией.
4) Изолировать «шумных соседей»
- Разделять трафик на high-priority и low-priority.
- Маршрутизировать нагрузки так, чтобы одна «тяжёлая» фича не деградировала весь продукт.
5) Использовать connection pooling и дисциплину по таймаутам
На больших системах «шторм подключений» может положить базу быстрее, чем медленные запросы. OpenAI использует PgBouncer как proxy-слой и отмечает, что в их тестах среднее время установления соединения снизилось примерно с 50 ms до 5 ms. Также важны таймауты, чтобы пулер и база не захлёбывались idle-сессиями.
6) Защитить кэш от stampede
Если тысячи запросов одновременно промахиваются по одному ключу, они могут «пробить» базу. OpenAI внедрила механизм cache locking/leasing: при промахе по ключу только один запрос идёт в Postgres, остальные ждут обновления кэша.
7) Масштабировать реплики с учётом стоимости WAL
Чем больше реплик, тем больше primary должен стримить WAL всем сразу — это нагрузка на сеть и CPU. OpenAI тестирует каскадную репликацию (cascading replication), где часть реплик получает WAL не от primary, а от промежуточных реплик — так можно потенциально масштабироваться дальше.
8) Включить rate limiting и точечный load shedding
- Лимиты на уровне приложения, прокси и отдельных классов запросов.
- Адекватные задержки и политика ретраев, чтобы не создавать retry storm.
- Возможность быстро «приглушить» конкретные дорогие запросы.
9) Считать изменения схемы операцией повышенного риска
- Ограничивать schema changes и ставить короткие таймауты.
- Создавать/удалять индексы через concurrent-подходы, где это возможно.
- Backfill выполнять медленно и под жёсткими лимитами — даже если это занимает неделю.
Что это даёт на практике: стабильность, миллионы QPS и предсказуемая латентность
OpenAI пишет, что в результате система выходит на миллионы запросов в секунду в read-heavy режиме, почти 50 реплик с минимальным лагом, p99-латентность на стороне клиента на уровне «низких двузначных миллисекунд» и доступность порядка 99.999%.
Как применить подход OpenAI в обычном продукте
- Берегите primary: чтение — на реплики, запись — минимизировать и сглаживать.
- Сделайте кэш безопасным: защита от stampede (locking/leasing) — must-have.
- Поставьте пул соединений: PgBouncer и таймауты почти всегда окупаются.
- Следите за SQL: ORM может генерировать запросы, которые отлично выглядят в коде и ужасно — в проде.
- Изолируйте нагрузки: разные приоритеты и маршрутизация спасают при всплесках.
- Схема — это риск: особенно на больших таблицах, где ALTER может дорого стоить.
Связанный сервис Serverspace: VPS с PostgreSQL для быстрого старта и масштабирования
Если вы строите продукт в Узбекистане и хотите быстро развернуть PostgreSQL под прод, тестирование или миграцию, удобный вариант — поднять базу в облаке на VPS и масштабировать ресурсы по мере роста.
В Serverspace можно:
- Запустить VPS/VDS в Узбекистане (Ташкент) и получить локальную инфраструктуру с низкой задержкой для региональных пользователей.
- Развернуть VPS-сервер с PostgreSQL как готовое решение — подходит для быстрых пилотов и проектов, где важны скорость запуска и предсказуемость окружения.
- Гибко менять конфигурацию CPU/RAM/диска и платить за используемые ресурсы.
Ссылки:
Практический сценарий: поднимите PostgreSQL на VPS, настройте PgBouncer, включите кэш с защитой от stampede и подключите read-реплики по мере роста — вы получите «лестницу масштабирования», которая позволяет долго жить на Postgres без болезненного шардирования.