ECS (コンテナ) から Lambda への移行事例
株式会社ギークプラス / 今村優太
CTO・VPoE / CTO / 従業員規模: 51名〜100名 / エンジニア組織: 11名〜50名
| ツールの利用規模 | ツールの利用開始時期 | 事業形態 |
|---|---|---|
| 11名〜50名 | 2025年5月 | B to B |
| ツールの利用規模 | 11名〜50名 |
|---|---|
| ツールの利用開始時期 | 2025年5月 |
| 事業形態 | B to B |
アーキテクチャ

アーキテクチャの意図・工夫
- AWS Lambda は 15 分までの実行時間制限があるため、各バッチで処理しなければならない量を事前に計算したうえで、コンテナによる実行か AWS Lambda による実行かを切り替えています。
- AWS Lambda のコールドスタートの時間を抑えられるよう、関数を分けるのではなく、バッチ処理をすべて共通の関数で実行し、内部で目的のバッチに応じて起動する処理を切り替えています。SnapStart でコールドスタートの時間を抑制するのみならず、起動済みの Lambda インスタンスが使い回されるよう、ウォームスタートで Lambda が起動される確率を高めています。
導入の背景・解決したかった問題
導入背景
ツール導入前の課題
弊社はサプライチェーンマネジメントを支える SaaS サービス skylaa を運用しており、既存のバッチ処理のコンポーネントとして Java / Spring Boot によるファイル連携基盤が存在しました。業務ロジック自体は安定しており、日々のオペレーションを確実に支える重要な役割を果たしていましたが、一方でその実行基盤については、次第に課題が顕在化していきました。
当時、バッチ処理は ECS on EC2 上で実行されており、実際の処理が行われていない時間帯であっても、EC2 インスタンスを常時起動しておく必要がありました。これは、JVM を含んだ Java のコンテナイメージのサイズが非常に大きく、イメージキャッシュを効かせるための環境としての選択肢が AWS では ECS on EC2 に限られたためです。弊社のバッチ処理は、ひとつのバッチ単位を細かく分割しており、その分割ごとにコンテナが起動されるため、イメージキャッシュが効いていない場合にイメージのダウンロードのみに 1 分近くの時間を要することがありました。
AWS でコンテナ基盤といえば Fargate が有名かと思いますが、Fargate のイメージキャッシュの要望はすでに 6 年以上オープン (link) のままであり、大規模なイメージを取り扱う対策としては SOCI (Seekable OCI) を試すことが推奨されています。弊社では SOCI + Fargate の構成も試しましたが、期待された程のパフォーマンス改善効果を得ることはできませんでした。
そのため、コストや起動時間といった非機能要件が、実行基盤の制約によって十分に満たされていない状態にありました。
どのような状態を目指していたか
これらの課題はアプリケーションそのものの品質や設計に起因するものではありませんでした。当時の Java バッチは業務に深く組み込まれ、長期間にわたり安定稼働しており、言語やフレームワークの変更などを伴うような大きな改修を行うことはリスクが高い状況でした。そのため、既存のアプリケーション資産を最大限に活かしながら、これらの課題を解消したいという問題意識がありました。
そのため、以下の 2 点が満たせることを理想状態と定義し、Java および Spring Boot で構成されたバッチ処理をコンテナから AWS Lambda へ移行することを計画しました。
- 5 から 7 個程度のバッチ処理の組み合わせで実行されるワークフローが、平均 1 - 2 分程度で完了すること
- バッチ処理に要する計算リソースのコストが、実際に計算に要した時間に比例した状態になること
比較検討したサービス
- AWS Fargate
比較した軸
まだ立ち上がったばかりの SaaS であり、サービスの性質上大量のリクエストを捌くよりも少数のリクエストがまとまって送信、処理されるようなワークロードであったため、まずはコスト効率よく高速にリクエストを捌くにはどうすればよいかを検討しました。
そのため、計算処理を行うインスタンスを常駐化させることよりも、サーバーレスに「必要なときに必要なリソースを立ち上げる」ことに特化させる方がメリットが大きいと判断しました。
選定理由
AWS Lambda はコストの観点で無料枠が大きく、サーバーレスのサービスであるため利用時間と料金が純粋に比例することが大きな決め手でした。
また、SnapStart と呼ばれる機能が Java アプリケーションの場合は無料で利用することができる点も選定のポイントになりました。サーバーレスなインスタンスである以上、起動時にある程度のオーバーヘッドは必ず発生しますが、SnapStart と呼ばれる機能を利用すると、実行状態のスナップショットをメモリ保管させておくことで起動を高速化することが可能です。
導入の成果
改善したかった課題はどれくらい解決されたか
導入にあたっては Spring Cloud Function と呼ばれる、Spring Boot プロジェクトをサーバーレスで動かすライブラリを、アプリケーションの wrapper として採用しました。これにより、アプリケーションの実装は大きく変更することなく、もともと課題として抱えていたコストとパフォーマンスの課題をクリアすることができました。
ハンドラーの層のコードについては、弊社 技術ブログの記事 もあわせてご確認ください。
どのような成果が得られたか
コストとパフォーマンスはもとより、耐障害性とスケーラビリティがサービスに組み込まれている分、本来取り組みたいビジネス的な付加価値の開発へ取り組みやすくなったことは、非常に大きな成果だと思います。通常は Availability Zone の分割や処理負荷に応じたスケーリングルールを取り決める必要がありますが、AWS Lambda はリージョン単位での可用性を提供し、かつ実行される処理の負荷に応じてインスタンスが容易に増減するため、これらの懸念を AWS に委ねることが可能となりました。
導入時の苦労・悩み
これまでは ECS コンテナが起動され終了、破棄される構成でしたが、AWS Lambda の場合はある程度時間をおかないと同じインスタンスが使い回されることになります (ウォームスタートと呼ばれる)。そのため、Static 変数などインスタンス間で共有され得るようなメモリ領域を利用していないか確認が必要でした。幸い、今回のバッチアプリケーションでは、そのように利用されている変数はありませんでした。
- 仮にインスタンス間で共有される変数があったとしても、2025 年の re:Invent で発表された テナント分離 の機能を組み合わせれば、回避はできたと考えられますが、当時はまだ未発表の機能でした。
サーバーレスに RDBMS を取り扱う場合の対策として RDS Proxy を検証し、データベースへの並列接続をまとめることができないか試しましたが、1 クエリあたり平均 5 ミリ秒程度のレイテンシーが発生することで、目標とするパフォーマンスを達成することができず、またクエリの内容を変更するにはアプリケーション本体への改修が必要であったことから、導入を見送りました。また、アプリケーションの中で Prepared Statement を利用している場合、RDS Proxy の製品仕様上、データベースへの並列接続をまとめる効果を得られずコネクションのピン留めが発生する (link) ことも導入を見送った一因となりました。
導入に向けた社内への説明
上長・チームへの説明
まずは簡単な PoC を行い、もっとも構成がシンプルなバッチ処理から置き換えが可能か検討しました。PoC の結果、平均的な実行時間が 1/6 程度になるなど有意なパフォーマンスの向上が見込まれたこと、およびコスト見積もりの上では 1/4 程度まで抑えられることから、移行に踏み切りました。
活用方法
- アプリケーションのバッチ処理全般で利用しています
よく使う機能
- SnapStart
- VPC 接続
- Lambda Layers
- CloudWatch Logs へのログ出力
- StepFunctions からの実行や SQS トリガーによる非同期実行
ツールの良い点
- バッチの計算リソースに要していた課金が限りなく抑えられるようになったこと
- バッチの起動にこれまでコンテナイメージのダウンロードの時間としておよそ 1 分ほどかかっていたオーバーヘッドをほぼゼロに短縮できたこと
- Java / Spring Boot の構成で AWS Lambda にバッチ処理を載せ替えることは、Spring Cloud Functions を利用することで既存アプリケーションを大きく変更せずに達成できること
ツールの課題点
- データベースへのコネクションが、並列起動される Lambda のインスタンスの分だけ発生するため、負荷の高いワークロードではデータベースの Max Connections に気をつける必要がある
- アプリケーションとしてデプロイできるパッケージサイズには 250 MB という最大サイズが設けられているため、これを超える場合はコンテナベースの AWS Lambda に移行する必要がある
ツールを検討されている方へ
- Lambda の最も大きな制約として 15 分という実行時間の制限がありますが、今回の我々のアーキテクチャでは、入力されるサイズにより従来のコンテナ起動か、Lambda 起動か変更されるように設計しました。そのため、事前に実行時間がある程度見積もることができるのであれば、このように二通りの実行パスを用意し、StepFunctions などで切り替えるとよいかと思います。
今後の展望
Lambda を問わずサーバーレスなアーキテクチャを利用するときに問題となるのが、RDBMS を利用する際の並列接続ですが、最近は Aurora DSQL のような New SQL に該当する製品も AWS で出てきているので、このような最新の技術を試験的に取り入れつつ、サービスの成長に応じてより多くの負荷に耐えられるようなシステムを設計していきたいと思います。
株式会社ギークプラス / 今村優太
CTO・VPoE / CTO / 従業員規模: 51名〜100名 / エンジニア組織: 11名〜50名
よく見られているレビュー
株式会社ギークプラス / 今村優太
CTO・VPoE / CTO / 従業員規模: 51名〜100名 / エンジニア組織: 11名〜50名
レビューしているツール
目次
- アーキテクチャ
- 導入の背景・解決したかった問題
- 活用方法



