- 初期のスタートアップでコードを性急にマイクロサービスへ分割すると、チームの生産性の深刻な低下と複雑性の増大を招く
- モノリシック(単一)アーキテクチャは、シンプルなデプロイ、高速な新機能リリース、効率的な協業を通じて生存に最適化されている
- マイクロサービスは、大規模なスケーラビリティ、多様なワークロード、または別個のランタイム要件がある場合にのみ、分離の利点を発揮する
- 過度なサービス分割、リポジトリの乱立、不安定なローカル開発環境、技術スタックの不一致などが、速度低下とチーム士気の低下につながる
- スタートアップはモノリスから始めて、明確なボトルネックが生じた時だけ分離する慎重なアプローチが最適である
序論と背景
- スタートアップの生存は、高速な反復、新機能の提供、ユーザー価値の創出によって決まる
- プロジェクトの基本アーキテクチャ、技術スタック、プログラミング言語の選択がチームの速度に影響する
- 早期のマイクロサービス導入は表向きには洗練されて見えるが、実際には生産性低下、未完成サービス、過剰な複雑性を招く
- データ: サービスオーケストレーション、Docker/スクリプトの問題、重複したCI/CD、サービス間結合、可観測性コスト、テストの分散など、さまざまな開発コストが発生する
- むやみに複雑なアーキテクチャへ進むのではなく、実利的なアーキテクチャの重要性を強調している
モノリスの強み
- SaaSであれ単純なデータベースラッパーであれ、時間とともにアプリは複雑になるが、モノリスアーキテクチャはシンプルかつ柔軟に保ちやすい
- デプロイが容易で、人気フレームワーク(Django, ASP.Net, Nest.js など)の支援やオープンソースコミュニティの恩恵が大きい
- 実例: ある不動産スタートアップでは Laravel モノリスを使い、多数のサードパーティ統合や機能拡張を容易に実現した
- 複雑なインフラ導入やマイクロサービスへの分割を行わず、ビジネス要件と期待値の充足に集中できた
- 教訓: アーキテクチャの簡潔さはチームがデプロイに集中する助けとなり、内部のモジュール化の失敗さえ避ければ十分にスケール可能である
マイクロサービスは常に最善か?
- 多くのエンジニアはマイクロサービスが模範解答だと考えるが、実際にはスケールなど特別な理由がある時にだけ真価を発揮する
- 少人数・小規模・高速変化の段階では、むしろ重複インフラ、遅いローカル開発、遅い反復サイクルという逆効果を生む
- Segment のような企業も、非効率な構造による転換を経験している
- 教訓: マイクロサービスはボトルネック解消のためのツールであり、初期テンプレートではない
マイクロサービスが特に初期段階で失敗する理由
1. 恣意的なサービス境界
- ドメイン駆動設計やクリーンアーキテクチャ理論を借用し、ビジネスロジックごとにサービス分割を試みても、実際のロジックとサービス境界がうまく一致しない
- 例: ユーザー、認証、権限の分離により、デプロイの複雑性や API 開発の難度が上がる
- 実際のボトルネックが発生していない段階での分離は、システムを不安定かつ低速にする
- 内部フラグやトグルで将来の分離をシミュレーションし、急ぎのインフラ作業よりも有機的な境界探索を行う方が効果的である
- 教訓: 理論ではなく実際のボトルネックに基づいて分離を決めるべきである
2. リポジトリ/インフラの過剰化
- コードスタイル、テスト、設定、ドキュメント、CI/CD など、あらゆる要素がサービス数に比例して増える
- モノレポ構造を使えば、すべての構成を一か所で管理し、コードの一貫性と協業効率を高められる
- Node.js の場合、
nx や turborepo のようなツールで、内部サービス間の依存関係やビルド管理を容易にできる
- 欠点としては、複雑な依存関係、CI 性能のチューニングの必要性、より高速なビルドツールの必要性などがある
- Go エコシステムでも、初期は単一 workspace で管理し、規模が大きくなればモジュール分割を検討できる
- 教訓: 小さなチームはモノレポと共有インフラによって時間を確保できる
3. 不安定なローカル開発環境
- ローカル実行に過度な時間がかかる、スクリプトが複雑、システム依存が多いなど、オンボーディングの遅延と生産性低下が発生する
- 文書化不足、互換性問題、OS 固有のハック(例: macOS 専用スクリプト)などが障害となる
- あるプロジェクトでは、Node.js プロキシによって Docker の複雑性を緩和し、開発者のオンボーディング時間を短縮した
- 教訓: アプリが一つの OS でしか動かないなら、チームの生産性は結局一台のラップトップの信頼性に左右される
4. 技術スタックの不一致
- Node.js と Python は高速な反復には向いているが、マイクロサービス環境ではビルド/ランタイムの不一致問題が頻発する
- Go は静的バイナリ、高速ビルド、運用の単純さで利点がある
- 初期の技術スタック選定は慎重に行うべきで、必要であれば gRPC などのプロトコルで言語混在も可能である
- ML・ETL などの特別な要件がないなら、スタック混在はむしろ複雑性を増すだけである
- 教訓: 理想ではなくチームの現実に合ったスタックを選ぶべきである
5. 隠れた複雑性: 通信と監視
- マイクロサービスでは、サービスディスカバリ、API バージョニング、分散トレーシング、集中ログ管理などが必須となる
- バグや障害の追跡は、モノリスではスタックトレース一つで済んでも、分散環境でははるかに複雑になる
- きちんとやるには、OpenTelemetry などの専門ツール導入と可観測性スタックの構築が必要である
- 分散システムは、追加のエンジニアリング課題に対する義務的投資だと認識しなければならない
マイクロサービスが有効な状況
- ワークロード分離: 画像処理、OCR など特定の非同期処理を分離すると効率的である
- スケーリング必要性の不均衡: Web API と ML ワークロードでハードウェア・運用要件が異なる場合、それぞれ別に分離する
- 別のランタイムが必要: レガシー C++ コードなど、主要アプリとランタイム互換のない構成要素は分離サービスとして維持する
- 大規模なエンジニアリング組織(例: Uber)の事例から見ても、明白な組織的必要と成熟した運用能力がある場合にのみ適している
- 小規模チームでも、外部分析サービスのように管理が単純な場合には、まれに分離が実用的である
- 教訓: 実質的に分離の利点が明確なワークロードでのみ採用すべきである
スタートアップ実践ガイド
- 最初はモノリスで始め、実証済みのフレームワークで開発に集中するべきである
- シングルリポジトリは、運用・管理効率やセキュリティの観点から初期チームにより有益である
- ローカル開発環境の簡素化が重要であり、難しい場合は詳細な案内文書や動画の提供が必須である
- CI/CD への早期投資により、反復作業の自動化とチームの心理的負担の軽減が必要である
- 明確なボトルネックが現れた時だけ選択的に分離し、それまではモノリス内のモジュール化とテスト強化に集中する
- 最優先目標は開発速度の維持である
- 教訓: シンプルさから始め、分離の必要性に応じてスケールすべきである
マイクロサービスをどうしても使うなら
- 技術スタック評価と開発者体験ツールへの投資: サービスごとの自動化、明確なスクリプト、統合デプロイ管理ツールの整備が必要である
- 信頼できるサービス間通信プロトコルと標準化: メッセージスキーマの一貫性、文書化、エラー処理など、追加実装事項を把握する必要がある
- テストインフラの安定化: 単体・統合・E2E テストがサービス分離に合わせて拡張されるべきである
- 共通ライブラリの検討: 可観測性・通信の共通コードは最小範囲に保ち、全サービスの頻繁な再ビルドを防ぐ
- 可観測性は早期導入: 構造化 JSON ログ、コリレーション ID など基本的なロギングツールから整備するべきである
- 結論として、複雑性を受け入れるなら、全力で管理可能な体制を設計することが重要である
結論
- 性急なマイクロサービス導入は負担だけを残すため、シンプルさを最優先に選ぶべきである
- 明確な痛点なしに分離せず、生き残り成長するために必要な最小限の複雑性だけを追加するという視点が重要である
- 生き残ることが先、スケールはその後である
10件のコメント
元の話には全体的に同意します。
組織の経験の問題だと思います。
フードトラックで料理を売っていて、やがてレストランへと成長していくことを想像するとよいでしょう。
最初から分業化や専門化を考えるには、利害関係者の経験が絶対的に不足しています。
スタートアップは生存期間を延ばすために、コストの低い方法を選ぶべきだと思います。マイクロサービスは決して安くありません。実際に現場へ適用すると、かなりのコストを発生させます。できるだけ自社サービスに合ったアーキテクチャを設計することが、より少ないコストで同様の効果を得られる方法だと考えます。
マイクロサービスが悪いというわけではありません。多くのコストを必要とするモデルです。
同期専用モノリスと非同期専用モノリスの2つだけでも十分だと思いますし……。マイクロサービスの導入は、結局のところDBで管理すべきテーブルの規模次第だと考えています。テーブルが常識外れに多くて複雑ならMSAを検討すべきですし、単純ならモノリスが最適でしょう。
このすべての波が過ぎ去ったとき、後世はこの時代をどのように記憶するでしょうか
あの時はまたあの時の波が…
スタートアップでも、マイクロサービスには多くの利点があると思います。まず、モノレポを使う利点は本当におすすめです。
大規模AI開発時代に合わせて、小さな単位で単一責任として実装することが必須だという点には同意します
意見欄でも少し出ていましたが、beam/otp 系はこういうかなり柔軟で良い感じですね。Gleam の場合は、go と rust 両方の良い文法に beam の安定性が加わって、かなり印象的な言語になっています。小規模プロジェクトでそろそろ使ってみたいですね。
チームをやたらと細かく分けると、集まって意見を交わすことさえ非常に大きな業務になってしまいます。
Hacker Newsの意見