アプリケーションとインフラを分けて考えるほど、設計は壊れやすくなる
Hatched by Ryusei Nakamura
Sep 05, 2026
1 min read
0 views
88%
「画面を作ること」と「サービスを動かし続けること」は、別々の専門領域だと思われがちです。しかし本当に難しいのは、その境界を引くことではありません。どの責任を、どの境界に置くかを決めることです。
Webアプリケーションの設計思想と、クラウド上のコンテナ設計は、一見すると異なる話に見えます。前者は画面表示やデータ取得の方法を扱い、後者は実行環境、ネットワーク、監視、スケーリングを扱います。けれども両者は、同じ問いに答えようとしています。
複雑なシステムを、変更しやすく、壊れにくく、理解可能な単位へどう分解するか。
この問いを見落とすと、アプリケーションは動くのに運用できない状態になり、インフラは堅牢なのに開発者が何も変更できない状態になります。優れた設計とは、個々の技術を正しく使うことではなく、変更の流れと障害の広がり方を設計することです。
便利な抽象化は、責任の所在を隠すためにあるのではない
現代のWeb開発では、フレームワークが多くの判断を引き受けてくれます。ページの生成、データ取得、キャッシュ、ルーティング、認証との接続などを、個別に組み立てる代わりに、一定の規約に沿って記述できます。これは単なる省力化ではありません。チーム全員が毎回同じ問題を解かずに済むという意味で、設計判断を共有する仕組みです。
コンテナも同じ役割を持ちます。アプリケーションとその実行に必要なライブラリをひとまとまりにし、開発環境と本番環境の差を小さくします。誰のコンピューターで動かすかという偶然を減らし、サービスをどのような単位で配置し、交換し、増減させるかを明確にします。
ただし、抽象化には危険があります。便利な仕組みを採用すると、内部の構造を理解しなくても動かせるようになります。その結果、障害が起きた瞬間に「どこで責任を負うべきか」が分からなくなります。
たとえば、画面表示が遅いとします。原因は、ブラウザー側の処理かもしれません。サーバーでのデータ取得かもしれません。データベースへの接続数、コンテナの起動時間、通信経路、キャッシュ設定が原因かもしれません。抽象化が多いほど開発は速くなりますが、観測可能性がなければ、問題の所在は見えにくくなります。
だから重要なのは、抽象化を減らすことではありません。抽象化の境界を越えたとき、何が起きているかを説明できることです。
設計単位は、技術ではなく変更単位で決める
システムを分割するとき、多くの人は技術名から考え始めます。画面はこの仕組み、APIはこの仕組み、処理はこのコンテナ、といった具合です。しかし、より強い出発点は「何が一緒に変更されるか」です。
あるECサイトに商品一覧、商品詳細、注文処理があるとします。商品一覧の表示方法を変更したとき、注文処理まで再配置する必要があるでしょうか。通常は必要ありません。一方、注文処理のデータ構造を変更すると、在庫更新や決済連携も同時に見直す必要があるかもしれません。
ここで有効なのが、変更の結合度という見方です。二つの機能が頻繁に一緒に変更されるなら、同じ境界内に置く価値があります。ほとんど独立して変更されるなら、別の境界に置く価値があります。
コンテナを細かく分ければよいわけでもありません。サービスを細分化すると、個別のデプロイやスケーリングはしやすくなります。しかし通信、認証、監視、障害対応の経路が増えます。逆に、すべてを一つの実行単位に詰め込めば、通信は単純になりますが、小さな変更でも全体を再配置することになります。
この判断は、部品の大きさではなく、変更の頻度、障害の影響範囲、必要な拡張方向で決めるべきです。
たとえば画像変換処理だけが急激に負荷を増やすサービスなら、注文処理と同じ実行単位に置く理由は弱いでしょう。画像変換だけを増やせる方が、費用と性能の両面で有利です。一方、二つの処理が常に同じデータを参照し、同じタイミングで成功しなければならないなら、分離による通信コストや失敗パターンの増加が、得られる利益を上回る可能性があります。
良い境界とは、部品を小さくする線ではない。変更と障害が広がる方向を制御する線である。
配置を考えるときは、成功時より失敗時を先に見る
設計の議論では、正常系が中心になりがちです。利用者がページを開き、サーバーが処理し、データが返り、コンテナが稼働する。けれども、実際の設計品質が表れるのは、どこかが失敗したときです。
一つの処理を別の実行単位へ分けると、独立して拡張できるようになります。しかし同時に、通信失敗、応答遅延、再試行の重複、部分的な成功が発生します。画面をサーバー側で生成する場合も、データ取得先が遅ければ、利用者は画面全体の遅延として影響を受けます。表示方法の選択は、単なる速度の問題ではなく、失敗をどの場所で止めるかの問題です。
ここで使える実践的な方法があります。設計図を描くとき、各境界に次の四つを書き込みます。
- この境界の外で障害が起きたら、利用者には何が見えるか
- この処理は何回実行されても安全か
- どの程度の遅延まで許容できるか
- 失敗を検知し、原因を追跡する情報があるか
たとえば注文確定処理は、通信が再試行されても二重注文にならない仕組みが必要です。画面に表示するおすすめ商品は、取得に失敗しても注文機能を止めない設計にできます。すべての機能を同じ重要度で扱うのではなく、失敗の許容度に応じて実行単位と表示単位を変えるのです。
この考え方を採用すると、設計は「何を分けるか」から「何を一緒に壊してよいか」へ変わります。これは非常に重要な転換です。システムは完全には壊れません。だからこそ、壊れ方を選ばなければなりません。
標準化は自由を奪うのではなく、自由を使う場所を選ぶ
チームが成長すると、開発者ごとに異なる構成や運用方法を採用することが難しくなります。実行環境の作り方、ログの形式、設定値の渡し方、デプロイの手順が毎回異なれば、障害対応は経験者の記憶に依存します。
そこで、フレームワークの規約やコンテナの共通構成が役立ちます。サービスの起動方法、環境ごとの設定、監視の入口、公開経路などを標準化すれば、個別の機能開発に集中できます。これは創造性を抑えるためではありません。毎回繰り返す判断を自動化し、本当に差別化したい領域へ判断力を残すためです。
ただし、標準化すべきものと、選択肢を残すべきものは分ける必要があります。
標準化に向いているのは、ログ出力、秘密情報の管理、ヘルスチェック、デプロイ手順、エラーの形式、基本的な監視です。これらはサービスごとに独自性を持たせても、利用者への価値が増えにくい領域です。
一方、利用者体験、データの整合性、キャッシュの戦略、処理の優先順位などは、事業や機能によって異なります。ここまで一律に固定すると、仕組みが目的化します。
判断に迷ったら、次の基準が使えます。その違いは利用者に価値を届けるために必要か、それとも単にチーム内の好みか。後者なら標準化し、前者なら理由を記録したうえで選択の余地を残すべきです。
今日から使える設計のチェックリスト
アプリケーションと実行環境を一緒に設計するために、次の手順を試してください。
-
変更の地図を作る 過去数か月の変更履歴を見て、どの機能が一緒に変更されているかを確認します。現在の分割が、実際の変更の流れと一致しているかを調べます。
-
障害の地図を作る 各サービスや画面について、停止した場合に何が止まるかを書き出します。重要でない機能が重要な機能を巻き込まない境界を探します。
-
境界ごとに観測点を置く 応答時間、エラー率、処理数、再試行回数、実行中の数を記録します。動いているかどうかだけでなく、どのように悪化しているかを見えるようにします。
-
標準構成を一つ作る 新しいサービスを作るたびに、実行、ログ、設定、監視、デプロイの基本が同じ形で始まるようにします。例外は許可しますが、最初から例外を前提にしません。
-
失敗を含めて設計レビューする 正常に動く説明だけで承認しないことです。通信が遅い場合、同じ要求が二度届いた場合、片方の処理だけ成功した場合を確認します。
結論: システム設計とは、境界を増やすことではない
Webアプリケーションの構造とクラウド上の実行環境は、別々に最適化するものではありません。画面の生成方法は通信経路やキャッシュと結び付き、コンテナの分割はデプロイの頻度や障害の広がり方と結び付きます。どちらか一方だけを見れば、もう一方に複雑さを押し付けることになります。
優れた設計は、技術の一覧では説明できません。それは、変更がどこまで届き、障害がどこで止まり、チームが何を理解しなくても安全に扱えるかを示す地図です。
最終的に問うべきなのは、「この機能をどの技術で作るか」ではありません。
この境界は、私たちが変化し、失敗し、学び続けるために十分な強さを持っているか。
アプリケーションとインフラを一体として設計するとは、すべてを一つにまとめることではありません。変更と失敗を、意図した範囲に閉じ込めることです。その視点を持てば、フレームワークもコンテナも、単なる便利な道具ではなく、組織の思考を形にするための境界装置として見えてきます。
Sources
Hatch New Ideas with Glasp AI 🐣
Glasp AI allows you to hatch new ideas based on your curated content. Let's curate and create with Glasp AI :)
Start Hatching 🐣