AWS Builder Center

Lambda Web Functionsをどう選ぶか

注文APIを題材に、再試行、DB接続、HTTPの入口、更新失敗からの復旧をAWSで比べます。通常のLambdaとの対照から、Web Functionsを選ぶ条件を考えます。

Senior Evangelist

Web Functionsを選ぶ基準

Lambda Web Functionsを選ぶなら、HTTPの入口、DB接続、失敗した後の扱いを一緒に考えます。今回の検証では、直接アクセスとHTTP API経由で、受け付けた件数が分かれました。注文の再送や、失敗した更新からの復旧も、アプリ側で設計が必要でした。
通常のLambdaであるEvent Functionsとも比べます。こちらは、呼び出し1回ごとにhandlerが実行される方式です。Event Functionsの同時処理 では、1つの実行環境が同時に1件を処理します。Web Functionsは、起動したHTTPサーバーへリクエストを渡します。Honoは、HTTPの処理を書くWeb frameworkです。今回のEvent Functionsには、呼び出し形式とHonoをつなぐadapterを加えました。
選ぶ基準は、「同じ実行環境で何件を同時に処理したか」だけでは足りません。注文の完了条件、DB接続数、HTTPの入口、更新の戻し方を、同じ業務処理で確かめます。

注文APIで比べる

注文IDをDBへ保存し、結果を返す小さなAPIを用意しました。決済や在庫更新は含めていません。保存処理はWeb Functions、Event Functions、SQSのworkerで共通にしています。
CloudFrontとHTTP APIからWeb Functions・Event Functionsへ接続し、SQS workerとAuroraを比較する構成
青線は呼び出しとDB接続です。Web FunctionsはVPC接続用のNetworkConnectorを通して、外部公開していないAuroraへ接続します。Event FunctionsもVPCへ接続します。灰色の破線は、Web FunctionsのログをCloudWatch Logsへ送る経路です。呼び出し元への応答は、呼び出しの経路を戻ります。代表的な処理経路を描いており、Secrets Manager、S3、Event Functions・受付Lambda・workerのログ経路は省略しています。
Runtimeは、プログラムを動かす環境です。Previewは、正式提供前の段階です。
項目検証条件
配置先ap-northeast-1。CloudFrontはglobal
Web Functionsnodejs24.x、Node.js v24.21.0、arm64
Event Functionsの比較用nodejs24.x、Node.js v24.21.0、arm64
Event Functionsの最新Previewnodejs26.x、Node.js v26.8.2、arm64
SQSの受付Lambdaとworkernodejs26.x(Preview)、arm64。Node.jsの実versionは未採取
実行環境Webは2GB。Eventは2,048MB、同時実行上限2
Webの設定環境数の上限2、環境内の同時処理数の上限1または8
DBAurora PostgreSQL 17.5、Serverless v2、計算容量は0.5〜1 ACU。ACUは計算容量の単位
接続pool(接続を環境内で再利用する仕組み)環境ごとの最大接続数を1または4
timeoutWebは6秒、Eventは10秒。CloudFrontの通常経路とHTTP APIの連携は8秒、短い経路は1秒
入口の受付上限Web endpointは毎秒100件。HTTP APIのstage(APIを公開する環境)は毎秒10件、瞬間的な受付上限も10件
endpointWebはHomeRegion。1つのAWS Regionで実行する種類を選び、東京へ配置
Runtimeは、Web Functionsの対応一覧 と、Event Functionsの対応一覧 を分けて確認しました。2026年10月16日時点で、Node.js 26はPreviewです。APIの主な対照には、正式対応のNode.js 24を使います。SQSの受付Lambdaとworkerは、Preview runtimeでの検証です。
API比較のNode.js version、受付とworkerのruntime、呼び出し拒否数を示す保存記録
baseはWeb、api24とapi26は通常のLambdaです。下段のThrottlesは、同じ測定期間にLambdaが呼び出しを断った件数です。
endpointは、Web Functionsを呼ぶURLです。revisionは、コードと設定を固定した版です。DBの設定を比べる条件は、別のrevisionを別のendpointへ配置しました。
環境IDと、コードの版を示す値を応答とログへ入れました。ここでいう環境IDは、アプリ起動時に発行した値です。同じIDを返した呼び出しを、再利用された環境として数えます。設定した上限と、実際に使われた環境数は分けて数えます。
以下の実測画面は、2026年10月16日に測定したAWS応答の保存記録を、同日のCloudShellに表示したものです。件数は、同じ保存記録から数えています。画面のreqは、要求の記録番号です。

