🦀

Full-Stack TSでのマルチプロダクト基盤開発

に公開

はじめに

VPoTの@soartec-labです。この記事はMOSH Advent Calendar 2025の4日目の記事です。

この記事は先日参加したTSKaigi Hokuriku 2025 で発表したFull-Stack TSでのマルチプロダクト基盤開発の内容をまとめ文章化した内容です。スライドも合わせてご一読ください。

マルチプロダクト開発の背景


MOSHでは、クリエイターがオンラインで活動するための複数のサービスを展開しており、予約、サブスク、コミュニティなど多様な価値をオールインワンで提供しています。更なるビジネス拡大とクリエイターの多様で変化する要求に応えるために「マルチプロダクトの基盤」を構築しています。

サービス成長のスピードを落とさず価値を提供し続けるため、フルサイクル開発を採用しています。小さな開発ユニットがドメイン理解を深めながら企画から運用まで一貫して担う体制です。

こうした背景の中で、TypeScriptをフロントエンド、バックエンド、一部インフラに共通して採用し、開発体験と変更容易性の向上を図っています。本記事では、その基盤構築におけるアーキテクチャと技術的な工夫を紹介します。

フルサイクル開発のメリットと直面した「リアル」


MOSHが採用しているフルサイクル開発は、Netflixが提唱したFull Cycle Developersの概念に基づいています。開発者が設計・実装だけでなく、デプロイ、運用、サポートまでを一貫して担うスタイルです。

この体制の最大のメリットは「ドメイン理解の深化」にあります。作り手と顧客の間の層を減らし、開発者自身が顧客解像度を高めることで、本当に必要な機能を最適な形で届けることができます。
書籍「小さなチーム、大きな仕事」でも、顧客との関わりについて以下のように述べられています。

チーム全員が顧客とかかわりを持たなければならない。これこそ、チームが顧客の気持ちを理解する唯一の方法だ。
客の意見を聞くのは、商品の強みと弱みを知る一番の方法だ。顧客と作り手の間に人が多いほど、顧客の声は歪んだり失われたりしていく。
(引用: 「小さなチーム、大きな仕事」 P.230)

しかし、実際に複数のチームが並行して走るマルチプロダクト体制でこれを運用していく中で、私たちは「フルサイクル開発のリアル」な課題に直面することになりました。

1. 運用コスト増加による開発生産性の低下


1つ目は、「ドメイン理解に集中したいが、運用コストに時間を奪われる」というジレンマです。

書籍Platform Engineeringでは、ソフトウェアのコストについて以下のような現実が指摘されています。

ソフトウェアの生涯コストの内、少なくとも60 ~75%は初期開発後に発生し、その約4分の1は、移行やその他の適応メンテナンスにのみ費やされてる
(引用: 「PlatformEngineering -Chapter 1. Why Platform Engineering Is Becoming Essential- 」)

フルサイクル開発ではチームが運用責任も負うためプロダクトの機能が増えるほど、この「初期開発後に発生するコスト」がチームに重くのしかかります。

特に深刻なのは、このコスト増が1つのチームだけでなく、並行して動く複数のチームそれぞれで同時多発的に発生してしまう点です。 組織全体で見ると、運用に奪われるリソースがチームの数だけ掛け算で膨れ上がっていく構造になっていました。

2. チーム間での機能重複

2つ目は「車輪の再発明」です。

各チームが高い自律性を持って動く一方で、認証、通知、決済といった本来共通化できるはずの機能や振る舞いが、チームごとに個別に実装されてしまうケースが発生してしまいます。これは開発リソースの浪費であるだけでなく、プロダクト全体でのUXや仕様の不整合を招く要因にもなります。

これらの課題に対して、私たちは「アプリケーション機能開発」と並行して、課題を解決するための「共通基盤開発」を進めています。その基盤開発の核となる技術選定が、Full-Stack TypeScriptです。

その課題に対する技術戦略:Full-Stack TypeScript

前述の課題を解決するための技術基盤の主軸として Full-Stack TypeScript を採用しています。

Full-Stack TS採用の期待と懸念

すでにフロントエンド/バックエンド開発で得られていた「生産性の高さ」を基盤開発でも再現したいためTypeScriptを採用したいモチベーションがありました。

具体的には、以下の4点を期待しています。

  1. FE/BE開発で得たFull-Stack TSの生産性の再現
  2. AIとの親和性: AIコーディング支援ツールの恩恵を最大限に受ける。
  3. 静的型付け: 連携システム間で型定義を共有し、堅牢なインターフェースを構築する。
  4. コンテキストの共有: 同じ言語を用いることでコンテキストが分断されず目的単位での開発をスムーズにする。

一方で、「共通基盤としての高い信頼性要求に応えられるか」「事例が少ない中でトラブルシューティングが可能か」といった懸念もありましたが、それ以上にエコシステムがもたらすメリットが勝ると判断しました。

エコシステム選定理由(モノレポとの親和性)


