🐕

大してアクセスないサイトにECSはオーバースペック

に公開
9

概要

私が業務で触ったシステムは全部ECSでホスティングされています。ECSは動いてる間中ずっと課金されます。しかしlambdaはリクエスト~レスポンス構築完了 の時間しか課金されません。よって大してアクセス数がないサイトや、CloudFrontのキャッシュが効きまくるサイトはECSが暇をしている時間が長いことになり、オーバーパワーです。その時間課金されないlambdaで作れば安いことになります。lambdaなんかで複雑なサイトが作れるかよという話になりますが、aws amplifyなどを使えばモダンなフレームワークで作ったアプリを勝手にlambdaでデプロイしてくれるため、そんなに遠い夢ではありません。そこで今回はaws lambdaとECSの料金を比較し、損益分岐点を探してみます。

想定するwebサービス

ニュースサイトのような、記事が読めて楽しいね、みたいなサイトを想定します。

3Dモデルや動画ファイルみたいな重いファイルはない、ルート検索や検索のような重い処理もない、ゲームのようなリアルタイム性もない、といった計算量的には楽なサイトです。もし例に挙げたようなきつめの要求があるなら、計算がそこそこ必要なのでlambdaとかは選択肢にも上げないほうがいいと思います。

それぞれの構成

lambda

lambda関数1個しか呼び出されないものとします。aws amplifyでデプロイしたときどのような形のlambdaがデプロイされるかはわかりませんが、以下の理由から1個だけということにします

  • 私が業務で携わっているwebサービスではサブプロセスを使っていない
  • 重いファイルも複雑な処理も必要ない

そのほかのパラメータは以下とします。

パラメータ 理由
CPUアーキテクチャ Arm x86より安いから
実行秒数(s) 3 先人の経験則。応答時間がこれ超えたら使ってくれる人が激減するらしいので、何としてもここまでに収めるとする。
メモリ(GB) 2 今仕事で携わってるシステムの半分の量。そっちはFargateなので並列にレスポンスをさばいている。lambdaは複数呼び出されたら複数個立ち上がるので、1リクエスト処理するだけでいい=並列処理する分のメモリはいらない
エフェメラルストレージ(GB) 10 lambdaに指定できる最大値。かなり余裕を持っている

ECS

コンテナ1個で固定とします。
オートスケールするのがECSのいいところですが、オートスケールするほど負荷が高いシステムならlambdaと比較する必要はありません。どう考えてもECSをそのまま使ったほうがいいです。

そのほかのパラメータは以下とします。

パラメータ 理由
CPUアーキテクチャ Arm x86より安いから
vCPU(単位なし) 1 今仕事で携わってるシステムと同じ量
メモリ(GB) 2 今仕事で携わってるシステムと同じ量

料金の計算

計算1:計算リソースの料金だけ比較

まず純粋に計算リソースを何で作るかだけ比較します。ECSならAPI GatewayとかNAT Gatewayとかいろいろ課金されるし、lambdaもapi gatewayに課金されます。簡単のためそれらを無視し、lambdaとecsの利用料金を比較します。

lambdaの料金は計算時間*(確保するメモリ*メモリあたりの料金+確保するストレージ*ストレージ当たりの料金)で計算できます(リクエスト数に応じても課金されますが、月100万リクエストまで無料なので計算に含めません)。また、lambdaには無料枠があり、1 か月あたり 40 万 GB 秒のコンピューティング時間が無料で使えます。よって確保するメモリ*計算時間 から40万GB秒を引いて料金を計算します。

上のパラメータで計算してみると以下のようになります。

アクセス数(アクセス/月) 計算された料金(USD/月)
10000 0.01
100000 2.78
200000 10.89
300000 19.00
400000 27.11
500000 35.22
1000000 75.78

ECSの料金は起動時間*(確保するvCPU*vCPU当たりの料金+確保するメモリ*メモリあたりの料金)で計算できます。こっちは初年度以外無料枠がありません。上のパラメータでこちらも計算すると以下のようになります。(aws pricing calcuratorで計算しました)

単位変換管理イベント
タスクまたはポッドの数: 1 /日 * (730 時間 (1 か月) / 24 1 日の時間数) = 30.42 /月
平均期間: 1 days = 24 hours
料金の計算
30.42 タスク x 1 vCPU x 24 時間 x 0.04045 USD /時間 = 29.53 USD vCPU 時間用
30.42 タスク x 2.00 GB x 24 時間 x 0.00442 USD/GB/時間 = 6.45 USD GB 時間用
20 GB - 20 GB (追加料金なし) = 0.00 タスクあたりの GB 請求可能エフェメラルストレージ
29.53 USD vCPU 時間用 + 6.45 USD GB 時間用 = 35.98 USD 合計