タイムアウトと注文の保存

重複対策なしの条件には、別の表unsafe_ordersを使いました。この表は行ごとのIDだけを主キーにし、注文IDには一意制約を付けません。同じ注文IDでも、INSERTのたびに別の行が増えます。
CloudFrontの待ち時間を1秒にし、DBへ保存する前か、保存した後に2.2秒待たせました。Web Functions側のtimeoutは6秒です。短い待ち時間の経路へ送り、その後、通常の経路から同じ注文を再送します。
接続が成功した後の測定では、最初のHTTP応答はすべて504でした。それでも、DBには注文が保存されました。再送を判断するときは、HTTP応答とDBの保存結果を分けて見ます。
条件最初の応答同じ注文を再送した後の保存件数
保存前に待機、重複対策なし5042件
保存後に待機、重複対策なし5042件
保存前に待機、注文IDを主キーにする5041件
保存後に待機、注文IDを主キーにする5041件
各条件を2回ずつ試し、再送はすべて200でした。クライアントのtimeoutを0.4秒にする対照も、保存前・保存後に分けて試しています。timeoutの後に2秒待ち、再送の前に主キーのある表から1件の保存を読み返しました。再送は両方200で、inserted=falseでした。insertedは、新しく登録したかを示します。最初の要求で保存され、再送では追加されなかったことを確認しました。
初期の2条件では、DB接続を待つ2.5秒の上限に達しました。再送も503となり、読み返した時点の保存件数は0件でした。原因は特定できていません。接続成功を確認した後、コードを変えずに上の全条件を測り直しています。
CloudFrontの504後に再送した結果とDBの保存件数を示す保存記録
初期の接続失敗と再測定の保存記録です。firstは最初の応答、retryは再送の応答です。IDのbeforemsとaftermsは、保存前と保存後の待機を表します。ID末尾のtrueが重複対策なし、falseが主キーありです。DBは主キーあり、なしの順です。requestIdとdbRequestIdは、再送応答とDB読み返しを追う識別値です。retryNumberは、再送した要求の記録番号です。
DB側のSQLの実行期限も試しました。statement_timeoutを250msにし、INSERT前に2秒待つSQLを実行します。2回とも待機SQLが止まり、エラーコード57014となりました。アプリはROLLBACKを行い、HTTP 504を返しました。ROLLBACKは、DBの変更をまとめたtransactionを取り消す命令です。読み返した保存件数は0件でした。INSERT後の書き込みがROLLBACKで戻るかは、今回の測定には含めていません。

同じ注文の再送

重複対策には、DBの主キーとINSERTを使いました。先に件数を調べてから登録すると、その間に別のリクエストが入る可能性があります。重複を止める判断を、一つのINSERTへまとめます。
SQLの中心は次の部分です。
1
2
3
4
5
6
7
8
9
10
CREATE TABLE orders (
order_id text PRIMARY KEY,
revision text NOT NULL,
created_at timestamptz NOT NULL DEFAULT now()
);