技術選定のもう一つの大きな背景は、モノレポ(Monorepo)構成との親和性です。
旧システムではバックエンドがPython、フロントエンドがTypeScriptなので技術要素を増やして認知負荷を上げたくなかったこと、そしてTypeScript周辺のモノレポツールが充実していることが決め手となりました。

書籍Googleのソフトウェアエンジニアリングでも、大規模組織におけるモノレポの優位性について以下のように述べられています。

単一のリポジトリー(モノリポ)を持つ大規模組織は、ソースコントロールのポリシーを用いて、別々のリポジトリーを使う場合と比べ圧倒的に先までスケールアップ可能であり、それがGoogleのアプローチである。
(引用: 「Googleのソフトウェアエンジニアリング」 P.498)

このアプローチを実現するために、BunBiomeといった最新のTypeScriptエコシステムを活用し、複数プロダクトの連携を支える基盤構築に着手しました。

技術基盤の深掘り

ここからは共通基盤の解像度を1段階具体的にしてお話を進めます。
書籍Platform Engineeringの用語を引用して以下の2種類のプラットフォームをそれぞれ紹介します。

  1. 共通サービスプラットフォーム(Integration/Shared Services Platforms)
  2. コアプラットフォーム(Core/Infrastructure Platform)

1. 共通サービスプラットフォーム


アプリケーションの共通機能を提供する「共通サービスプラットフォーム」についてです。

具体的には、決済、通知、メッセージ配信、アカウント管理など、どのプロダクトにも必要不可欠な機能群を指します。
これらの基盤は単に機能を共通化するだけでなく以下を目的としています。

  • 横断的なドメイン知識の深化
  • 一貫したユーザー体験の提供
  • 基盤同士のデータ連携による新たな価値づくり
  • 技術的複雑性のカプセル化

OpenAPIを軸とした型駆動連携


複数の基盤とプロダクトが連携するアーキテクチャにおいて懸念されるのがインテグレーションの不整合です。書籍Googleのソフトウェアエンジニアリングには、継続的インテグレーションについて以下のような記述があります。

アプリケーションを破綻させるコード変更は、そのアプリケーションのプロジェクトがある直接のコードベース内に存在している見込みは低く、ネットワーク経由の呼び出しの反対側にある疎結合したマイクロサービス内にある見込みの方が高い。
(引用: 「Googleのソフトウェアエンジニアリング」 P.555)

この問題に対処するために、私たちはOpenAPIを用いたスキーマ駆動開発を徹底しています。

  1. Interfaceの定義: 各基盤のIFをOpenAPIで厳密に定義する。
  2. コード自動生成: Orvalを活用し、Client/Server双方のソースコードを自動生成する。
  3. 依存の明示: 使用するPackageにClientを出力し、依存先を明示的に管理する。

API定義の変更と依存するClientの更新タイミングを強制することで、ネットワーク越しの疎結合な連携であっても、コンパイル時に不整合を検知できる堅牢なシステムを構築しています。

技術的複雑性のカプセル化

共通基盤のもう一つの重要な役割は、個別のプロダクトチームがプロダクトの価値開発に集中できるよう、技術的複雑性を基盤側に閉じ込めることです。
ここでは2つの基盤を例に挙げます。

事例1:通知基盤(高負荷対策の隠蔽)


「通知基盤」では、システム全体から発生する大量の通知リクエストを一手に引き受けています。
直近の実績では1日最大40,000件、スパイク時には秒間105件のリクエストを処理しており、将来的にはすべての通知を統合し、1日100,000件規模になる想定です。

こうしたスパイクへの対応、流量制御、リトライ処理といった複雑な非機能要件を基盤側で吸収することで、利用するプロダクト側は流量を気にせず通知リクエストを投げることができる状態を作っています。

事例2:メッセージ配信基盤(最新エコシステムの活用)


「メッセージ配信基盤」では、イベント駆動アーキテクチャを採用し、疎結合でスケーラブルな構成をとっています。
インフラにはAWS CDK、コンピュートリソースにはLambdaを採用していますが、ここでもFull-Stack TSの利点を活かしています。

具体的には、Lambdaのデプロイパッケージ作成にBunを活用しています。bun build コマンドを用いてターゲットをNode.jsとしてビルドすることで、高速なビルドと実行ファイルの最適化を実現しました。

2. コアプラットフォーム

二つ目の基盤定義は、開発環境やインフラそのものを支える「コアプラットフォーム」です。

レバレッジによる開発生産性向上

Platform Engineeringの価値は「レバレッジ」にあります。基盤チームの活動がテコの原理のように作用し、組織全体の生産性を大きく引き上げることを目指しています。
書籍Platform Engineeringでは、その価値について以下のように述べられています。

ビジネス価値を作成する際の生産性を向上させることと、チーム間の重複作業を排除することでエンジニアリング組織を効率化すること
(引用: 「PlatformEngineering -Chapter 1. Why Platform Engineering Is Becoming Essential- 」)

私たちは、この「ビジネス価値向上」と「重複作業の排除」の両輪を回すために基盤整備を行っています。

