scaling-evolution について
システム設計者向けに、最終形を先回りして構築せず、現在のボトルネックごとに拡張を計画するスキルです。負荷とリソースを診断し、拡張の時期や各段階で生じる制約を整理します。
主な機能
- 01ボトルネックごとの段階的な拡張計画
- 02コンピュート・ストレージ・ネットワーク負荷の区別
- 03垂直・水平スケーリングの比較
- 04各段階の移行条件の特定
- 05拡張で加わる障害モードの考慮
活用シーン
- 01トラフィック増加時の次の構成変更の選択
- 02最初に到達する容量上限の診断
- 03単一マシンから複数ノードへの移行計画
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ proyecto26/ system-design-skills --skill scaling-evolutionインストール後、Claude Code で/scaling-evolutionを入力して読み込まれたか確認します。
同梱ファイルreferences/scaling-ladder.md
詳細
スケーリングの進化
ボトルネックを一つずつ解消しながら設計を成長させます。1,000 人のユーザーにサービスを提供するシステムと、1,000 万人のユーザーにサービスを提供するシステムではアーキテクチャが異なりますが、両者の間を飛び越えるわけではありません。各段階で 現在の 上限を取り除き、次の上限を明らかにしていく道筋をたどります。これを誤ると、初日から過剰に構築してしまう(1,000 人のユーザーのためにマルチリージョンの複雑さを抱える)か、負荷が倍増したときに設計が正当な理由に基づく段階的な進化ではなく、暗記した最終形だったために身動きが取れなくなります(GUIDE #7)。
これを使う場面
負荷の増加が検討されている(「トラフィックが 10 倍になったら?」「数百万人規模にスケールしたら?」)、ユーザーからボトルネックや最初に壊れる箇所について質問された、あるいは単一マシンの設計が一台のマシンで処理しきれなくなった場合です。次の 2、3 段階の進め方を組み立てるために使い、ロードマップ全体を一度に示すことは避けてください。
使わない場面
数値がまだ必要としていない段階を先回りして構築しないでください(YAGNI)。シャーディング、マルチリージョン、メッセージキューは 後半 の段階で行うものです。2 台のマシンで収まるシステムにこれらを提案するのは、このスキルが防ごうとしている過剰な先読みです。現在の負荷を、レプリカを備えた垂直スケールのマシンで余裕を持って処理できるなら、そこで止めてください。それが制約を満たす最も安価な設計であり、最善の選択です。必要なのが 1 段階だけなのに、次の 5 段階まで挙げるのは先見の明ではなく、危険信号です。
まず確認すること
進め方は数値と制約によって完全に決まるため、先に以下を明確にしてください(多くは requirements-scoping と back-of-the-envelope から得られます)。
- 現在と目標の規模 — 現在の QPS/データ量と、達成すべき倍率(2 倍? 100 倍?)。倍率によって、今進める段階数が決まります。
- 読み取りと書き込みの比率 — 読み取り中心のシステムはレプリカとキャッシュでスケールします。書き込み中心のシステムはマスター/ストレージの上限に達し、より早い段階でシャーディングが必要になります。
- 現在の問題箇所 — 症状 はコンピュート(CPU 飽和)、ストレージ(DB/ディスク飽和)、それともネットワーク(帯域幅/接続数)のどれですか?追加する前に診断してください。
- 一貫性と許容可能な古さ — レプリカとマルチリージョンは、スケールと引き換えに鮮度を犠牲にします。読み取りデータを常に最新にする必要がある場合、進め方が制約されます(→
consistency-coordination)。 - 状態 — サーバーにひも付いているもの(セッション、ローカルファイル)はありますか?ステートフルな層は水平スケーリングを妨げます。
方法:ボトルネックの段階を一つずつ進む
各段階で、上限を一つ取り除きます。段階をすべて進めるのではなく、数値に基づいて次の段階を適用してください。具体的なトリガーとしきい値の例は、references/scaling-ladder.md に記載されています。
- 単一サーバー。 1台のマシンにWeb、アプリ、DB、キャッシュをまとめます。トラフィックが少なく、初期の検証段階に適しています。限界を迎えるのは 1台のマシンで負荷やデータを保持できなくなったときです。
- 階層を分割する。 データベース(その後、キャッシュも)を専用のホストに移し、Web層とデータ層を独立してスケールできるようにします。限界を迎えるのは 1台のWebサーバーまたは1台のDBが飽和したとき、あるいはいずれかが単一障害点になったときです。
- 垂直スケール+読み取り用レプリカ。 まず、ハードリミットやコストの転換点に達するまで、スケールアップ(より大きなマシンに変更すること。シンプルで、アプリの変更は不要)します。読み取りをプライマリから分散するために読み取り用レプリカを追加します(レプリケーションは
data-storageが担当します)。限界を迎えるのは 書き込みによってプライマリが飽和したとき、またはレプリカの遅延によってデータの鮮度が損なわれたときです。 - キャッシュを追加する。 読み取りが優勢になったことを示す数値が出たら、頻繁に読み取られるデータをDBの前段に置きます(→
caching)。読み取り負荷の高いシステムで最も効果の大きい手段です。限界を迎えるのは 書き込みがボトルネックになったとき、またはワーキングセットをキャッシュに収められなくなったときです。 - 静的コンテンツ/エッジ処理をCDNに移す。 画像、JS、CSS、動画を、ユーザーに近いエッジサーバーにオフロードします(→
content-delivery)。限界を迎えるのは ボトルネックが静的アセットではなく、動的リクエストになったときです。 - Web層をステートレスにして、ロードバランサーで負荷を分散する。 セッションや状態を共有ストアに移し、どのリクエストも任意のサーバーで処理できるようにします。ロードバランサーを前段に配置し、サーバー群を自動スケールします(→
load-balancing)。これにより、低コストでの水平スケールが可能になります。限界を迎えるのは ボトルネックになったデータ層が処理に追いつかなくなったときです。 - 非同期処理で疎結合にする。 時間のかかる処理やバーストする処理(アップロード、エンコード、ファンアウト)をキューの後段に移し、プロデューサーとコンシューマーを独立してスケールできるようにするとともに、急増する負荷を吸収します(→
messaging-streaming)。限界を迎えるのは 同期処理の経路やストレージでさえ上限に達したときです。 - 複数のデータセンター/リージョンを利用する。 ユーザーを最も近い正常なデータセンターに地理的にルーティングし、レイテンシーを低減して障害に備えます。リージョン間でレプリケーションを行います。限界を迎えるのは リージョン間のデータ同期、競合解決、または1つのデータセットが大きすぎて1つのリージョンに収まらないことが、最後の段階への移行を迫るときです。
- データ層をシャーディングする。 1台のプライマリで書き込みやデータを保持できなくなったときに、ノード間でデータを分割します(シャーディング/パーティショニングは
data-storageが担当し、一貫性のあるハッシュはconsistency-coordinationが担当します)。最も複雑な手段のため、最初ではなく最後に行います。
垂直スケール(スケールアップ:CPU/RAMを増やすこと)は、アプリの変更が不要で、初期には低コストで導入できますが、明確な上限があり、冗長性もありません。水平スケール(スケールアウト:マシンを増やすこと)は、可用性が高く、ほぼ無制限の余裕を確保できる、長期的に有効な解決策です。ただし、ステートレス化が必要で、調整のコストも増えます。転換点までは垂直にスケールし、その後は水平にスケールしてください。
何かを追加する前にボトルネックを診断する
診断なしに「サーバーを増やす」のは当てずっぽうです(GUIDE #3、#7)。まず負荷がかかっているリソースを分類し、そのリソースに対処します。
- コンピュートがボトルネック(CPU/スレッドが限界に達し、リクエストレートの上昇に伴ってレイテンシが増加する):アプリケーションサーバーを追加するか、自動スケーリングを行います。ハードウェアを購入する前に、O(n) のホットパスがないか確認します。
- ストレージがボトルネック(DB の CPU/IO が限界に達し、クエリが遅く、レプリカラグが拡大している):読み取りレプリカ、キャッシュの順に追加し、その後シャーディングします。ここでウェブサーバーを増やすと、状況はさらに悪化します。すでに飽和している DB への接続が増えるためです。
- ネットワークがボトルネック(帯域幅の飽和、接続数の上限、リージョン間 RTT):送信トラフィックには CDN を使い、圧縮とコネクションプーリングを行い、頻繁に通信するトラフィックを同じ DC 内に収めます。 よくある失敗は、ボトルネックがコンピュートにあるのにデータベースをシャーディングすることです。間違った層の問題を解決しようとして、新たな障害要因を追加してしまいます。症状を読み取り、リソースを特定してから、次の段階を選びます。
各段階は到達点ではなく、仮説として扱います。「書き込みが X を超えるまで/リージョンが失われるまで/ワーキングセットが RAM を超えるまで、この設計で対応できる」と考えます。限界点を声に出して説明することが、図を擁護するだけの姿勢と、論理的に考える姿勢を分けます。負荷が倍増する、レイテンシ目標が厳しくなる、DC が失われるなど、制約が変わったら、前提を見直して次の段階へ進みます。古い構成を合わなくなった問題に無理に当てはめるのではなく、落ち着いて対応します。
やるべきこと、避けるべきこと
段階的な拡張、診断の手順、そしてこの手法が誤解を招く場面を踏まえてまとめています。
やるべきこと
- 容量を増やす前にリソースを診断する — コンピュート、ストレージ、ネットワークのどれが問題なのかを特定してから、その層に対処します。症状を見ずに「サーバーを増やす」のは当てずっぽうです。
- 数値が正当化する次の段階だけを適用し、限界点を声に出して説明します(「書き込みが X を超えるまで/リージョンが失われるまで対応できる」)。
- 垂直方向に限界点まで拡張し、その後に水平方向へ拡張する — まず大きなマシンを使い(アプリケーションの変更は不要)、上限またはコストの限界に達してからスケールアウトします。
- ウェブ層をスケールアウトする前にステートレスにする — セッションを共有ストアに移し、自動スケーリングによってセッションが失われないようにします。
- 各段階で追加される障害要因を必ず組み合わせて考える(キャッシュスタンピード、レプリカ昇格、リージョンフェイルオーバー、ホットシャード)→
resilience-failure
避けるべきこと
- 段階をチェックリストとして扱わない — これは選択肢です。多くのシステムは段階 4~6 で問題なく稼働し続け、シャーディングを必要としません。
- 「印象的な」答えに飛びついて段階を飛ばさない — シャーディングやマルチリージョンに飛躍するのは、上限を超えたのではなく、図を暗記していることの表れです。
- ボトルネックではない層をスケールしない — 飽和した DB にウェブサーバーを増やしても、接続数が増えて下流の負荷が増幅するだけです。
- レプリカラグがあるレプリカに、書き込み直後の読み取りをルーティングしない — レプリカラグのある状態での読み取りはデータ損失のように見えます。そのような読み取りはプライマリに固定します(→
consistency-coordination)。 - 初日から最終形を構築しない — ユーザーが 1k 人しかいないのにマルチリージョンにすると、見返りがないままコストと複雑さが増します。今日の数値に合った段階を選びます。
重要な数値
次に進む段階を決めるのは数値です。表を繰り返すのではなく、back-of-the-envelope を参照してください。次の段階へ進むきっかけとなる上限の目安は、単一の RDBMS ノードが約 1k QPS、キーバリューノードが約 10k、キャッシュノードが約 100k~1M です。約 64 コアのマシン 1 台では、IO が発生する前の純粋なコンピュートで約 64k req/s です。推定値がこれらの上限を超えた時点で、それが次のボトルネックになります。ピーク値は通常、平均値の約 2 倍なので、ピークに合わせて容量を確保します。目安として、必要な段階は目標 QPS とデータセットサイズの桁数でおおよそ決まります。1k QPS なら 1 台のマシンで対応でき、約 10k ではレプリカとキャッシュが必要になり、100k 以上ではステートレスな水平スケーリング層が不可欠です。また、データセットが 1 台のマシンの RAM を超えるとシャーディングが必要になります。可用性の「9」を 1 つ増やすごとに、冗長性のコストは不釣り合いなほど大きく増加します(レプリカ → マルチ AZ → マルチリージョン)。目標は意欲ではなく要件に結び付けます(→ back-of-the-envelope、resilience-failure)。
図
現在のアーキテクチャと、1段先のバージョンを並べて可視化し(限界点と次の手を明確にするため)、プラグイン内の architecture-diagram スキルを使用します。今いる段とその次の段だけを図にしてください。はしご全体を描く必要はありません。
関連する構成要素
back-of-the-envelope— 上限値を把握するために依存します。数値が上限を超えると、次のボトルネックが明らかになります。data-storage— 所有する概念はこちらにあります:レプリケーションとシャーディング/パーティショニング。最も負荷の高い段です。caching— キャッシュの段としてこれと連携します。何をキャッシュするか、負荷時にどのように機能しなくなるかを扱います。load-balancing— ステートレスな水平スケーリング層につながり、その手前に位置します。content-delivery— 静的コンテンツや地理的に分散したコンテンツ向けの CDN/エッジの段としてこれと連携します。resilience-failure— すべての段と連携します。各段で障害モードが増えるため、適切に劣化できるようにします。consistency-coordination— 所有する概念はこちらにあります:レプリカ、マルチリージョン、シャードに伴う鮮度維持/調整のコストです。system-design— これによってオーケストレーションされます。このスキルは「設計をスケールさせる」ステップで実行されます。
参考資料
references/scaling-ladder.md— 具体的なトリガー閾値、コンピューティング/ストレージ/ネットワークの診断チェックリスト、垂直スケーリングと水平スケーリングの選択、マルチリージョン同期の注意点を含む、段ごとの完全なスケーリングのはしごです。次の手を決めるときや、最初に何が問題になるかを診断するときに読んでください。