INSERT INTO orders (order_id, revision)
VALUES ($1, $2)
ON CONFLICT (order_id) DO NOTHING
RETURNING order_id;
同じ注文IDを約0.1秒間隔で8件送り、応答待ちを重ねる条件も2回ずつ試しました。重複対策がない表には各8件、主キーのある表には各1件が保存されました。
同じ注文の連続送信、クライアントのtimeout、SQL取消しと保存件数を示す保存記録
約0.1秒間隔の送信、クライアントのtimeout、SQL取消しの保存記録です。DBは、重複対策あり、なしの順です。disconnect行のDBは、再送前の読み取りです。
8件を一斉に送る条件は未測定です。主キーとON CONFLICTによる競合の扱いは、PostgreSQLのINSERT仕様 でも確認しています。
これは、今回のDB登録を重複させない仕組みです。利用者ごとに注文IDを扱う場合や、同じIDで異なる内容が届く場合の判断は、実際の業務に合わせて加えます。

DBへの接続を抑える

環境内の同時処理数と、DB接続数は別に決めます。接続poolは、DBへの接続を環境内で再利用する仕組みです。環境が増えると、poolも増えます。
DB接続を0.8秒使う注文を、0.1秒以上の間隔で8件送りました。送信は毎秒10件以下、同時送信は最大8件です。環境数の上限は2に固定し、各条件を2回ずつ比べています。
条件8件のHTTP結果。1回目/2回目対象環境のDB接続数の観測最大
Web:同時処理数1、pool1200が2件、429が6件/同じ2
Web:同時処理数8、pool1200が6件、503が2件/200が7件、503が1件2
Web:同時処理数8、pool4200が4件、429が4件/同じ4
Web:同時処理数8、pool1、空きがなければ受付を断る200が2件、503が6件/同じ2
HTTP API+Event:同時実行上限2、pool1200が2件、503が6件/同じ2
429は、Web endpointのPlatform.EndpointMaxEnvThrottleでした。環境数の上限による拒否です。Eventの503はHTTP APIの応答で、同じ期間のLambda metricsにもThrottlesが記録されました。アプリの接続取得期限や受付拒否の503と分けます。
DB接続数は、接続の状態を調べるpg_stat_activityから取得しました。0.5秒の待機を挟み、取得時間も含む実際の間隔は約0.5〜0.8秒でした。応答の環境IDと照合し、対象の接続を数えています。
同時処理数とpoolを変えたHTTP結果と、観測したDB接続数の最大値を示す保存記録
cap1は同時処理数1、baseは同8、pool4は接続poolの上限4です。guardTrueは空きがなければ受付を断り、guardFalseは接続取得期限まで待ちます。api24はHTTP API+Event24です。dbMaxは対象環境の接続数の観測最大、secは8件の全応答が返るまでの秒数、reqは最初の要求の記録番号です。画面の~0.5sは待機の設定値で、実間隔は約0.5〜0.8秒です。
pool1のbase endpointは、8件ともアプリへ届きました。うち1〜2件は、2.5秒の接続取得期限に達して503となりました。pool4のendpointは、2環境が2件ずつ受け付け、残り4件はendpointで429となりました。処理先と受け付けた件数が違うため、所要時間をpoolだけの効果に読み替えません。ここで確認したのは、対象のDB接続数の観測最大が2と4だったことです。
空きがなければ受付を断る条件では、約1.0〜1.1秒で全応答が返りました。拒否された要求は、呼び出し側で待機と再送を制御します。

環境数の設定を確かめる

環境数の上限を4にした条件は、2回とも8件すべて成功しました。実際には、2つの環境が4件ずつ処理しました。上限2の条件でも8件成功したため、成功数の差を上限変更の効果とは言えません。
上限を2へ戻した約1分半後に、base endpointから64件の注文を送りました。poolは各1です。DB接続を使う時間を0.8秒から0.4秒へ短くし、毎秒10件以下、同時に応答を待つ要求は最大8件としました。約13.5秒で64件すべてが成功しました。
復旧から約12分後、環境IDが入れ替わった状態で0.8秒の処理を再測定しました。1回目は8件とも新しい1環境へ届きました。2件が200となり、6件はアプリの接続取得期限で503となりました。2回目は2環境へ4件ずつ届き、8件すべて200でした。環境の暖まり具合はそろえていません。
環境数の上限変更と復旧後の結果、64件の持続送信を示す保存記録
測定順は、上限変更と復旧、64件送信、約12分後の再測定です。画面のsizing-restored2が再測定、sustained64が64件送信です。envsは200の応答の環境ID、secは全応答が返るまでの秒数です。
接続の予算は、環境数の上限とpoolから見積もります。運用時は、実際の環境数とDB接続数を追います。