依存関係の統制と共通作業の削減

特に注力しているのが、メンテナンスコストの削減です。

セキュリティパッチの適用に必要なアップグレード、ソフトウェアの再テスト、基盤となる依存関係の新しいバージョンへの移行など、ソフトウェアのメンテナンスには多くのエンジニアリング時間がかかります。
(引用: 「PlatformEngineering -Chapter 1. Why Platform Engineering Is Becoming Essential- 」)

これらのコストを個別のプロダクトチームが背負い続けるのは困難です。また、書籍Googleのソフトウェアエンジニアリングでも指摘されている通り、依存関係の管理は規模拡大とともに深刻な問題となります。

オープンソフトウェア(OSS) モデルが新たな要因向けて発展と拡大を続け、また人気がある様々なプロジェクトの依存関係グラフが時間の経過とともに拡大を続けていくのに伴い、おそらくは依存関係の管理が、ソフトウェアエンジニアリングポリシー内における最重要問題となっていく。
(引用: 「Google のソフトウェアエンジニアリング」 P.498)

そこで私たちは、コアプラットフォーム側で以下のような作業を一元管理し、重複作業を徹底的に排除しています。

  • ライブラリのバージョンアップ管理
  • Linter / Formatter / tsconfig のルール統一と配布
  • CI/CDパイプライン整備
  • AIコンテキスト整備
  • 共通UIコンポーネントの提供

モノレポ構成と技術選定背景

これらを実現するための具体的な技術構成として、私たちはモノレポ構成を採用しました。
TypeScript, Biome, commitlint などを採用していますが、その中でも特に技術的な挑戦としてBunを全面的に導入しています。

Bunによる基盤整備

Bunの技術選定のポイントは、開発体験の良さとパフォーマンス、そして依存管理の厳格さです。

テストランナーやパッケージマネージャーとしての高速性はもちろん、Workspace機能による厳格なライブラリ依存関係管理を評価しています。また、bun buildによってLambda用の実行ファイルをシングルバイナリ化し、サイズ圧縮にも貢献しています。「どうしても行き詰まったらNode.jsに移行可能」という互換性も安心材料の一つです。

workspace戦略と横断script


ディレクトリ構成は、Rootディレクトリに共通設定を配置し、各Package(アプリケーションや共通基盤)がそれを継承する形をとっています。

  • 設定の継承: tsconfig.jsonbiome.json はRootの設定を継承(extends)することで、各Packageの設定ファイルを数行のミニマムな構成に保っています。
  • 横断Scripts: package.json のscriptsを使い、Workspace横断で一括実行したい処理(全テストの実行、全ビルドなど)を管理しています。コマンド名をPackage間で統一することで、開発者の認知負荷を下げています。

取り組み成果の整理

これまでのFull-Stack TSによる基盤開発の成果を、課題・対策・効果の観点で整理します。

課題 対策 効果
① 複数チームで統一したい振る舞いや機能の重複・繰り返し 共通サービスプラットフォーム
/コアプラットフォーム
・プラットフォームの再利用による機能の立ち上げ速度向上
・共通基盤自体のプロダクト価値
・基盤同士のデータ連携
・技術的複雑性のカプセル化
② 開発と比例する運用コスト増加によるスピード低下 コアプラットフォーム ・設定ファイルの共有
・横断スクリプト
・増幅する運用コストの最小化
③ 共通サービスプラットフォームを含めた複数プロダクトの依存解決とインテグレーション コアプラットフォーム ・モノレポによる複数プロダクトのインテグレーション
OpenAPIでのスキーマ駆動開発による厳密なIFと型での依存管理

今後の課題と展望


順調に進んでいる一方で、新たな技術課題も見えてきています。

  1. Dockerのimage sizeの肥大化: 初期700MB程度だったものが、運用と共に2.6GBまで肥大化するケースがありました。二度に渡り1.5GBまで削減しましたが、継続的な監視と対策が必要です。
  2. Bunの互換性と安定性: いくつかのライブラリで bun compile が失敗したり、マイナーアップグレードでテストが落ちたりする事象が発生しています。調査と解消に一定の運用負荷がかかっており、エコシステムの成熟を待ちつつ、知見を蓄積していく必要があります。

おわりに

MOSHでは、「ドメイン理解」と「技術的レバレッジ」の両方を追求することで、クリエイターに最良の価値を最速で届けることを目指しています。
Full-Stack TSでのマルチプロダクト基盤開発は、まだ道半ばですが、少人数で複数の基盤を効率的に運用するための強力な武器となっています。今後もこの構成を磨き上げ、エンジニアリング組織全体の生産性を高めていきたいと考えています。

フルサイクルなマルチプロダクト開発にレバレッジを効かせるコアプラットフォームと、新たな価値を作る共通サービスプラットフォームにFull-Stack TSをフル活用している紹介でした。

明日は、tskaigiでも発表した同じプロダクティビティチームの安達さんです!よろしくお願いします〜!

MOSH

Discussion