第12章 スケールの物語 — フォロワー1億人をTwitterはどう捌いたか
📖 この章のゴール:「規模(スケール)が変われば、設計も変わる」を、物語として感じてもらいます。第8章で素朴に作った「フォロー中の人の投稿を出す」という一見シンプルなお題に、エンジニアが何時間も議論できるほどの奥行きがあると知ること。それがゴールです。コードはほとんど出てきません。肩の力を抜いて、お話として読んでください。
📱 小さいうちは、なんでもうまくいく
第8章で、あなたは「ホームタイムライン」を作りました。
やり方は素直なものでした。follows の表から「自分がフォローしている人」を集めて、その人たちの投稿を tweets の表から新しい順にひろってくる。たった2ステップ。動いたときは、ちょっと感動しましたよね。
そして大事なことに——それは完璧に動きます。あなたと、友だち数人と、フォローもせいぜい数十件くらいの世界では、ホームを開いた瞬間にスッと投稿が並びます。なんの問題もありません。
でも、もしこのアプリが大ヒットしてしまったら?
利用者が10人から、1万人、100万人、1億人と増えていったら、あの素直な2ステップはどうなるのでしょう。
実は、ここからが本当のWeb開発の世界です。今回は極端な2つのケースを想像して、「規模が変わると何が壊れるのか」をのぞいてみましょう。
🤔 問題1「フォロイー100万人」 — 読むたびに重い
まず1人目。仮に コレクターさん と呼びましょう。
コレクターさんは、とにかくフォローするのが好き。気になったアカウントを片っぱしからフォローして、なんと 100万アカウント をフォローしています。フォロー数の世界記録に挑戦中、という感じです。
さて、コレクターさんがアプリでホームを開きました。
第8章のやり方を思い出してください。「フォロー中の人の最新投稿を集めて、新しい順に並べる」——でしたね。つまりアプリは、100万人ぶんの最新投稿をかき集めて、100万件の中から新しい順に並べ直す作業を、ホームを開くたびに毎回やらなければなりません。
これはたとえるなら、図書館で本を1冊さがすたびに、館内100万冊を全部チェックして、出版日順に並べ直してから目当ての棚を見る、ようなものです。1回ごとにヘトヘトです。コレクターさんがホームを更新するたびに、サーバーは汗だくになります。
このやり方には名前があります。「読むときに集める方式」——英語で fan-out on read(ファンアウト・オン・リード)、ふだんは pull(プル)型 と呼ばれます。「見たいと言われた、その瞬間に、引っぱって(pull)集めてくる」からです。
🟢 pull型の弱点:たくさんフォローしている人ほど、読むのが重くなる。
シンプルで分かりやすい方式ですが、フォロー数がふくらむと、読むたびのコストが青天井になっていくのです。
🤔 問題2「フォロワー1億人」 — 書くたびに重い
では、逆の極端を見てみましょう。2人目は スターさん。
スターさんは世界的な有名人。投稿すれば世界中が注目します。そのフォロワー数は、なんと 1億人。
「だったら、さっきと逆の作戦はどうだろう?」と考えた人は鋭いです。読むときに毎回集めるのが重いなら、先に配っておけばいい。つまり、スターさんが投稿した瞬間に、その投稿を フォロワー全員の「受信箱」にコピーして入れておく。そうすればフォロワーは、自分の受信箱を開くだけ。読むのは一瞬です。
……ところが。
スターさんが「おはよう」と1回つぶやくと、何が起きるか。その「おはよう」を、1億個の受信箱に1億回コピーすることになります。たった1ツイートのために、サーバーは1億回の書き込み作業。投稿ボタンを押した瞬間、サーバーが悲鳴をあげます。
これは、結婚式の招待状を 1億人ぶん手書きで宛名を書いて投函するようなもの。出す側がパンクします。こちらの方式にも名前があります。「書くときに配る方式」——fan-out on write(ファンアウト・オン・ライト)、ふだんは push(プッシュ)型 と呼ばれます。「書いた瞬間に、みんなへ押し出す(push)」からです。
🟢 push型の弱点:フォロワーが多い人ほど、1回の投稿が重くなる。
おもしろいですよね。pull型とpush型は、ちょうど 重さの場所が反対なのです。
- pull型:書くのは軽い/読むのが重い(コレクターさん問題)
- push型:読むのは軽い/書くのが重い(スターさん問題)
片方を立てれば、もう片方が立たない。Twitterの設計者たちは、まさにこのジレンマと向き合うことになりました。
🐳 Twitterの実話 — クジラの思い出
これは作り話ではありません。実際に、若き日のTwitterが通った道です。
2000年代後半、Twitterは爆発的に人気が出ました。すると、人が増えるたびにサーバーが追いつかなくなり、サイトはしょっちゅう落ちました。アクセスが集中すると、画面に1枚の絵が出る。何羽もの小鳥がクジラをロープで持ち上げようとしている、あのイラストです。
これは「Fail Whale(フェイル・ホエール/失敗クジラ)」と呼ばれ、当時のTwitterユーザーにはおなじみのキャラクターでした。「あ、また落ちた」と、みんな半ば名物あつかいで眺めていたのです。小鳥たち(=サーバー)が、重すぎるクジラ(=殺到するアクセス)を持ち上げきれずにいる——まさに当時のTwitterそのものでした。
そこでエンジニアたちは、発想を大きく転換します。
「ホームタイムラインを、毎回その場で組み立てるのをやめよう。 各ユーザーの『受信箱』を、あらかじめ作って置いておこう。」
ホームタイムラインを、前もって作っておくキャッシュ(=受信箱)としてとらえ直したのです。しかもそれを、取り出しの速い場所——メモリ上(Redis(レディス)のような、超高速の置き場)に並べておく。これなら、ユーザーがホームを開いたとき、その場で100万件を並べ直す必要はありません。できあがった受信箱を、ただ差し出すだけ。
第9章で学んだ「キャッシュ(同じものを何度も作り直さない工夫)」を、タイムラインそのものに当てはめた、と言ってもいいでしょう。でも、ここでさっきのジレンマが戻ってきます。受信箱方式(=push型)は、スターさん問題を抱えていましたよね。1億人に配るやつです。さあ、どうしましょう。
⚖️ 答えは「ハイブリッド」 — 良いとこ取りをする
結論から言うと、Twitterが選んだのは 「どちらか一方」ではなく「両方を使い分ける」 という答えでした。これを ハイブリッド方式 と呼びます。
考え方はとてもシンプルです。人を2種類に分けるのです。
-
🟢 ふつうの人 → push(受信箱に配る) あなたや私のような、フォロワーが数人〜数千人くらいの人。この人たちが投稿したら、フォロワーの受信箱にせっせと配ります。配る相手がそんなに多くないので、書き込みは大した負担になりません。そのかわり、フォロワーは読むのが速い。
-
🔧 スターさん(セレブ) → push をやめて pull(読むときに混ぜる) フォロワーが1億人もいるような超有名人。この人の投稿は、あえて受信箱に配りません。配ったら1億回コピーになってパンクするからです。そのかわり、フォロワーがホームを開いたその瞬間に、「フォロー中のセレブの最新投稿」を別途ちょこっと取りにいって、混ぜて見せます。
つまり、あなたがホームを開いたとき、画面はこう作られます。
- あらかじめ用意された 自分の受信箱(ふつうの人たちから配られた投稿)を出す
- そこに、自分がフォローしているセレブの最新投稿を、その場で取ってきて マージ(合流) する
- 全部を新しい順に並べて、はい完成
なぜこれがうまくいくのか。直感的に言うと——「重い作業を、軽い側に寄せている」からです。
セレブはフォロワーが1億人。でも、1人のユーザーがフォローしているセレブは、せいぜい数十人ですよね。だったら「1億人に配る(書き込み1億回)」より、「読むときに数十人ぶんだけ混ぜる」ほうが、はるかに軽い。逆にふつうの人は、配ってもフォロワーが少ないから push でも平気。
こうして、push型の「読みの速さ」と、pull型の「書きの軽さ」の、いいとこ取りができました。Fail Whaleが空に帰っていったのは、こうした地道な設計の積み重ねのおかげなのです。
💡 この物語の学び
ここまでの話から、エンジニアとして覚えておくと一生役立つことが、いくつもにじみ出ています。
-
🟢 ① 正解は1つではない。 「pull型が正しい/push型が正しい」のような唯一の答えはありません。規模によって、正解そのものが変わるのです。10人のときの最適解と、1億人のときの最適解は、まるで別物。これはプログラミングのいろんな場面で当てはまる、とても大事な感覚です。
-
🟢 ② 最初から1億人向けに作らない。 「いつか1億人が来るかもしれないから、最初から受信箱もハイブリッドも全部作りこもう」——これは実はやってはいけないことが多いのです。来るかどうか分からない規模のために複雑なしくみを先に作ると、コードが難しくなり、バグも増え、肝心の「今ほしい機能」が遅れます。これを 早すぎる最適化(そうしょうさいてきか) と呼び、ベテランほど警戒します。まず小さく素直に作り、本当に詰まったところを、詰まってから直す。 第8章であなたが素朴な2ステップで作ったのは、実は正しい第一歩だったのです。
-
🟢 ③ 単純なお題に、深い設計が潜む。 「フォロー中の人の投稿を出す」——文にすれば一行です。でもその裏に、pull/push、受信箱、マージ、セレブ問題……と、エンジニアが会議室で何時間も議論できる奥行きがありました。簡単そうに見えるものほど、奥が深い。これに気づけたら、もう立派なものの見方です。
-
🟢 ④ あなたの小さなTwitterも、巨大Twitterと地続き。 この教材であなたが作った、ささやかなTwitterもどき。それと、世界中が使う本物のTwitterは、まったく同じ問い——「フォロー中の人の投稿を、どう集めて、どう速く見せるか」——の延長線上にあります。規模がちがうだけで、考えていることは同じ。ここから先は、「もっと大きくしたらどうする?」を考える、設計の世界が広がっています。
📝 ことばメモ
- スケール(規模):利用者数やデータ量の大きさのこと。「スケールする」とは、規模が大きくなっても壊れずに動かせること。規模が変わると最適な設計も変わる、というのが本章の主題でした。
- fan-out on write(push型):書くときに配る方式。投稿した瞬間に、フォロワーの受信箱へコピーを押し出す。読むのは速いが、フォロワーが多いと書きが重い。
- fan-out on read(pull型):読むときに集める方式。ホームを開いた瞬間に、フォロー中の人の投稿を引っぱって集める。書くのは軽いが、フォロー数が多いと読みが重い。
- 受信箱(タイムラインのキャッシュ):各ユーザーぶんに、あらかじめ作って置いておくホームタイムライン。第9章の「キャッシュ」をタイムラインに応用したもの。Redisのような高速な置き場に持つことが多い。
- セレブ問題:フォロワーが極端に多い人に push でコピーを配ると、1回の投稿が天文学的な書き込み回数になってしまう問題。ハイブリッド方式で、セレブだけ pull に切りかえて回避する。
- 早すぎる最適化:まだ必要かどうか分からない速度・規模対策を、先回りして作りこんでしまうこと。コードを無駄に複雑にする原因になりやすく、「まず素直に作る」が基本。
🎉 おわりに(次の一歩)
おめでとうございます。あなたは、この教材を 最後まで やり切りました。
ふり返ってみましょう。あなたが歩いてきた道のりは、こうでした。
ログイン(認証) → 自分のデータを守る(データ分離・RLS) → 出し入れの窓口(API) → みんなに見せる(公開タイムライン) → 人とつながる(フォロー) → フォロー中の人を見せる(ホームタイムライン) → そして今日、規模の物語(スケール)。
Web開発の骨組みを、ぐるりと一周したのです。これはもう、立派な土台です。
では、次の一歩は何でしょう。それは——自分のアイデアで、何か作ってみることです。
Twitterのクローンでなくてもいい。日記アプリでも、本の感想を記録するサービスでも、友だちと使うちょっとした掲示板でもいい。「ログインして、自分のデータを安全に保存して、人に見せる」——この型は、世の中のほとんどのアプリに当てはまります。あなたはもう、その型を知っています。
手が止まったら、付録A〜Fを頼ってください。Supabaseのセットアップ、Google認証の設定、ふつうのDBの守り方、ORM、用語辞典、トークンのしくみ——つまずきやすいところに、それぞれ手すりを用意してあります。そして困ったら、第11章で学んだように、AIに頼んで、書かせて、自分の目で読む。その力が、あなたにはもうあります。
さあ、ここからは、あなたの番です。よい開発の旅を。