キューへ受け渡す

すぐに登録結果を返す必要がなければ、受付と保存を分ける選択肢があります。HTTP APIから受付用Lambdaを呼び、SQSへ注文を送ります。SQSは処理待ちのメッセージを保存するサービスです。保存するworkerには、Event Functionsを使いました。
workerの同時実行上限は2、poolは環境ごとに1です。DB接続を0.8秒使う処理は、先ほどの同期処理と同じです。
8つの注文IDを送り、そのうち1つを意図的に再送しました。9件とも、受付を示す202が返りました。最初の応答は約0.78秒、その後は約0.10〜0.15秒です。
最後の受付からの待ち時間DBで読み返せた注文
約1秒0件
約6秒7つの注文ID、各1件
約66秒8つの注文ID、各1件
SQSへの9件の受付と、その後のDB読み返しを示す保存記録
待ち時間を1秒、5秒、60秒と追加し、最後の受付から約1秒、6秒、66秒の順で読み返しています。
8つの注文IDのうち、最初の1件だけworkerの初回を失敗させました。可視性タイムアウトは、受け取ったメッセージを他のworkerへ見せない時間です。今回は60秒にしたため、同じメッセージの再配送は約60秒後でした。この待ち時間があり、約6秒後は7件、約66秒後に8件となっています。同じmessage IDの2回目の配送で完了したことを、ログでも確認しました。意図的に2回送った注文ID queue-022107-1も、保存は1件でした。2通目の処理はinserted=falseでした。
同じSQS message IDの初回失敗と2回目の完了を示すCloudWatchログ
CloudWatchから取得したログです。同じmessage IDで、queueRetryとattemptが2のqueueCompletedを確認しています。
202が示すのは受付です。受付後の状態確認、完了までの待ち時間、再試行と復旧の手順が増えます。SQSからの呼び出し では重複処理が起こり得るため、workerにも同じ注文を再登録しない設計が必要です。

I/O待ちを重ねる

Web Functionsの待ち時間の扱いを、DBを使わないタイマーで確かめました。200ms待つ非同期処理と、200msの間、同期的に計算し続ける処理を用意します。前者はI/O待ちを模したものです。I/O待ちは、DBや外部APIからの応答を待つ時間です。後者の計算中は、同じHTTPサーバーの別のリクエストが待たされます。待機と計算をそれぞれ200ms続け、要求の重なり方を比べます。
8件を同時に送り、条件ごとに2回試しました。
経路と設定I/O待ち同期計算
Webへ直接。同時処理数1各回2件成功、6件429各回2件成功、6件429
Webへ直接。同時処理数8各回8件成功。全体0.304〜0.318秒各回8件成功。全体0.896〜0.897秒
HTTP API+Web。同時処理数8各回4件成功、4件429各回4件成功、4件429
HTTP API+Event24。同時実行上限2各回2件成功、6件503各回2件成功、6件503
HTTP API+Event26 Preview。同時実行上限2各回2件成功、6件503各回2件成功、6件503
8件同時のI/O待ちと同期計算を各経路で2回ずつ比べた保存記録
cap1は同時処理数1、baseは同8の直接アクセスです。apiはHTTP API+Web、api24・api26はHTTP API+Eventです。ioはタイマー待ち、cpuは同期計算です。envsは200の応答の環境ID、secは8件の全応答が返るまでの秒数です。各条件を2回ずつ試しました。
直接アクセスのWebは、両方とも2環境で、各環境が4件ずつ処理しました。タイマー待ちは8件全体で約0.3秒、同期計算は約0.9秒です。同じ環境で待ち時間を重ねる場合と、同期計算で順に処理する場合の違いが出ました。
Event Functionsは、同時実行上限2により、同時に処理する環境は最大2つです。今回も2環境が各1件を処理しました。環境数の上限をどちらも2としたとき、Webの直接アクセスは8件、Eventは2件を受け付けました。速度に加え、受け付けた件数と拒否を合わせて見ます。
Web Functionsの同時処理数 は、AWSが使用状況に応じて変えます。設定値は、その上限です。直接アクセスのbaseは8件成功し、HTTP API経由の別endpointは4件でした。環境数と同時処理数の上限は同じです。差の原因は特定できていません。HTTPサーバーのI/O待ちを重ねたい場合に候補とし、実際の入口と依存先で負荷を確かめます。

