きっかけ
X でこんな趣旨のポストを見かけました。
ChatGPTは8億人のユーザーを単一のPostgreSQLプライマリで処理している。読み取りは約50台のレプリカに分散し、書き込みの重い処理は Cosmos DB へ逃がし、PgBouncer とキャッシュロックとレート制限でプライマリを保護。結果として 99.999% の可用性を達成した。
元ポスト: https://x.com/kuwa_tw/status/2115789385170104487
(リンク先は Hashnode のまとめ記事: https://mahmad.hashnode.dev/chatgpt-800-million-users-one-postgres-primary )
「単一プライマリで8億人」はさすがに盛ってないか、と思って公式ブログを辿ったメモです。
公式ブログの確認
この話の出どころは、OpenAI のインフラエンジニア Bohan Zhang による公式ブログ 「Scaling PostgreSQL to power 800 million ChatGPT users」(2026年1月公開)でした。VentureBeat など複数メディアも報じていて、主要な数字は二次情報とも一致しています。
- 構成: Azure PostgreSQL Flexible Server の 単一プライマリ(書き込み)+ 約50台のリードレプリカ(読み取り)、シャーディングなし
- 規模: 約8億ユーザー、数百万 QPS、p99 は低い二桁ミリ秒、可用性 99.999%
- PostgreSQL の負荷は1年で10倍以上に増加
- この1年で大きな障害は1回だけ(画像生成ブームで書き込みが平常の10倍超に跳ねたとき)
つまりポストの要約は、盛っているわけではなく公式ブログどおりでした。
なぜシャーディングしないのか
まず言葉の整理です。シャーディング とは、DB を複数台に分けてデータを分散させること。たとえば「ユーザーID が偶数の人は DB1、奇数の人は DB2」のように分けて、1台あたりの負荷を下げます。
規模が大きくなればシャーディングが定石に見えますが、OpenAI はあえて選びませんでした。理由は現実的なコストの問題です。
今の ChatGPT のコードは、数百あるエンドポイント(API)が「1つの DB を見れば、必要なデータは全部そこにある」前提で書かれています。たとえば「ユーザー情報と、その人の会話履歴を JOIN して取る」ような処理が当たり前にできます。
これをシャーディングすると、その前提が崩れます。
- データが別々の DB に散るので、DB をまたいだ JOIN ができなくなる
- 「このデータはどちらの DB に聞けばいいか」という振り分けが全処理に必要になる
- 複数の DB にまたがる更新で、データの整合性を保つのが難しくなる
つまり数百の API を「データの場所を意識する作り」に書き直すことになり、数ヶ月規模の大工事と、バグが入り込むリスクを引き受けることになります。
代わりに取った方針は、全部を分割する大手術ではなく、問題を切り分けて、痛いところだけ外に出す ことでした。
- 書き込みが重くて分割しやすいワークロードは Azure Cosmos DB へ移行
- この PostgreSQL には 新規テーブルを追加しない ルールにした(新しいものは最初からシャーディング前提の基盤へ)
Azure Cosmos DB とは
Microsoft のクラウド DB です。PostgreSQL のような表形式(リレーショナル)ではなくドキュメント型の NoSQL で、最初から複数台へデータを分散する(シャーディングする)設計のため、書き込みを水平にスケールさせやすいのが特徴です。
OpenAI は、PostgreSQL が苦手な「重い書き込み」をこの Cosmos DB に任せ、読み取り中心の本体は PostgreSQL に残す、という適材適所の役割分担をしています。
プライマリを守るための施策
単一プライマリ構成が成り立つのは、プライマリに余計な負荷を一切かけない運用があるからでした。
- 読み取りのオフロード: 読み取りはレプリカへ寄せ、その手前にキャッシュ層を置いて大半の読み取りを DB に到達させない
- PgBouncer で接続プーリング: 平均接続時間が 50ms → 5ms に短縮
- キャッシュロックでスタンピード防止: キャッシュの有効期限切れで一斉に DB へアクセスが殺到する(thundering herd)現象を、ロックで1リクエストだけに代表させる
- 多層のレート制限とワークロード分離: アプリ → プーラー → プロキシ → クエリの各層で制限し、優先度の低いバッチやバックフィルはレートを絞る
- 重いクエリの排除: 重い JOIN などを避ける運用でプライマリを保護
読み書き分離という意味では CQRS の親戚
ここまでの話は、「書き込みと読み取りを分けて、それぞれに最適化する」という点で、CQRS(Command Query Responsibility Segregation)という設計パターンと発想が共通しています。
ただし厳密な CQRS は、書き込み側のモデルと読み取り側のモデル自体を分離し、読み取り用に整形したデータをイベント経由で別に用意する設計です。今回の PostgreSQL 構成は、同じデータ・同じスキーマのコピーをレプリカに配って読ませているので、モデルの分離まではしていません。古典的なプライマリ/レプリカ構成です。
一方で、書き込みの重い処理だけを Cosmos DB に逃がす部分は、用途ごとに保存先を使い分ける CQRS 的な発想に近いものです。
弱点は書き込み(MVCC)
PostgreSQL の MVCC は更新のたびに行全体をコピーするため、書き込み増幅と dead tuple による肥大化が起きやすい。読み取り中心のワークロードでは強くても、書き込みの急増には弱い、というのが公式ブログの正直な結論でした。唯一の大きな障害が書き込み急増だったのも、それを裏付けています。
なお公式ブログの最後では、今後の成長次第ではシャーディングされた PostgreSQL や分散システムの検討も続ける、とされています。「単一プライマリで永遠にいける」という話ではありません。
ISUCON目線で刺さったこと
ちょうど ISUCON の前日に読んだので、チューニングの観点でメモしておきます。
- スケールさせる前に「プライマリ(DB)を守る」発想が先にあること
- 接続プーリング、キャッシュ、重いクエリの排除、読み取り分離 — 手札はどれも地味で基本的なもの
- 大手術(シャーディング)より、ボトルネックの切り分けとオフロードの積み重ね
派手な分散アーキテクチャではなく、「枯れた構成 × 規律ある運用」で限界まで引っ張る、という話でした。計測して、ボトルネックを特定して、そこだけ直す。当たり前のことを8億人規模でもやっている、というのが一番の収穫です。
参考
- 元ポスト: https://x.com/kuwa_tw/status/2115789385170104487
- まとめ記事(Hashnode): https://mahmad.hashnode.dev/chatgpt-800-million-users-one-postgres-primary
- 報道(VentureBeat): https://venturebeat.com/data/how-openai-is-scaling-the-postgresql-database-to-800-million-users
- 公式ブログ: OpenAI「Scaling PostgreSQL to power 800 million ChatGPT users」(Bohan Zhang) https://openai.com/index/scaling-postgresql/
- Azure Cosmos DB 公式ドキュメント(Microsoft Learn) https://learn.microsoft.com/ja-jp/azure/cosmos-db/overview
※ 本記事は公式ブログと報道をもとにした二次まとめです。正確な仕様や数字は公式ブログを確認してください。
最後に
いつの時代も基礎的な手法が1番強い…!!