これを見ると、計算リソースへの課金だけなら50万アクセス/月程度が損益分岐点ということになります。さらにこれはキャッシュが一切効かない環境での話です。もしキャッシュヒット率が50%あるなら、損益分岐点は100万アクセス/月ということになります。ちなみに私の携わっているサービスのキャッシュヒット率はもっと高いです。

lambdaの料金の途中計算

1ドル160円としている(私の人生最大値付近で計算しやすい値)

アクセス数/月 メモリ(GB/秒) ストレージ(GB/秒) 計算された料金(USD/月) 計算された料金(円/月) aws pricing calcuratorの回答(USD)
10000 60000 300000 0.01 2
20000 120000 600000 0.02 4
30000 180000 900000 0.03 5
40000 240000 1200000 0.04 7
50000 300000 1500000 0.06 9
60000 360000 1800000 0.07 11
70000 420000 2100000 0.34 55
80000 480000 2400000 1.16 185
90000 540000 2700000 1.97 315
100000 600000 3000000 2.78 444
200000 1200000 6000000 10.89 1742
300000 1800000 9000000 19.00 3040
400000 2400000 12000000 27.11 4338
500000 3000000 15000000 35.22 5635
600000 3600000 18000000 43.33 6933
700000 4200000 21000000 51.44 8231
800000 4800000 24000000 59.55 9529
900000 5400000 27000000 67.67 10827
1000000 6000000 30000000 75.78 12124 75.72
2000000 12000000 60000000 156.89 25102
3000000 18000000 90000000 238.00 38080
4000000 24000000 120000000 319.11 51057
5000000 30000000 150000000 400.22 64035
6000000 36000000 180000000 481.33 77013
7000000 42000000 210000000 562.44 89990
8000000 48000000 240000000 643.55 102968
9000000 54000000 270000000 724.66 115946
10000000 60000000 300000000 805.77 128923
20000000 120000000 600000000 1616.87 258700
30000000 180000000 900000000 2427.98 388477
40000000 240000000 1200000000 3239.08 518253
50000000 300000000 1500000000 4050.19 648030
60000000 360000000 1800000000 4861.29 777807
70000000 420000000 2100000000 5672.39 907583
80000000 480000000 2400000000 6483.50 1037360
90000000 540000000 2700000000 7294.60 1167136
100000000 600000000 3000000000 8105.70664 1296913

計算2:付随するリソースの料金も含めて比較

しかし計算リソースだけではwebサイトをホスティングすることはできません。上では計算量のみを比較するためにコンテナを1つとしましたが、ECSならコンテナが複数あるのが普通であり、その場合ルーティングを行うALBを設置する必要があります。lambdaではapi gatewayがないとインターネット経由でlambdaを呼び出せません。これらの料金をシンプルに加算して比較してみましょう。

API Gatewayは100万アクセスでも月1.29USDくらいです。アクセス数が少なければもっと安いですが、簡単のために全部この金額がかかることにします。

512 KB/リクエスト / 512 KB リクエストの増分 = 1 リクエスト
RoundUp (1) = 1 請求可能なリクエスト
1 1 か月あたりのリクエスト x 1,000,000 単位乗数 x 1 請求可能なリクエスト = 1,000,000 請求可能なリクエストの合計
Tiered price for: 1,000,000 リクエスト
1,000,000 リクエスト x 0.00000129 USD = 1.29 USD
合計階層コスト = 1.29 USD (HTTP API リクエスト)
HTTP API リクエストのコスト (毎月): 1.29 USD

2025/9/16 追記)API Gatewayは必須ではない

ここでAPI Gatewayが必須かのように書いていますが、これは誤りでした 🙇
API Gatewayを使わなくてもlambdaをインターネット経由で呼び出す方法を教えてもらいました。Lambda Function URLsを関数に設定すればAWSの用意したURLでインターネットに公開できます。(さらにCloudFrontを経由するなら、CloudFrontのOriginをFunction URLのURLにし、CloudFrontの代替ドメインに自分のURLを設定することで、任意のURLで公開できます。)

ALBは存在するだけでUSD 0.0243/Application Load Balancer/時 かかります。月に直すと17.74USDとなります。通信量に応じてもっとかかりますが、通信量は想像がつかないので一旦お金がかからないものとします。

これをシンプルに足してみると表は以下のようになります。