HTTPの入口を決める

前の記事は「Lambda Web FunctionsとCloudFront・API Gatewayを連携してみる 」です。CloudFrontとHTTP APIの接続、cache、逐次応答を比べました。今回は、署名付きtokenのJWT、通常のLambda、pathの書き換えがない条件を加えています。
CloudFront、HTTP API、アプリの認証は、役割を分けました。利用者の認証には、検証用に発行した署名付きJWTを使っています。JWTは、発行元や利用者の情報を署名で確かめるtokenです。
アプリは署名、発行元、利用先、有効期限を確認します。利用者のJWTはX-App-Tokenへ入れました。HTTP APIの呼び出し元を確認するIAM署名が、Authorizationを使うためです。ここでは、検証用に発行したJWTの署名確認までを比べます。
OACは、CloudFrontから処理先へのアクセスを認証する設定です。
経路呼び出し元から入口まで入口から処理先まで
CloudFront+WebアプリがJWTを検証OACがIAM署名。対象distribution以外を明示的に拒否
HTTP API+WebrouteでAWS_IAM。アプリもJWTを検証API Gatewayが専用tokenを上書きし、アプリが照合
HTTP API+EventrouteでAWS_IAM。アプリもJWTを検証Lambda連携の呼び出し権限
CloudFrontからの経路では、LambdaがIAM認証を行います。同じaccountのIAM権限だけでも直接呼べるため、今回のpolicyでは対象のCloudFront以外をDenyで拒否しました。
HTTP API用のendpointはApplicationManagedです。Lambda自身は認証せず、アプリが共有の専用tokenを照合します。専用tokenが漏れると、正しい利用者JWTを持つ相手は直接呼べます。tokenの更新手順は未検証です。認証方式の仕様 に沿って、共有tokenの保管と更新は利用者が担います。
各経路で2人の正しいJWTは200、JWTなし・期限切れ・不正値は401でした。各条件を2回ずつ試しています。
各経路で正しいJWTと未指定、期限切れ、不正値を送った認証結果の保存記録
1回目の認証結果を表示しています。cfはCloudFront、apiはHTTP API+Web、api24とapi26はHTTP API+Eventです。
CloudFront用endpointへ直接送る対照は、IAM署名の有無にかかわらず403でした。API Gateway用endpointへの専用tokenなしの直接アクセスも403です。呼び出し側が誤った専用tokenを付けても、API Gatewayが上書きした経路は200でした。利用者の認証と、処理先を呼べる相手の制限を、別に確かめています。
CloudFront用endpointへの直接アクセスとAPI Gatewayのtoken上書きを示す保存記録
CloudFront用endpointへの直接アクセスは403でした。API Gatewayが専用tokenを上書きした要求は200です。

逐次応答の経路を選ぶ

