モノリス vs マイクロサービス:2026年にアーキテクチャをどう選ぶか
アーキテクチャの振り子は振れた。マイクロサービスはもはやデフォルトの答えではない。モジュラーモノリス、抽出戦略、そして議論を断ち切るたった一つの質問を含む、実践的なアドバイス。
10年近くにわたり、ソフトウェアアーキテクチャにおける従来の知恵は単純だった:マイクロサービスが未来であり、モノリスはレガシーである。新しいプロジェクトを始めるならマイクロサービスを構築する。既存のモノリスがあれば、その分解を計画する。問題はマイクロサービスを採用するかどうかではなく、どれだけ速くそこに到達できるかだった。
そのコンセンサスは死んだ。過去3年間で、マイクロサービスを早すぎる段階で、あまりに積極的に、または間違った理由で採用したチームからの反省レポートが相次いでいる。AmazonのPrime Videoチームは、サーバーレスマイクロサービスからモノリスに移行することでコストを90%削減した事例を発表した。InnoGamesはマイクロサービスをモノリスに統合することでインフラの複雑さを半減させたと報告している。これらの事例は異常値ではなく、修正の最先端である。
この記事は一方のアーキテクチャを支持するものではない。2026年の視点から、誇大広告と幻滅の全サイクルを見届けた上で、両者を選択するための意思決定フレームワークを提供する。読み終える頃には、次のアーキテクチャを選ぶ前に問うべき質問が正確にわかるだろう。
振り子は戻ってきた
マイクロサービスの当初の約束は魅力的だった:独立したデプロイ可能性、チームの自律性、ポリグロットな技術スタック、水平方向のスケーラビリティ。各サービスは小さなチームで他と調整することなく開発、テスト、デプロイできる。サービスが失敗してもシステム全体がダウンすることはない。スケールが必要なサービスだけをスケールできる。
これらの利点は本物だが、誇大広告の時代に組織的に過小評価されていた代償が伴う。すべてのマイクロサービスは、ネットワークレイテンシ、分散システムの複雑さ、データ整合性の課題、運用オーバーヘッドを導入する。モノリスには1つのデプロイパイプライン、1つの監視対象アプリケーション、1つの管理対象データベース、1つのナビゲート対象コードベースがある。10のマイクロサービスは、それらの間の統合ポイントの数だけ掛け合わせた10倍のすべてを持つ。
業界が再発見した根本的な洞察は、マイクロサービスは便益ではなくコストであるということだ。これらは特定の制約——チームサイズ、スケーリング要件、デプロイ頻度——を管理するためのツールであり、すべてのシステムが目指すべき最終状態ではない。マイクロサービスが解決する問題を抱えていないのであれば、マイクロサービスはシステムを良くしない。システムをより高価で、変更しにくくするだけだ。
マイクロサービスは特定の問題セットに対する優れた解決策である。その問題を抱えていなければ、マイクロサービスのコストを支払いながら利益を得ていないことになる。最も高価なアーキテクチャとは、あなたが抱えていない問題を解決するためのものである。
2026年のランドスケープはこの修正を反映している。純粋なマイクロサービスアーキテクチャは現在、それを真に必要とする組織——数十のチームを持つ大規模エンジニアリング組織、異なるコンポーネントの独立したスケーリングが必要なプラットフォーム、サービスごとに根本的に異なる信頼性やレイテンシ要件を持つ製品——に集中している。それ以外のほとんどの場所では、チームはよりシンプルなアーキテクチャを選択し、マイクロサービスはそれを必要とする特定のケースのために留保している。
モノリスが勝つとき
モノリスはほとんどのプロジェクトにとって正しいデフォルトである。これは経験豊富なアーキテクトの間では議論の余地のない主張だが、多くの開発者がマイクロサービスの誇大広告サイクルの中で吸収してきたメッセージとは矛盾する。モノリスは負けるよりも多くのシナリオで勝つ。鍵はどのシナリオかを知ることだ。
チームサイズはアーキテクチャの成功を予測する最も強力な単一指標である。チームが10人未満であれば、モノリスがほぼ間違いなく正しい選択である。少人数チームの場合、マイクロサービスの調整オーバーヘッド——サービス境界の調整、サービス間契約の管理、複数のデプロイパイプラインの維持——は、利用可能なエンジニアリングキャパシティのかなりの部分を消費する。作成するすべてのサービス境界は維持しなければならない契約であり、契約の維持は機能を出荷しない作業である。
スタートアップ段階もまた明確なシグナルである。製品が2年未満であるか、ビジネスモデルがまだ進化している場合、モノリスは迅速に方向転換する能力を保持する。マイクロサービスは、最初の1年でほぼ間違いなく間違えるドメイン境界についての仮定を固定化する。モノリスは自由にリファクタリングできる。アプリケーション全体が1つのコードベースであれば、機能をあるモジュールから別のモジュールに移動するのはリファクタリング操作である。アプリケーションが10のサービスであれば、機能を移動するにはサービスインターフェースの変更、コンシューマーの更新、デプロイの調整、データの移行が必要になる。
# What a simple monolith deployment looks like in 2026
# A single Dockerfile, a single service, zero orchestration
FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["node", "dist/server.js"]
# One docker-compose.yml for the entire stack
services:
app:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://db:5432/app
db:
image: postgres:17
volumes:
- pgdata:/var/lib/postgresql/dataこのセットアップの運用上の単純さは過小評価できない。監視するサービスは1つ、確認するログは1セット、ロールバックするデプロイは1つ。ジュニア開発者でもデプロイパイプライン全体を午後には理解できる。何かが壊れたとき、原因を探す場所は正確に1つだ。この単純さは贅沢品ではなく、時間とともに複利効果を生む戦略的優位性である。
ドメインの複雑さもモノリスを後押しする要因である。逆説的に、ドメインが複雑であればあるほど、時期尚早なサービス分割は危険になる。自然な境界を理解する前に複雑なドメインをサービスに分割すると、間違った方法で密結合されたサービスが生まれる——一方を変更するともう一方も変更せざるを得ないため独立してデプロイできないサービス、データがきれいに分割できないためデータベースを共有するサービス、契約が変わり続けるため連動してデプロイする必要があるサービス。
モジュラーモノリス:ほとんどのチームが検討すらしないアーキテクチャ
モノリスとマイクロサービスの二者択一は誤った二分法である。モジュラーモノリスは中間の立場を占め、両極端のいずれよりも多くのチームにとって正しい答えである。モジュラーモノリスは単一のデプロイユニットでありながら、マイクロサービスと同じ境界ルールに従う明確に定義された内部モジュールを持つが、ネットワークは介さない。
モジュラーモノリスと典型的なモノリスの主な違いは規律である。典型的なモノリスではモジュールは強制されない——どんなコードも他のどんなコードもインポートでき、時間とともに境界は侵食されて泥だんごと化する。モジュラーモノリスでは、モジュールは明示的な公開APIとプライベート実装を持つ。モジュールAはモジュールBの定義されたインターフェースを通じてのみ相互作用できる。モジュール境界を越えた直接のデータベースアクセスは禁止される。マイクロサービス通信を支配するのと同じルールが適用されるが、通信はHTTPリクエストではなく関数呼び出しを通じて行われる。
このアプローチは、マイクロサービスの利点のほとんど——強制された境界、モジュール内の独立した開発、明確な契約——を運用コストなしで提供する。1つのデプロイパイプライン、1つの監視対象アプリケーション、1つのナビゲート対象コードベースを得られる。しかし同時に、泥だんご問題を防ぎ、将来のマイクロサービス抽出を容易にするモジュール境界も得られる。
// A modular monolith boundary in TypeScript
// Each module exposes only its public API
// modules/orders/public-api.ts
export {
createOrder,
getOrderById,
getOrdersByUser,
OrderService,
} from "./order-service";
// modules/orders/internal/ ← everything here is private
// order-repository.ts
// order-validator.ts
// order-pricing.ts
// modules/payments/public-api.ts
export {
processPayment,
getPaymentStatus,
refundPayment,
} from "./payment-service";
// Cross-module dependency is explicit and auditable
// payments/payment-service.ts imports from orders/public-api
import { getOrderById } from "../../orders/public-api";モジュラーモノリスは不確実な未来に対する最良のヘッジでもある。モジュラーモノリスを構築し、後であるモジュールを独立したサービスにする必要があると判明した場合、抽出は機械的に行える:モジュールのコードを新しいサービスにコピーし、その公開APIをHTTPまたはメッセージキューで公開し、呼び出し元を配線する。モジュール境界はすでに存在する。インターフェースはすでに定義されている。難しい作業——ドメイン境界の理解——はすでに完了している。
モジュール境界なしで従来のモノリスを構築し、後からサービスを抽出したい場合、はるかに困難な問題に直面する。まず境界がどこにあるべきかを発見し、次にそれらを尊重するようコードをリファクタリングし、その後ようやく抽出できる。これがほとんどのモノリスからマイクロサービスへの移行が失敗する理由である——チームは境界発見の作業を過小評価し、目的を無効にする方法で結合されたマイクロサービスに行き着く。
- モジュラーモノリス:単一のデプロイ可能ユニット、ネットワーク呼び出しを関数呼び出しに置換、強制されたモジュール境界、容易な抽出パス。
- 従来のモノリス:単一のデプロイ可能ユニット、強制されない境界、初期段階での最大の自由度、苦痛な抽出パス。
- マイクロサービス:多数のデプロイ可能ユニット、ネットワーク呼び出しによる通信、強制されたサービス境界、高い運用コスト。
- モジュラーモノリスは通常、最良の出発点である。分散システムの複雑さにコミットせずにオプションを保持できるからだ。
マイクロサービスが実際に意味を持つとき
マイクロサービスは間違っていない。ほとんどのチームにとっては間違っているが、コストが便益によって正当化されるシナリオは存在する。鍵は、自分のシナリオが実際に適合するかどうかについて正直になることだ。
独立したスケーリングはマイクロサービスに対する最も防御可能な理由である。システムの異なる部分が劇的に異なるスケーリングプロファイルを持つ場合——APIゲートウェイが毎秒10万リクエストを処理する一方で、レポートサービスが1時間に100リクエストしか処理しない——それらを同じデプロイユニットに入れるとリソースが無駄になる。レポートサービスのハードウェアはアイドル状態になり、APIゲートウェイのオートスケーリングはレポートサービスのコールドスタート時間によって制約される。サービスを分離すれば独立してスケールでき、効率的なリソース活用によるコスト削減が運用オーバーヘッドを相殺できる。
チームの自律性が2つ目の正当な理由である。同じシステムで複数のチームが作業しており、各チームが独自のリズムで独立してデプロイする必要がある場合、マイクロサービスは調整のボトルネックを取り除く。チームAはチームBのレビューを待たずに1日3回サービスをデプロイできる。ただし、閾値に注意:この議論は複数のチームが存在する場合にのみ適用される。組織全体で10人の開発者であれば、マイクロサービスが解決する調整問題は存在しない。共有Slackチャンネルで解決できるコミュニケーション問題があるだけだ。
異なる信頼性やレイテンシ要件もマイクロサービスを正当化する。決済処理サービスに99.999%のアップタイムが必要で、分析サービスが時折のダウンタイムを許容できる場合、それらを分離することで、分析レポートのバグが顧客のチェックアウトを妨げないようにできる。同様に、システムの一部が極端に低いレイテンシを必要とし、別の部分がより高いレイテンシを許容できる場合、分離することでそれぞれを独立して最適化できる。
技術の多様性はマイクロサービスに対する最も弱い議論である。確かに、マイクロサービスはサービスごとに異なる言語やデータベースを使用できる。しかし実際には、ほとんどの組織はとにかく少数の技術に収束し、複数のランタイムを維持する運用コストは通常、便益を上回る。チーム全体がTypeScriptとPostgreSQLを知っているのに、単に異なる技術を使うためだけに1つのサービスをRustで、別のサービスをGoで構築することは、ほとんどの組織が負担できない贅沢である。
モノリスで始めてサービスを抽出するパターン
2026年にソフトウェアシステムを構築するための最も信頼性の高いパターンは、最もシンプルでもある:モジュラーモノリスで始め、必要であるという証拠があってからサービスを抽出する。これはモノリスファーストまたはマイクロサービス抽出パターンと呼ばれることもあり、マイクロサービスの誇大広告サイクルを経験し生き残った組織からのデフォルトの推奨事項となっている。
このパターンは4つのフェーズで機能する。フェーズ1はモジュラーモノリスである。厳格なモジュール境界を持つ単一のデプロイ可能ユニットとしてアプリケーション全体を構築する。各モジュールは自身のデータを所有し、公開APIを公開し、実装をプライベートに保つ。マイクロサービスに使用するのと同じ規律——明確な契約、分離されたデータ所有権、明示的な依存関係——を適用するが、すべてが単一のプロセス内で実行される。
フェーズ2は測定である。どのモジュールが最も頻繁に変更されているか、どのチームがどのモジュールに取り組んでいるか、どのモジュールに異なるスケーリングや信頼性要件があるかを監視する。直感や推測に基づいてサービスを抽出するのではない。データ——モノリスがボトルネックを生み出しており、サービス境界がそれを解決するという実際の証拠——に基づいて抽出する。
フェーズ3は抽出である。サービスになる必要があることが証明されたモジュール——変更頻度がモノリスのデプロイを増やしすぎている、またはスケーリング要件がシステムの残りと異なる——を抽出する。モジュールはすでにクリーンな境界を持っているため、抽出は機械的に行える。独自のデプロイパイプラインを持つ新しいサービスを作成し、モジュールの公開APIをHTTPまたはメッセージキューで公開し、モノリスを更新してモジュールの代わりに新しいサービスを呼び出す。
// Step 1: Define the extraction candidate as a module
// monolith/src/modules/reports/public-api.ts
export async function generateReport(
reportId: string
): Promise<ReportResult> {
// Implementation detail: queries a separate read-replica,
// takes 30 seconds, should not block the main application
}
// Step 2: When evidence shows this needs to be a service:
// 1. Create a new service from the module code
// 2. Expose the same API over HTTP
// 3. Replace the direct call with a service client
// monolith/src/clients/reporting-service.ts
const client = new ServiceClient({
name: "reporting",
baseUrl: process.env.REPORTING_SERVICE_URL,
timeout: 60000, // This service is slow
});
export async function generateReport(reportId: string) {
return client.post("/reports", { reportId });
}
// The monolith does not need to redeploy — the client handles
// retries, timeouts, and circuit breaking internally.フェーズ4は反復である。システムが成長するにつれて、サイクルを繰り返す——測定、抽出、再測定。抽出したサービスの一部は、さらに小さなサービスに分割する必要があるかもしれない。抽出が価値を提供しなかった場合は、モノリスに戻す必要があるかもしれない。重要なのは、すべての抽出がアーキテクチャ上のドグマではなく証拠によって駆動されることだ。
このパターンにはマイクロサービスファーストのアプローチに対する1つの決定的な利点がある:不可逆的な決定を先送りすることだ。作成するすべてのサービス境界は、分散システムの複雑さへの不可逆的なコミットメントである。サービスが存在すると、クライアントを壊さずにその境界を簡単に変更することはできない。モノリスで始めて必要なときにのみ抽出することで、すべてのサービス境界が将来のニーズの推測ではなく実際の要件によって正当化されることが保証される。
選択方法:意思決定フレームワーク
新しいシステムを設計するとき、または現在のアーキテクチャを評価するときは、以下の質問を順番に検討する。答えは、未来を予測する必要なく、正しいアーキテクチャへと導いてくれる。
最初の質問:このシステムには何人の開発者が取り組んでいるか?答えが10人未満なら、モノリス——できればモジュラーモノリス——で始める。マイクロサービスが解決するような調整問題はなく、運用オーバーヘッドを負担できない。答えが10人以上の場合、その組織方法による。単一のチームとして機能しているならモノリスでも機能する。複数の自律的なチームに編成されているなら、マイクロサービスを検討する価値がある。
2つ目の質問:システムに根本的に異なるスケーリングプロファイルを持つコンポーネントはあるか?システムのすべての部分がほぼ同じレートでスケールする必要があるなら、分離するメリットはない。あるコンポーネントが毎秒1万リクエストを処理し、別のコンポーネントが10リクエストしか処理しないなら、分離する——ただし、システム全体ではなく、高スケールのコンポーネントだけを最初に分離する。
3つ目の質問:システムのすべての部分を同じスケジュールでデプロイできるか?はいの場合、モノリスはデプロイパイプラインを単純化し、調整コストを削減する。いいえの場合——システムの異なる部分に異なるリリースサイクル、規制要件、またはリスクプロファイルがあるため——マイクロサービスにより各パーツが独自のデプロイリズムに従うことができる。
4つ目の質問:システムのすべての部分が同時にダウンしたらどうなるか?答えが「ビジネスが完全に停止する」なら、マイクロサービスから回復力を得ているのではなく、単にコストを支払っているだけだ。真の回復力には、個別のサービスだけでなく、個別のインフラ、個別のデータストア、サービス間のグレースフルデグラデーションが必要である。ほとんどのチームはこれを構築しない。デプロイでは密結合、理論上は疎結合という最悪のサービスを構築する。
最良のアーキテクチャとは、チームが自信を持ってデプロイでき、迅速にデバッグでき、恐れずに変更できるものである。それがあなたの特定の組織にとってどのようなものであれ——モノリス、モジュラーモノリス、マイクロサービス——それが正しい答えである。それ以外はすべて、エンジニアリング原則を装ったアーキテクチャファッションである。
5つ目の質問:ドメイン境界についてどの程度確信があるか?確立されたパターンを持つよく理解されたドメイン——eコマース、コンテンツ管理、請求——で構築している場合、ドメイン境界は比較的安定しており、マイクロサービスのリスクは低い。境界がまだ出現途上にある新しいドメインで構築している場合、モノリスは理解が進むにつれてリファクタリングする能力を保持する。時期尚早なサービス境界は、まさに実行すべき学習プロセスを遅らせる制約となる。
2026年のほとんどのチームにとって正直な答えはモジュラーモノリスである。マイクロサービスの規律を運用コストなしで提供する。後でサービスを抽出するオプションを保持しながら、今日分散システムの複雑さにコミットすることを強制しない。単一の開発者でデプロイ可能で、単一のログストリームでデバッグ可能で、単一のプルリクエストで変更可能である。そして、モノリスが機能しなくなるほどシステムが成長した場合、構築したモジュール境界により、マイクロサービスへの移行が予想よりもスムーズになる。
アーキテクチャの振り子はシンプルさへと戻ってきた。それは後退ではない。業界が経験から学んでいるのだ。誇大広告を無視した——またはそこから迅速に回復した——チームは、サービスを移行しているのではなく、機能を出荷している。出荷できるアーキテクチャを選び、システムが変更を必要としていると告げたときにのみ変更せよ。