アクセス数(アクセス/月) 料金(USD/月)
10000 1.30
100000 4.07
200000 12.18
300000 20.29
400000 28.40
500000 36.51
700000 52.73
1000000 77.07

ECS
35.98+17.74=53.72 USD

損益分岐点は70万アクセスくらいになりました。キャッシュヒット率0%での話です。かなりlambdaが安く見えますね。

結論

  • (当然だけど)アクセス数が少ないうちはlambdaが安く、アクセス数が上がるとECSが安い
    • 同じインスタンスサイズでさばければの話
  • この設定だと損益分岐点は50万アクセス/月
    • キャッシュヒット率が上がるほどさらにlambdaが安い
  • 意外とそこそこの規模のサイトでもlambdaのほうが安いのではなかろうか

月100万アクセスあってもキャッシュヒット率50%でlambdaが勝ちます。月10万アクセスくらいならECS使うな。

じゃあ以後うちのプロジェクトは全部lambdaで作ろう

そういうわけにはいきません。これまでweb開発をやっていた人たちはサーバーにデプロイしてnginxやapacheでリクエストを受け付けていたものです。それがコンテナになるのはまだこれまでの延長線上にありますが、lambdaは理の外にあります。作り始めたらどんな問題が起きるかわかりません。私自身もlambdaで全部システムを構築したことがないエンジニアの一人です。lambdaでサービス全部作るなんてバカだぜという知見を持っている方は教えてください。
すぐ思いつく範囲でも以下のような問題があります。考えるよりやってみたほうが早そう。ちゃんと時間かけて個人サービス作ったよ~という人は教えてください。私もやる気が出たら実験します。

  1. 純粋にlambdaで作るときに美しくモジュール分割できなそう
    1. amplifyを信じていいのか?
  2. RDB使えない
    1. VPCにlamdba置いてRDS建てましょう。IG分余計にお金とられるけど
    2. RDSよりsqlite on efsのほうが安いらしいです
      1. https://qiita.com/aki366/items/f2d353948cebbbf9c94c
      2. https://zenn.dev/beenos_tech/articles/lambda-sqlite-application
    3. できればDynamo使えると無料枠があるのでさらに安上がりです

Discussion

kanaruskanarus

lambdaではapi gatewayがないとインターネット経由でlambdaを呼び出せません。これらの料金をシンプルに加算して比較してみましょう。

API Gatewayは100万アクセスでも月1.29USDくらいです。アクセス数が少なければもっと安いですが、簡単のために全部この金額がかかることにします。

ここで Lambda Function URLs が最初から選択肢に入っていないのは何か理由があるのでしょうか?

(文脈を掴めていなかったらすみません…)

gyanagyana

普通に知りませんでした。API Gateway使わなくてもパブリックアクセスができると追記しておきます。
知見ありがとうございます🙇

acomaguacomagu

うちは会社の方針で可能な限り Web サイトには Lambda を採用する方針となっています。(もう10年くらい?)
Lambda で Web サイトをホストできるか?の一番の判断のポイントは「Cold Start が許容できるか」です。ECS では常時起動になりますが、Lambda では Cold Start があります。(Lambda はコンテナと違い複数リクエストを1コンテナで受ける、みたいなことができないのでこれは Provisioned Concurrency 等を用意していても基本避けられないと考えたほうがいいです。めちゃめちゃリクエストがあるなら別ですが) ランタイム自体の起動時間は多くの場合無視できますが、アプリケーション自体に起動時に時間のかかる処理が必要な場合、もしくは起動に数秒かかってしまうほど大規模なアプリケーションな場合、Lambda は諦めることになります。

しかし Cold Start の問題がクリアできれば、Lambda は驚くほどスムーズに Web バックエンドとして機能してくれます。前段は API Gateway でもいいですし、Function URL + CloudFront でも OK です。最近は VPC Lambda も癖無く動いてくれます。
Lambda をうまく使うコツは、「Function だからと言ってむやみに責務を複数の Lambda に分けない(界隈では Lambdalith という名前で知られています)」「できる限り Cold Start(起動時間)を速くするよう意識してコードを書く」「RDS に直接繋がない(RDS Proxy や DSQL を検討する)」「メモリキャッシュはできる限り使わない」あたりでしょうか。

あと最新の Next.js は正直現状 Lambda だと微妙なので、OpenNext で Cloudflare に上げたほうが体験はいいです。(この数か月で改善されていたらすみません)

gyanagyana

会社単位でlambda使ってるところもあるんですね!社内で提案する勇気が湧いてきます
確かにコールドスタートの問題がありましたね。前Django乗せる方法あるじゃん!と思って起動遅いって書いてあってやめた記憶がよみがえってきました
知見をありがとうございます🙇