公開データは同じURLへ8件送り、初回がMiss、残り7件がHitでした。後半4件は、前半で作られたcacheを再利用しています。個人別の応答はcacheを無効にし、private, no-storeを返しました。今回は、Event連携の逐次応答も比べます。
比べた条件今回の結果
CloudFront+Webで250ms間隔の3行を送信2回とも約250ms間隔で到着
HTTP API+Web/Event24/Event26で同じ3行を送信各2回とも、3行をまとめて受信
逐次応答の到着時刻と公開データのCloudFront cache結果を示す保存記録
kindがstreamの行は、arrivalMsに到着までのミリ秒を示します。kindがcacheの8行は、今回の公開データの記録です。
今回加えたEvent連携でも、受信側には3行がまとまって届きました。ここで使ったHTTP APIと、REST APIのresponse streaming は分けて判断します。
今回の逐次応答や公開データのcacheが要件なら、CloudFront+Webが候補になります。

日本語を含むURLの転送

前の記事では未確認だった、pathの書き換えを設定しない条件を加えました。入口によって結果が分かれています。同じ入力を送り、各条件を2回ずつ比べています。
1
/echo/%E6%97%A5%E6%9C%AC?q=%E6%97%A5%E6%9C%AC
経路結果
CloudFront+Web200
HTTP APIのHTTP_PROXY+Web400
HTTP APIのLambda連携+Event24/26200
HTTP_PROXYは、受け取ったHTTPリクエストを別のHTTPサーバーへ転送する連携です。今回はpathの書き換えがないIntegrationと、overwrite:pathを設定したIntegrationを別に作りました。
同じAPI、同じpath、同じ転送先で、書き換えなし、あり、なしへ戻す順に比べました。AWSから取得した実設定でも、指定の有無を確認しています。3段階とも、英数字のpathとqueryでは200でした。pathとqueryの両方に日本語を含む上のURLでは、400でした。
同じHTTP APIでpath書き換えを外し、加え、再び外したURL転送の保存記録
pathを書き換える設定の有無と、実際のHTTP結果を対応させています。
pathを書き換える設定の有無では、結果が変わりませんでした。今回の入力では、pathとqueryのどちらが400の原因かは分離できません。日本語を含むURLが必要なら、今回成功したCloudFront経由やEvent Functionsを候補に残します。採用前に、実際のURL形式で確かめます。

不良版から戻す

正常版goodと、不良版badを作りました。badは、注文IDが-badで終わるときだけ、保存後に500を返します。今回の更新前・段階配信・切り戻し後の注文は、すべて-badで終わるIDです。badへ振り分けられた注文は、必ず保存後に失敗する条件としました。不良版も、AWSが示す状態はActiveでした。
更新前に、判定基準を決めています。正常版で20件すべて成功することを確かめ、切り替え後の20件に1件でも失敗があれば戻します。戻した後は、正常版で20件連続成功することを確かめます。
段階観測結果
正常版のみ20件すべて200
重み50:50へ変更した直後注文はgoodが16件200、badが4件500
正常版100へ戻した後20件連続でgoodの200
管理APIの更新完了と、実際の転送先は分けて見ます。重みを50:50にし、管理APIがSuccessfulを示した約3.5秒後に、healthの送信を始めました。状態確認用の8回は、すべてgoodでした。続く注文20件はgoodが16件、badが4件でした。配分の仕組みや、定常時の比率を測った結果ではありません。
切り替え時に処理中だったgoodの注文は、約2.5秒後に200を返しました。badが500を返した4件も、DBには保存されています。切り戻した後も、保存済みの注文はそのまま残りました。
不良版の配信、500応答、正常版への切り戻しとDB保存件数を示す保存記録
20件の配信結果と、処理中の注文、版ごとのDB保存件数を表示しています。healthAfterShiftは、重み変更後、注文の前に送った8回の状態確認です。
戻した後、同じ4つの注文IDを再送しました。4件とも200となり、新規登録を示すinsertedはfalseでした。DBの保存は各1件のままです。
切り戻した後に同じ4つの注文IDを再送したHTTP結果と保存件数の記録
同じ4つの注文IDを再送し、insertedがfalse、保存件数が各1件であることを確認しています。
監視には、注文IDと版の識別値を残します。標準のWeb Functionsのmetrics にはrevisionの区別がないためです。HTTPの500、DBへの保存、戻した後の再送を、それぞれ追えるようにします。

