成長を続けるヘルスケア・栄養ビジネスにおいて、単一のバックエンドでは処理しきれなくなっていました。AIチャットボットのトラフィック、大量のウェアラブルデータ取り込み、そして日常的なAPIリクエストがすべて同じリソースを競合し、システムのスケーリングを困難にし、デプロイメントにリスクをもたらしていました。私たちは、これをAWS上で動作する、単一のAPIゲートウェイの背後に編成された、独立してデプロイ可能な集約型サービスに再設計しました。
課題
- すべてのタスクを処理する単一のコードベース。 あるワークフローには、ユーザー管理、AIチャットボットの推論、レシピ、ヘルスケアデータ分析が含まれていました。いずれか一分野でスパイクが発生するとプラットフォーム全体が劣化し、変更のたびにシステム全体を再デプロイする必要がありました。
- 非常に異なるリソースプロファイル。 LLMを活用したチャットボットのリクエストは、CPUとメモリを大量に消費し、バースト的です。ウェアラブルデータの取り込みは書き込みが多く、継続的です。コアのCRUD APIは軽量で一定です。これら3つすべてを1つのサーバーでサイジングすることは、一部のワークロードに過剰な費用を支払い、他のワークロードを飢えさせることを意味していました。
- 独立したスケーリングとデプロイメント。 チームはコアAPIに影響を与えることなくAIワークロードをスケーリングし、他のドメインを危険にさらすことなく1つのドメインに変更を出荷する必要がありました。
単一の安全な入口点。 複数のバックエンドサービスにもかかわらず、クライアント(モバイル、ウェブ、管理)は、一貫した認証されたインターフェースを必要としていました。内部のサービス構成が外部に漏れることは許されません。
私たちのソリューション
私たちは、プラットフォームを3つの特化したNestJSサービスに分割し、AWS Application Load Balancerの背後に配置しました。メインサーバーはAPIゲートウェイ兼オーケストレーターとして機能します。メインサーバーは認証とコアとなるドメインを管理し、認証されたRESTを介してチャットボットおよびヘルスケアマイクロサービスに専門的な作業を委譲します。共有されたデータおよびメッセージング層により、サービスは疎結合でありながら一貫性を保ちます。

アーキテクチャ
- メインサーバー (NestJS) — APIゲートウェイ兼オーケストレーター:認証、ユーザー、目標、レシピ、スケジューリング、通知。すべてのクライアントは単一の公開エントリーポイントを持ちます。
- チャットボットマイクロサービス (NestJS) — LangChain/LangGraphを介したAzure OpenAI (GPT-4o) を搭載したAI会話サービスで、レシピや知識検索のためにElasticsearchをバックエンドとするRAGを使用します。
- ヘルスケアマイクロサービス (NestJS) — ウェアラブルおよび手動のヘルスケアデータ(Apple Health、Health Connect)を取り込み、集約し、分析機能を提供します。
- AWS ECS Fargate は、3つのコンテナ化されたサービスをそれぞれ独自のCPU/メモリサイジングとスケーリングポリシーで実行します。
- Application Load Balancer はHTTPSを終端し、パスベースで適切なサービスにトラフィックをルーティングします。
- 共有データ層 — MongoDB Atlas(プライマリストア)、Redis(キャッシュ/セッション)、Elasticsearch(検索)、ActiveMQ(非同期通知配信)。
CI/CD — DockerマルチステージビルドがAmazon ECRにプッシュされ、ローリングアップデートとしてECSにデプロイされます。
主な機能
1. オーケストレーターパターン。 メインサーバーはクライアントに公開される唯一のサービスです。すべてのリクエストを認証し、内部でサービス間呼び出しを行います。これにより、バックエンドのトポロジーはプライベートに保たれ、クライアントとの連携はシンプルになります。
2. 認証されたサービス間呼び出し。 サービス間通信は、共有HTTPクライアントを介したRESTで行われ、サービスごとのBearer APIキーで保護されています。
// メインサーバーがAIリクエストをチャットボットマイクロサービスに委譲する const reply = await this.microserviceClient.post( this.chatbotApiKey, // サービスごとのBearerキー `${this.chatbotUrl}/chat`, { user, question, sessionId, attachment }, ); |
3. ワークロードごとの独立したスケーリング。 各サービスは独自のサイジングを持つ個別のFargateタスク定義です。メモリを大量に消費するチャットボットサービスは、軽量なコアAPIとは独立してスケーリングするため、AIトラフィックのスパイクが日常的なリクエストを枯渇させることはありません。
4. 組み込みのレジリエンスを備えた適切なサイジングのAIサービス。 チャットボットサービスは複数のAzure OpenAIキーをローテーションし、レート制限やエラー時に自動的にフェイルオーバーします。これにより、負荷がかかってもAI機能は応答性を維持します。
5. 非同期メッセージングによる通知。 ActiveMQの遅延キューが時間ベースの通知やリマインダーをリクエストストリームから分離するため、通知の配信がコアAPIトラフィックを妨げたり遅延させたりすることはありません。
6. 繰り返し可能で分離されたデプロイメント。 ECRからECSまで、各サービスは独自のDockerイメージとして出荷されます。ヘルスサービスへの変更は、単にヘルスサービスを再デプロイするだけで済みます。これは、ヘルスチェック済みのローリングアップデートによる迅速で低リスクなリリースを可能にします。
7. 一貫性のあるクライアント契約。 モバイル(React Native)と管理ダッシュボードはすべて、単一のロードバランシングされたHTTPSエントリーポイントと通信します。マイクロサービスへの内部的な分割は、それらからは見えません。
結果
- 今日では、AIチャットボット、ヘルスケアデータ、コアAPIのワークロードは個別にスケーリングされ、どのタスクも他のタスクを劣化させることはありません。
- 各サービスは独立してデプロイされ、リスクの高いプラットフォーム全体のリリースを、高速で隔離されたアップデートに変えます。
- コンピュートはサービスごとに適切にサイジングされ、単一の汎用サーバーによる過剰なプロビジョニングを排除します。
- 単一の安全でロードバランシングされたエントリーポイントにより、クライアント連携はシンプルに保たれ、バックエンドはプライベートかつモジュラーな状態を維持します。
技術スタック
NestJS · TypeScript · Node.js 20 · Azure OpenAI (GPT-4o) · LangChain · MongoDB Atlas · Redis · Elasticsearch · ActiveMQ · AWS ECS Fargate · Application Load Balancer · Amazon ECR · Docker
その他のブログ
1. AWS ECSで動画処理ワークロードをスケーリングする方法
2. AWS ECRを使用してコンテナイメージを管理・デプロイする方法

