SpaceCoreを陰で支えているバックエンドの紹介(後編)

~100万デバイス接続を支えるスケーラブル設計~

みなさんこんにちは!プロダクト開発グループに所属している堀井です。

前編では、SpaceCoreのバックエンドを構成する技術スタック(Rails / Lambda / Firebase / IaC / CI/CD)を紹介しました。後編となる本記事では、「2028年までに100万デバイス接続」 というアクセルラボのVISIONを実現するために、このアーキテクチャがスケーラビリティの観点からどのように設計されているかを深掘りします。


1. なぜスケーラビリティが重要なのか

SpaceCoreが管理する対象は「物件 → 部屋 → IoTデバイス」という階層構造を持ち、1部屋あたりスマートロック・カメラ・センサー・ゲートウェイなど複数のデバイスが紐づきます。

100万デバイスという目標は、単純なAPIリクエスト数の増加だけでなく、以下の課題を同時に解決しなければなりません。

イベントの爆発的な増加 各デバイスはオンライン/オフライン状態の変化、センサー検知、ドアの開閉など多様なイベントを発生させます。デバイス数に比例してイベント量も増加するため、基幹システムがそのまま受け取る設計ではすぐに限界を迎えてしまいます。

多ベンダーとの同時通信 現在、11以上のIoTベンダーとの同時通信が必要であり、各ベンダーのAPIレスポンス時間やスループットはバラバラです。

生活インフラとしての可用性 スマートロックの解錠やセキュリティアラートなど、遅延や停止が許されない操作が存在します。スケールアップの過程でも可用性を損なうわけにはいきません。


2. Lambda × イベントドリブン設計:スケールの核心

2-1. デバイスイベントの流れ

SpaceCoreのLambdaは大きく2つのシステムで構成されています。

ひとつはレガシー層です。Pythonベースの単一Lambda関数(Monolithic Lambda / Lambdalith)として、200以上のAPIエンドポイントをルーティングし、複数のベンダーAPIへの統一的なアクセス層を提供しています。

もうひとつは次世代層です。Node.js / TypeScript / Koaベースの十数個の独立したLambda関数で構成されるServerless Frameworkアプリケーションです。レガシー層と役割は同じですが、アーキテクチャを刷新しており、将来的にはレガシー層のエンドポイントをこちらへ段階的に移行していく予定です。

図1.デバイスイベントフロー

2-2. Lambdaがスケールする理由

機能ドメインごとの関数分離 次世代層は機能ドメインごとに十数個の関数に分離されています。デバイス操作にトラフィックが集中しても、ルール管理やIRリモコンの関数には影響しません。関係する関数だけをスケールさせれば済むため、リソース効率が高い設計です。

コールドスタートの最小化 各Lambda関数は初回呼び出し時にDIコンテナを初期化し、以降のウォームインスタンスでは再利用します。これにより、コールドスタートの影響は初回のみに限定されます。

長時間処理のStep Functions委譲 デバイスペアリングやファームウェア更新など、Lambdaのタイムアウト上限を超える可能性がある操作は、AWS Step Functionsに委譲する非同期パターンを採用しています。

2-3. 疎結合設計がスケールを助ける

次世代層では共通インターフェースを通じてベンダー固有のロジックをランタイムで選択する設計を採っています。11以上のIoTベンダーがそれぞれ独立したパッケージとして実装されており、新ベンダーの追加はDIコンテナへのバインディング追加のみで完了します。

Rails側でも同様に、ゲートウェイの種類でベンダー差異を吸収しています。Lambdaだけでなく、システム全体が一貫してプラグインアーキテクチャの思想で設計されています。

100万デバイスへの道のりは、台数の増加だけでなく対応ベンダー・デバイス種別の多様化も意味します。この設計により、新ベンダーへの対応コストを最小限に抑えることができます。


3. Railsアプリケーションのスケール戦略

3-1. ECS × コンテナによる水平スケール

