system-design について
システムの新規設計、説明、再設計を段階的に進めるスキルです。要件から詳細検討まで一貫した構成を用い、根拠に基づく説明と不明点の明示を促します。
主な機能
- 01段階的なシステム設計フレームワーク
- 02新規設計・説明・再設計への対応
- 03根拠と不明点の明示
- 04詳細検討でのトレードオフ分析
- 05視覚的な提示と反復修正
活用シーン
- 01要件からシステム設計案を作成
- 02コードと文書に基づいてシステムを説明
- 03設計上の選択肢を比較
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ yahyabedirhan/ skills --skill system-designインストール後、Claude Code で/system-designを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/api-design.mdcaching.mdcap-theorem.mdcommon-patterns.mdconsistent-hashing.mddata-modeling.mddatabase-indexing.mdnetworking-essentials.mdnumbers-to-know.mdsharding.md詳細
システム設計
新規設計、説明、再設計のいずれの場合も、すべてのセッションで提供フレームワークに従います。これにより、ユーザーはいつも同じ場所で同じ項目を見つけられます。セッションの目的はユーザーが決め、回答の構成はフレームワークが定めます。ユーザーからどこかに書き出すよう求められない限り、設計は会話内にとどめます。書き出す場合は、各段階をセクションとして使います。
1 つのサービスのコードベース内で、モジュール、クラス、フォルダーのレベルで設計するには、代わりに /low-level-design を使います。
コマンドラインインターフェースのコマンド、フラグ、出力、ヘルプを設計するには、/cli-design を使います。
手順
- リクエストとそのコンテキストからセッションの目的を読み取り、開始前に 1 行で言い換えます。これにより、読み違いがあっても 1 回のやり取りで済みます。
- プロジェクト内で指示がないまま呼び出された場合: そのプロジェクトの現在の設計を説明します。
- 目的が不明確な場合: 設計を何に使いたいのか、システムがすでに存在するのか、説明だけを求めているのかを尋ねます。
- 以下の提供フレームワークを段階ごとに進め、各段階で該当する概念に到達したら、概念のリファレンスを読みます。
- すべての段階を提示し、ユーザーが納得するまで修正します。
目的に応じて段階の進め方を決めます。以下はよくあるケースですが、すべてを網羅しているわけではありません。セッションでは、複数のケースを組み合わせたり、別のケースへ移ったりできます。
- 新しいシステムを設計する場合: すべての段階を通じて、完全な初稿を作成します。
- 既存のシステムを説明する場合: 変更せず、現状のまま各段階に沿って説明します。
- 根拠に基づいて各段階を組み立てます。既存の設計ドキュメントを出発点に、コードと照らし合わせて確認します。コードでは、ルートとハンドラー、ジョブとコンシューマー、スキーマとマイグレーション、接続設定とデプロイ設定、他のサービスへの呼び出しを読み取ります。ユーザーの説明も根拠になります。各主張の根拠となるファイル、セクション、メッセージを示します。
- コードから読み取った要件には 推定 と明記します。トラフィック、データ量、インシデント、選択理由など、根拠からはわからないことには 不明 と明記し、推測を事実として扱わないよう、ユーザーに確認します。
- 詳細な掘り下げの代わりに、設計が依拠する概念をそれぞれ説明します。たとえば、キャッシュ、シャーディング、一貫性に関する選択について、その仕組み、この設計で重要な理由、設計上のトレードオフを説明します。
- 弱点は提案ではなく所見として記録します。セッションではシステムを変更せず、説明に徹するためです。追加の質問には、設計に沿ってリクエストや障害の流れをたどって答えます。
- 既存のシステムを再設計する場合: まず現状を説明し、その説明が正しいというユーザーの同意を得ます。その後、問題の原因となっているコンポーネントを除き、既存の各コンポーネントを維持しながら、同じ段階に沿って再設計します。新しい設計のトレードオフは選択肢として提示し、変更した段階はすべて変更前と変更後の
diffで示します。 - 「ここでは Postgres と DynamoDB のどちらがよいか?」のように、1 つの事柄を決める場合: 1 つの詳細な検討として回答し、影響する設計の要素と、その背景にある要件を明示します。
提供フレームワーク
Requirements → Core entities → API → [Data flow] → High-level design → Deep dives
各段階は前の段階を土台にするため、この順番で進めます。API は要件を満たし、ハイレベル設計は API の要件を満たし、詳細な検討によってハイレベル設計が非機能要件を満たすようにします。後の段階で抜けが見つかった場合は、前の段階に戻ります。
要件
機能要件は、「ユーザーが〜できるようにする」という形で表す中核機能です。実際のシステムには何百もの機能がありますが、対象範囲のリストは3つ程度に絞ってください。リストに含める項目はすべて、設計で満たす必要があるためです。
非機能要件は、「システムが〜であるべき」という形で表す、システムに求められる品質です。それぞれこのシステムに即して記述し、可能な限り数値化してください。「低レイテンシ」ではなく、「検索結果は500 ms未満」のようにします。このチェックリストから、設計を最も左右する3〜5項目を選んでください。
- ネットワーク分断時の一貫性または可用性は、機能ごとに決定します(cap-theorem.md)。適合するストアが決まるため、まずこれを確定します。
- スケーラビリティ:トラフィックの急増、ピーク時のイベント、読み書きの比率を考慮し、どちら側をスケールさせる必要があるかを判断します。
- レイテンシ:特に、検索やフィードなど、実際の計算を必要とするリクエストについて検討します。
- 耐久性:データを失った場合の影響が、ソーシャル投稿と銀行振込ではどの程度異なるかを考慮します。
- セキュリティ:データ保護とアクセス制御を考慮します。
- フォールトトレランス:冗長性、フェイルオーバー、復旧を考慮します。
- コンプライアンス:法的・規制上の制約を考慮します。
- 環境:モバイルクライアントが不安定なネットワークを使う場合など、デバイス、メモリ、帯域幅の制限を考慮します。
見積もり: ユーザー数、QPS、ストレージ容量などは、その数値によって判断が変わる場合に限って算出します。たとえば、top-K カウンターをメモリ上のヒープ1つに格納できるか、シャーディングが必要かを判断する場合です。選択が数値に依存する設計箇所で計算してください(numbers-to-know.md)。
要件は、機能要件、非機能要件、理由を添えた対象外の項目に分け、短いリストで示します。
中核エンティティ
APIでやり取りし、ストアに永続化するものを、TwitterのUser、Tweet、Followのように、明確な名前を付けた簡潔な初稿としてまとめます。アクターは誰か、アクター同士は重複するか、各機能要件でどのリソースが必要かを確認します。リクエストによってどの項目が重要になるかは、ハイレベル設計の段階で示します。
API
システムのユーザーとの契約です。通常は機能要件ごとに1つのエンドポイントを設けます。中核エンティティをリソースとして使います。デフォルトではRESTを使い、異なるデータニーズを持つ多様なクライアントにはGraphQLを、内部のパフォーマンスが重要な呼び出しにはRPCを使います。WebSocketsやSSEなどのリアルタイム機能は、中核APIの後に設計します。現在のユーザーは認証トークンから取得し、リクエスト本文から取得してはいけません(api-design.md)。
エンティティとエンドポイントは、短いリストまたは表で示します。
データフロー
データ処理システムの場合は、入力から出力までの手順を番号付きリストで示します。ウェブクローラーの場合は、シードURLを取得し、HTMLを解析し、URLを抽出して、データを保存し、これを繰り返します。
ハイレベル設計
クライアント、ロードバランサー、サービス、データベース、キャッシュ、キューなどのコンポーネントと、それらの連携方法を配置し、API全体を満たすまでエンドポイントごとに説明します。機能要件で必要なものだけを含めます。
- API呼び出しからレスポンスまで、各リクエストのデータがシステムをどう流れるか、また、どこでどの状態が変わるかを示します。
- リクエストがストアに到達したときは、設計が依存する重要なフィールドを併記します。明白なフィールドは含めません(data-modeling.md、database-indexing.md)。
- ある部分にキャッシュやキューが必要そうな場合は、詳細設計で扱うことを記して先に進みます。
コンポーネントの流れ(client -> LB -> API -> Postgres)を使って設計を示します。また、リクエストや障害については、状態の変化とともにコンポーネントをたどる手順を番号付きで示します。ストアについては、それぞれに格納するデータ、書き込みを行うコンポーネント、キーまたはシャードキーを表にまとめます。
詳細な検討
機能以外の各要件を満たし、ボトルネックや単一障害点を取り除き、エッジケースに対処します。キャッシュ、キューなどの複雑さを加えるのはここであり、それより早い段階ではありません。早期に追加した設計は、完成して実際に動く全体に至らないことが多いためです。各問題に名前を付け、スケールに関するものには数値を添えたうえで、選択肢とトレードオフを示します。Twitter の規模では水平スケーリング、キャッシュ、シャーディングが必要になり、高速なフィードでは読み取り時のファンアウトと書き込み時のファンアウトを比較します。どの詳細を検討するかは自分で選び、ユーザーが関心のある方向へ誘導できるようにします。
「まずはデフォルト」では、それぞれのデフォルトに、どのような場合に切り替えるべきかを示すリファレンスがあります。ストアは data-modeling.md、API は api-design.md、トランスポートとリアルタイム通信は networking-essentials.md、キャッシュは caching.md、スケールは sharding.md と numbers-to-know.md、非同期処理は common-patterns.md を参照してください。
選択肢は横並びで示し、それぞれの利点とコストを説明します。また、再設計や改訂では、変更したフローやリストを変更前/変更後の diff として示します。
まずはデフォルト
システム設計で最もよくある失敗は、必要になる前に複雑さを加えることです。そのため、各選択はデフォルトから始めます。デフォルトから切り替えるのは、明確な要件がある場合に限り、スケールに関するケースでは数値も示します。
- ストア: PostgreSQL。
- API: REST。
- トランスポートとリアルタイム通信: TCP と HTTP ポーリング。
- キャッシュ: なし。その後、Redis のキャッシュ・アサイド方式。
- スケール: まずはレプリカを備えたより大きなデータベースを使い、その後ハッシュシャーディングを導入します。
- 非同期処理: なし。処理は同期のままにします。
- よくある過剰設計: 毎秒 5k 件の書き込みにキューを導入する、100 GB でシャーディングする、ポーリングで十分な場面で WebSocket を使う、インデックス付きの検索の前にキャッシュを置く。
Kafka、DynamoDB、Elasticsearch などの特定の技術を設計に採用する場合は、その詳細を前提にする前に、ドキュメントを調べます。制限、保証、障害時の挙動を確認してください。
ユーザーとの協業
/show-me を読み込み、各段階を視覚的に示します。選択の理由だけを文章で説明します。
- 設計の現行版を 1 つ維持し、改訂していきます。
- フィードバックによってある部分が変わったら、その変更が影響するすべての部分にも反映します。
- 各改訂の冒頭で、変更した部分の変更前/変更後を示し、変更の内容と理由を説明します。他の部分の変更によって間接的に変わった箇所も含めます。
- ユーザーが決定済みの事項は、ユーザーが再検討を求めない限り、そのままにします。
コード、既存の設計ドキュメント、ユーザーの以前の回答で判断できないことだけを、一度に 1 つ質問します。それ以外は自分で決め、何を決めたかを伝えます。
リファレンス
コンセプトと技術
それぞれのリファレンスでは、1つのコンセプトを取り上げ、その内容、重要な理由、トレードオフ、どのような場合にどの種類の技術を選ぶべきかを説明しています。
| リファレンス | 内容 |
|---|---|
| networking-essentials.md | TCP と UDP、HTTP、REST、gRPC、SSE、WebSockets、WebRTC、ロードバランシング、リージョン、障害対応 |
| api-design.md | REST、GraphQL、RPC、リソース、ページネーション、冪等性、バージョニング、認証 |
| data-modeling.md | データベースモデル、スキーマ設計、正規化 |
| database-indexing.md | B-tree、LSM、ハッシュ、地理空間インデックスと転置インデックス、複合インデックス |
| caching.md | キャッシュの配置、キャッシュパターン、追い出し、障害モード |
| sharding.md | シャードキー、分散戦略、ホットスポット、シャードをまたぐ処理 |
| consistent-hashing.md | ハッシュリング、仮想ノード、ホットキー |
| cap-theorem.md | 可用性に対する一貫性、一貫性レベル |
| numbers-to-know.md | ハードウェアとコンポーネントの容量、それによって防げる過剰設計 |
| common-patterns.md | リアルタイム更新、長時間実行タスク、競合、読み取りと書き込みのスケーリング、大容量のバイナリデータ、複数ステップのプロセス、近接性 |
出典:Hello Interview、Delivery Framework。