料金の見積もり

Web Functionsは、request数、使ったCPU時間、環境が動いていた間のメモリを分けて見積もります。metricの仕様 では、CPU時間と稼働時間の単位はミリ秒、メモリはMegabytesです。CPUと稼働時間を1,000で割り、秒へ直しています。全環境の稼働時間は、環境ごとの秒数を足した値です。
CPU時間と稼働時間に値が記録されたのは、02:09〜02:30 UTCの22個の1分枠です。6つのendpointを含むWeb Function全体で、CPU時間は27.38 vCPU秒、全環境の稼働時間は7,618.609秒でした。観測した最大メモリは、AWSのmetric表記で190MBです。要求が0件だった1分間にも、CPU 131ms、メモリ最大159MBを記録した環境がありました。
CPU時間、環境稼働時間、最大メモリと、要求0件の1分間のCPU・メモリを示す保存記録
02:09〜02:30 UTCの保存記録です。CPU時間と稼働時間は合計、メモリは最大値です。440件の内訳と、要求が0件だった1分間のCPU時間・メモリも表示しています。
東京のArm単価を使い、メモリが常に190MBだったと仮定すると、次の計算になります。request数の入力には、同じ取得時点の6つのendpointのExecutedRequestsを合計した440件を使っています。
項目計算例金額
CPU27.38秒 × $0.0000322421約$0.000883
メモリ190 ÷ 1,024 GB × 7,618.609秒 × $0.0000042688約$0.00603
request440件 × $0.30 ÷ 100万件$0.000132
この記録範囲で、3項目の試算は約$0.00705です。メモリを一定と置き、1GBを1,024MBとして計算した例です。途中で取得したmetricsを使っています。単価は2026年10月16日に取得した東京Regionの料金カタログ で確認しました。
入口や依存先の料金も加えます。従量課金の最初の料金帯で計算する場合、次のような項目があります。表は、税、無料枠、割引を適用する前の単価です。
項目単価を使う条件の例
Event Functions Armで$0.0000133334/GB秒と$0.20/100万呼び出し。今回の2GB設定では待ち時間も実行時間へ入る
HTTP API 東京で最初の料金帯は$1.29/100万request
CloudFront HTTPSは米国なら$1.00、日本なら$1.20/100万request。配信先の地域と転送量を確認
Aurora Serverless v2 東京のPostgreSQLは$0.15/ACU時。0.5 ACUが1時間続けば$0.075。storageとI/Oは別
VPC endpoint 今回のSecrets Manager用は東京で$0.014/AZ時。2つのAZで1時間なら$0.028。処理データ量は別
SQS 東京の標準queueは最初の料金帯で$0.40/100万request。送信だけでなく受信・削除なども数える
CloudWatch Logs 東京の標準logへの取り込みは$0.76/GB。保存と分析も加える
今回は、配信拠点の範囲を絞るPriceClass_100 で試しました。対象は米国、カナダ、欧州、イスラエルです。最後の確認で返った拠点の識別値はSFO5-P1でした。CloudFrontの料金は、使われた配信拠点の地域に合わせて計算します。
専用tokenを保管するSecrets Managerや、コードを置くS3、データ転送も見積もりへ加えます。

AWSとアプリの分担