Rails基幹システムは、ユーザーや管理会社からのアクセスを直接受け付ける「公開API+管理画面システム」と、そこからのみアクセスを許可しセキュアな情報を扱う「内部APIシステム」の2つに分離され、それぞれ独立したECSサービスとして動作します。WebサーバはEC2ベースのECSオートスケーリング対象として、トラフィック増加に応じて自動的にスケールアウトします。バッチ処理は基本的にFargateで必要なときだけ起動することでリソースを節約しています。ただし、Fargateは特定の時間帯にリソースが枯渇し、タスクが正常に起動しないケースがあります。実際に複数バッチの実行時間が重なりリソース不足が発生した経験から、バッチごとに実行時間帯をずらす対応を行いました。また、確実な実行が求められる処理にはEC2起動タイプを指定するなど、用途と信頼性要件に応じてEC2とFargateを使い分けています。

図2.Rails ECSタスク構成とスケール戦略

3-2. 非同期処理による負荷の平準化

Sidekiq + Redisをジョブキューとして活用し、「今すぐ処理しなくていいこと」をキューに逃がすことでスパイクトラフィックを吸収しています。IoTゲートウェイのルール操作やデバイス登録の非同期化などが具体例です。デバイス未検出時の自動リトライなど、IoTならではの不安定な通信環境への対応も含まれています。

また、ゲートウェイのオンラインイベントではRedisのアトミック操作で重複イベントを排除し、バックエンドへの過負荷を防いでいます。デバイス数が増えるほど、こうした細かな工夫が効いてきます。

3-3. Fargateタスクによるバッチ処理の分離とシャーディング

重い処理はFargateタスクとして起動し、メインのAPIサービスへの影響を完全に排除しています。さらに、MODシャーディングによる並列分散も行っています。たとえば入居者のオフライン処理では複数のFargateタスクを同時起動し、IDのMOD演算でタスクごとに処理対象を分散することで、大量データの処理時間を短縮しています。


4. リアルタイム性とスケールの両立:Firebaseの役割

FCMによるPUSH通知では、セキュリティアラートやセンサー検知などのIoTイベントをiOS/Android両プラットフォームへリアルタイムに送信します。Firebase Realtime Databaseによるチャットでは、管理会社と入居者間のメッセージをリアルタイムで同期します。

Firebaseに通知・チャット基盤を委ねることで、Railsの責務をビジネスロジックとデータ永続化に限定しています。数十万ユーザーへの同時通知やリアルタイム配信というスケール課題をGoogleのインフラに任せられることは、開発・運用コストの観点からも大きなメリットです。


5. インフラ・CI/CDがスケールを支える

ECSのタスク定義はプレースホルダーを含むテンプレートとして管理され、CI/CDパイプラインで環境固有の値に置換されます。開発・ステージング・本番を同一テンプレートから生成できるため、スケールアップ時に新環境を追加してもズレが生じません。

Lambdaのデプロイは「バージョン発行 → エイリアス切り替え」パターンを採用しており、問題発生時の即時ロールバックが可能です。ECSのWebサービスはBlue/Greenデプロイでダウンタイムゼロを実現しています。本番デプロイにはSlack通知付きの承認ステップが挟まれており、影響範囲が広がるほどこの安全弁の価値が増します。

図3.CI/CDパイプライン


おわりに

前編・後編を通じて紹介してきたように、SpaceCoreのバックエンドは 「Lambda × イベントドリブン」「ECS × 水平スケール」「Firebase × マネージド通知」「IaC × 宣言的管理」 という4つの柱で構成されています。これらは単なる技術的な選択ではなく、100万デバイス接続という事業目標から逆算された合理的なアーキテクチャ判断です。

課題はまだ多くありますが、それ自体がエンジニアとして挑戦しがいのあるテーマです。このアーキテクチャを一緒に進化させるエンジニアを募集しています。ぜひ採用ページよりご応募をお待ちしております!

📩 お問い合わせ・採用情報

本ブログを読んでいただきありがとうございます。 もし内容にご興味を持っていただけましたら、以下よりお気軽にお問い合わせ・ご応募ください。

スマートホームの導入をご検討中の企業様へ:

👉お問い合わせ - SpaceCore(スペースコア)

アクセルラボへご興味を持たれたみなさまへ:

アクセルラボでは採用を強化しています。 私たちの技術やビジョンに共感し、スマートホームの未来を共に創っていきたい方のご応募をお待ちしています。

👉 株式会社アクセルラボ 採用サイト - ACCEL LAB RECRUIT-