takanaritakanari

弊社で直近でやった案件では React SPA + Lambda + DSQL(最近 GA されたやつ)で構築しました。DSQL は RDS と違い常時起動ではない PostgreSQL 互換の DB (一部制約あり)で、 リクエスト単位の動作(起動も一瞬)なので DB の稼働も節約できる(無料枠もあって、場合によってはかからない)構成です。
担当者数人しか使わない、極めて小規模な業務アプリの受託開発でした。それほどアクセスも高頻度でなく、データ量もそこまでなので、この場合インスタンスのランニングコストは当分かからない可能性もあります。小さい規模だとそれほど Cold Start も気にならない(Hono が薄いのもある)ですし、UIの工夫次第で感じ方を軽減できる可能性はあると思います。

ただし、Lambda と CloudFront を直接繋ぐ際、リクエストボディのハッシュ値をx-amz-content-sha256ヘッダーとして渡す必要があります。これらの解決を Lambda@Edge で行ったり等の多少の工夫が必要になります。

私が前提としている詳しい構成や設定方法等は、(私の友人が書いた著書ですが)以下の本をご参照ください。Pulumi による IaC まで含んでいます。ご参考までに。
https://zenn.dev/utcarnivaldayo/books/pulumi-lambadlith

ひかるひかる

apprunnerはどうですか? 以前会社で小規模アプリを構築するときに採用しました。ECSより手軽に構築できますが、ECSほど細かく設定することはできない感じなので、スモールスタートに良い印象でした。費用感の比較はしていないので、参考までに🙏
https://aws.amazon.com/jp/apprunner/

がれっとがれっと

Lambda良いですよね!!!個人的にはAPI Gatewayと組み合わせてWebSocketを作れるところが好きです。

VPCにlamdba置いてRDS建てましょう。IG分余計にお金とられるけど

Lambdaを置くのがPrivate Subnet, Public Subnetに関わらず、IGWのみで外部ネットワークに接続することはできません。NATインスタンスを使うのが定石ですが、コストを極限まで抑えるのであればLambdaにEIPをアタッチする方法もあります。
https://dev.classmethod.jp/articles/20230829-vpc-lambda/
外部APIを叩くなどしなければ、そもそも不要ですが…(リクエストを受け付けることはできる)

RDBに関してはAWS縛りがなければ、SupabaseやD1などに逃がしてしまうのが手っ取り早い気がします。

nixiemintonnixieminton

わかりやすい記事をありがとうございました。

コンテナになるのはまだこれまでの延長線上にありますが、lambdaは理の外にあります

lanbda web adapterというライブラリを用いることで、webサーバに限ってはコンテナと同等の負担でlambdaデプロイが可能になります。
こちらの記事が大変わかりやすいので、ご参考にしていただけると嬉しいです。

https://aws.amazon.com/jp/builders-flash/202301/lambda-web-adapter/

Satoshi KitaSatoshi Kita

Lambda良いですよね。私も大好きで、Lambdaで完結しているWebシステムもいくらかあるので少しコメントさせて頂きます。

「モダンなフレームワークを使えば勝手にLambdaでデプロイしてくれる」と書かれていますが、私の場合はLaravelを使うことが多いので、そのときはLaravel Vaporを使ってデプロイします。長いものだともう5年以上経ちますが、非常に安定して動いてくれています。

お金のかかり方は構成によってかなり違いますよね。

記事でも書かれていますが、DynamoDBで済ませるようなケースもあり、その場合は固定費はほとんどかかりません。外部サービスではありますが、Tursoのようなサービスが利用可能であれば、固定費のほぼかからないRDBとの組み合わせも作れるかもしれません。

一方でRDSを組み合わせると、RDSやらNATゲートウェイやらで途端に固定費が嵩みます。こちらのパターンは相当な規模までいかないとLambdaの費用が固定費を超えることはない印象です。こちらの場合、小規模だとVPS1台で済ませたりする方がずっと安上がりなので、必ずしもコスト的なメリットはありません。ですが個人的には、インフラのメンテから解放されるだけでも結構大きいと思っています。

複数のLambda関数の組み合わせについては、一般的にはLambdaからLambdaの直呼び出しはアンチパターンと言われていますが、現実的には同期処理したいことも多いので私は結構やってしまいます…。

正直Cloudflare Workersを使いたいシーンもあるんですけどね…ネットワーク待機中は課金されないのとか魅力的ですし。ですがそれを差し引いても、Lambdaの自由度はとても魅力的です。