endpointの仕様 、環境の増減 、環境の継続時間 を踏まえ、今回の注文APIの分担を整理します。
分担今回の構成で扱うこと
AWSへ任せることHTTPSのendpoint、実行環境の起動、負荷に応じた環境数と同時処理数の調整
利用者が守る条件HTTPサーバーを10秒以内に起動する。実行期限を守り、重要な状態はDBへ残し、要求ごとの状態を分ける
アプリ側に残る仕事注文の重複対策、poolと環境数の上限、採用前のDB接続上限の確認、入口の認証、失敗を検知して戻す基準
保証されないこと設定した同時処理数まで常に使えること、同じ実行環境が続くこと。実際の応答と環境IDで確認する
AWSが環境を増減しても、注文の正しさを保ち、DB接続数を調整する仕事はアプリ側に残ります。今回の429、接続取得期限の503、保存後の500は、それぞれ別の層で起きた結果です。再送、受付の制御、切り戻しを、原因のある層に合わせて設計します。
今回確認した範囲と、採用前に残る確認も分けます。
項目今回の範囲と、残る確認
注文の重複対策DB登録まで。同一ID8件の一斉送信、外部決済、同じIDで内容が違う場合、INSERT後のROLLBACKは未検証
DBと環境数接続数とpool待ちを小規模な入力で確認。DB側の接続数上限(max_connections)、ACUの負荷、上限に近づく条件、接続確立と空き待ちの個別時間、最大処理件数、Eventの上限8での接続数は未測定
待ち時間の比較DBなしの200msタイマーと同期loop。入口やCPU配分が同じとは限らず、固定計算量や経路間の速度順位は比較対象外
HTTPの入口検証用JWTと短いstreamで確認。認証基盤、鍵の更新、長時間stream、大きな本文、日本語を含むURLの400の内部原因は未確認
配信拠点PriceClass_100の短い試験。拠点ごとの遅延と月間のcache効果は未測定
更新と料金Webの切り戻しを確認。Eventの更新、定常状態の50:50配信、実請求と月間予測は未検証

まとめ

どの構成でも、同じ注文を重複して保存しない仕組みを前提にします。そのうえで、今回の結果から選ぶ条件を整理します。
要件候補採用時に確かめること
Node.jsのHTTPサーバーを動かし、I/O待ちを同じ環境で重ねたいWeb Functions入口ごとの受付件数、実際の同時処理数、共有する接続pool、同期計算で他の要求を待たせる箇所
DBの接続数に予算を設けたいWebは環境数の上限×pool、Eventは同時実行上限×poolで見積もり、workerにも同じ考え方を使うWebの観測最大は2・4接続、Eventは2接続。workerの接続数、DB側の上限と負荷は未測定。空き待ちか受付拒否かも決める
今回のような逐次応答や公開データのcacheが必要CloudFront+Web利用者の認証、直接アクセスの拒否、cacheするデータ、配信拠点
今回のようにpathとqueryに日本語を含むURLを、HTTP APIから扱いたいHTTP API+Event FunctionsHonoのadapter、実際のURL、同時実行数と依存先が受けられる接続数
受付と完了を分け、混雑や一時失敗を後で処理したいHTTP API+SQS+Event worker。今回はPreview runtimeで確認重複対策、待ち時間、完了確認、採用するruntimeでの動作
不良版を段階配信し、正常版へ戻せるようにしたいWeb Functionsのrevisionと重み更新完了と転送先の差、DBに残る書き込み、版を識別するログ。Event側の切り替えは未測定
DBなしの200msタイマーでは、直接アクセス用のbase endpointが2環境で8件を処理しました。HTTP API経由の別endpointは、同じ環境数と同時処理数の上限で4件でした。差の原因は未確認です。入口ごとに受付件数を確かめ、Web Functionsの利点を判断します。
まず、受付時に保存完了まで返すか、後で処理できるかを決めます。次に、待ち時間を重ねる必要があるかを確かめ、HTTPの入口を選びます。最後に、必要なDB接続数と更新を戻す基準を確かめます。その結果に合う構成を、表の候補から選びます。
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article