はじめに
#2 で主要クラウドの FaaS を比べたとき、大きな違いとして見えてきたのが 「1つのインスタンス(実行環境・VM)が、同時にいくつのリクエストを処理するか」 という点でした。
- 従来の AWS Lambda(Event Functions)は 1インスタンス = 1リクエスト
- Google Cloud Run functions や Azure Functions は 1インスタンスで複数のリクエストを同時に処理 できる
この「マルチコンカレンシー」は、コストにもパフォーマンスにも大きく効く 一方で、コードの書き方を誤ると事故につながります。今回は次の順で整理します。
- どのクラウドの、どのサービスが対応しているか
- コスト削減の効果(試算)
- コスト以外のメリット
- 実装上の注意点
この記事の情報は 2026年11月時点 の各社の公式ドキュメントに基づいています。料金は USD(さくら AppRun は円)で、東京リージョン、またはそれに相当する価格帯の値です。
用語の整理
各社で呼び方が違いますが、この記事では次のように呼びます。
| この記事での呼び方 | 各社での呼び方 |
|---|---|
| インスタンス | AWS Lambda: 実行環境(Execution Environment)/ Google Cloud Run functions: インスタンス / Azure Functions: インスタンス / Cloudflare Workers: isolate / さくら AppRun: インスタンス |
| 同時処理数 | 1インスタンスが同時に処理するリクエストの数(concurrency) |
1. 対応状況
一覧
| サービス | 同時処理数 | 設定できるか | 既定値・範囲 | 課金の単位 |
|---|---|---|---|---|
| AWS Lambda(Event Functions) | 1 で固定 | × | ― | リクエスト数 + 実行時間(GB秒) |
| AWS Lambda Web Functions | 複数 | ○ maxConcurrencyPerEnvironment
|
既定 64、1〜128(AWS Lambda が負荷に応じて動的に調整した値が上限になる) | アクティブな CPU 時間 + メモリ + リクエスト数 |
| AWS Lambda Managed Instances | 複数 | ○ PerExecutionEnvironmentMaxConcurrency
|
最大で vCPU あたり 64(既定値はランタイムによる) | EC2 料金 + 15% の管理費 + リクエスト数 |
| Google Cloud Run functions | 複数 | ○ --concurrency
|
既定 80、1〜1,000 | リクエスト数 + vCPU秒 + GiB秒(インスタンスがリクエストを処理している時間) |
| Azure Functions(Flex Consumption) | 複数 | ○ HTTP の同時処理数(インスタンス単位) | HTTP の既定は 512 MB→4 / 2 GB→16 / 4 GB→32(Python は既定 1) | 実行数 + GB秒(インスタンスが実行している時間) |
| Cloudflare Workers | 複数 | ×(プラットフォームが自動で制御) | ― | リクエスト数 + CPU 時間 |
| さくら AppRun(共用型) | 複数 | △ スケールアウトの目安となる同時リクエスト数 | 50〜200(既定 100)。1インスタンスの上限は 1,000 | インスタンス数 × 時間 |
AWS Lambda は「形態」で選ぶ
AWS Lambda の場合、同時処理数は 形態によって決まります。従来型の Event Functions は 1 で固定です。複数のリクエストを同時に処理したいときは、次のどちらかの形態を選びます。
| 形態 | 向いているケース | 注意点 |
|---|---|---|
| AWS Lambda Web Functions(2026年10月発表) | Web アプリや API。DB や LLM の応答を待つ時間が長い処理 | 発表時点では Node.js 24 / Arm64 のみ。対応リージョンは5つ(東京を含む) |
| AWS Lambda Managed Instances(re:Invent 2025 で発表) | 一定以上のトラフィックが続く処理。EC2 の割引(Savings Plans など)を使いたい場合 | アイドル時もインスタンス代がかかる。メモリは最低 2 GB / 1 vCPU から |
さくら AppRun の設定について
さくら AppRun の共用型には「スケールアウトの目安となる同時リクエスト数」という設定があります(50〜200、既定 100)。これは Knative の仕組みにもとづく値で、1インスタンスの上限を厳密に決めるものではなく、スケールアウトするかどうかの目安 です。値を大きくするほど、スケールアウトしにくくなります。
1 に設定して「1インスタンス = 1リクエスト」にすることはできません。つまり、さくら AppRun は 最初から複数のリクエストを同時に処理する前提 のサービスです。
Cloudflare Workers は特殊
Cloudflare Workers は、V8 の isolate の上で、プラットフォームが自動的に多数のリクエストを同時に処理します。利用者が同時処理数を設定することはできません。
課金が CPU 時間だけ なので、I/O の待ち時間はそもそも課金されません。マルチコンカレンシーで得たい「待ち時間のコストをなくす」効果が、最初から組み込まれていると言えます。
2. コスト削減の効果
なぜ安くなるのか
AWS Lambda(Event Functions)のように 1インスタンス = 1リクエスト で、経過時間で課金されるサービスでは、I/O を待っている時間も課金 されます。
1インスタンス = 1リクエスト(AWS Lambda Event Functions)
インスタンスA: [CPU][────── DB / LLM の応答待ち ──────][CPU] ← 全体が課金される
インスタンスB: [CPU][────── DB / LLM の応答待ち ──────][CPU] ← 全体が課金される
インスタンスC: [CPU][────── DB / LLM の応答待ち ──────][CPU] ← 全体が課金される
1インスタンス = 複数リクエスト(Google Cloud Run functions など)
インスタンスA: [CPU][CPU][CPU]─── 待ちの間にほかのリクエストを処理 ───[CPU][CPU][CPU]
← 課金されるのは「インスタンスA が処理中の時間」だけ
同時処理数を増やすと、待ち時間を複数のリクエストで共有 できます。そのため、I/O 待ちが長い処理ほど効果が大きくなります。
試算の前提
I/O の待ち時間が長い API を想定します。最近よくある、LLM の API を中継するバックエンドのようなケースです。
| 項目 | 値 |
|---|---|
| リクエスト数 | 月 1,000万(平均 約3.9 リクエスト/秒、トラフィックは一定と仮定) |
| 1リクエストの処理時間 | 2秒(うち CPU を使うのは 20 ms、残りは外部 API の応答待ち) |
| 平均の同時処理数 | 約 7.7(= 3.9 リクエスト/秒 × 2秒) |
| メモリ | 512 MB |
試算の結果
| サービス | 構成 | 月額の目安 |
|---|---|---|
| AWS Lambda(Event Functions) | 512 MB、同時処理数 1(固定) | 約 $162 |
| Google Cloud Run functions | 0.333 vCPU / 512 MiB、同時処理数 1 | 約 $183 |
| Google Cloud Run functions | 1 vCPU / 512 MiB、同時処理数 80 | 約 $63 |
| Azure Functions(Flex Consumption) | 512 MB、同時処理数 1 相当 | 約 $261 |
| Azure Functions(Flex Consumption) | 512 MB、同時処理数 4(既定) | 約 $69 |
| AWS Lambda Web Functions | メモリ 2 GB と仮定、CPU 時間だけで課金 | 約 $28(※) |
| Cloudflare Workers | CPU 時間だけで課金 | 約 $8.4 |
| さくら AppRun(共用型) | 0.5 vCPU / 1 GiB を1台、常時稼働 | 約 3,720円(≒ $24) |
※ AWS Lambda Web Functions は、実行環境1つあたりのメモリ量を公式情報で確認できなかったため、2 GB と仮定しています。
計算の内訳
- AWS Lambda(Event Functions): 0.5 GB × 2秒 × 1,000万 = 1,000万 GB秒。無料枠を引いて $0.0000166667 を掛けると約 $160。リクエスト料金 約 $1.8 を足して 約 $162。
- Google Cloud Run functions(同時処理数 80): インスタンス1台がほぼ常に処理中なので、1か月(約 259万秒)分が課金対象になる。CPU は 1 vCPU × 259万秒 から無料枠を引いて約 $58、メモリは約 $2.3、リクエストは約 $3.2。合計 約 $63。
- Azure Functions(同時処理数 4): 平均の同時処理数 7.7 を 4 ずつ処理するので、インスタンス2台が常に処理中。0.5 GB × 2台 × 259万秒 から無料枠を引いて約 $65、実行数の料金 約 $3.9 を足して 約 $69。
- Cloudflare Workers: CPU 20 ms × 1,000万 = 2億 CPU ms。込みの 3,000万 ms を引いた 1億7,000万 ms × $0.02/100万 = 約 $3.4 に、月額 $5 を足して 約 $8.4(リクエスト数は込みの 1,000万件に収まる)。
試算からわかること
- 同じ Google Cloud Run functions でも、同時処理数を 1 から 80 にするだけで約 1/3 になる($183 → $63)。
- Azure Functions も、既定の同時処理数 4 にするだけで約 1/4 になる($261 → $69)。
- AWS Lambda(Event Functions)は待ち時間がすべて課金される ので、このパターンの処理は苦手。同じ AWS の中なら Web Functions を選ぶと大きく下がる。
- CPU 時間だけで課金される Cloudflare Workers と AWS Lambda Web Functions が、待ち時間の長い処理では最も安い。
この試算は、トラフィックが一定である前提で かなり単純化 したものです。トラフィックに波がある場合や、CPU を多く使う処理の場合は、結果が大きく変わります。CPU を多く使う処理では、同時処理数を増やしてもコストはほとんど下がりません(後述)。
効果が出やすい処理・出にくい処理
| 効果が出やすい(I/O が中心) | 効果が出にくい(CPU が中心) |
|---|---|
| LLM の API の中継・ストリーミング | 画像や動画の変換 |
| DB を読み書きするだけの API | 暗号化やハッシュの計算 |
| 外部の SaaS の API を呼ぶ BFF | 機械学習の推論(CPU で実行するもの) |
| Webhook の受信と転送 | 大きなファイルの圧縮・展開 |
3. コスト以外のメリット
コールドスタートが減る
同じリクエスト数をより少ないインスタンスでさばけるので、新しいインスタンスを起動する回数が減ります。たとえば、同時に100リクエストが来た場合、次のように差が出ます。
| 同時処理数 | 必要なインスタンス数 | コールドスタートの回数(最大) |
|---|---|---|
| 1 | 100 | 100 |
| 80 | 2 | 2 |
DB の接続数が減る
AWS Lambda(Event Functions)で RDB を使うと、インスタンスの数だけ DB への接続が増える ため、接続数があふれる問題が起きがちです(そのために RDS Proxy などを使います)。
マルチコンカレンシーなら、1インスタンスの中のコネクションプールを複数のリクエストで共有 できます。インスタンスの数自体も少ないので、DB の接続数を大きく抑えられます。
メモリ上のキャッシュを共有できる
設定値、認証のトークン、よく参照するマスタデータなどを、インスタンス内のメモリにキャッシュすると、複数のリクエストで使い回せます。同時処理数が多いほど、キャッシュが効く割合が上がります。
クォータやスケールの上限に余裕ができる
AWS Lambda(Event Functions)の「同時実行数 1,000 / リージョン」のように、インスタンス数で決まる上限 に引っかかりにくくなります。Google Cloud Run functions の「100インスタンス / プロジェクト・リージョン」も、同時処理数 80 なら最大 8,000 リクエストを同時に処理できる計算です。
外部サービスへの負荷も下がる
インスタンスごとに走る初期化処理(認証トークンの取得、設定の読み込みなど)の回数が減るので、外部サービスへのリクエスト数やレート制限への影響 も小さくなります。
4. 実装上の注意点
ここからが本題です。マルチコンカレンシーは、「1インスタンス = 1リクエスト」の前提で書かれたコードを、そのまま載せると壊れる ことがあります。
注意点の一覧
| # | 注意点 | 起きること |
|---|---|---|
| 1 | グローバル変数にリクエストごとの情報を入れる | 別のユーザーのデータが混ざる・漏れる |
| 2 |
/tmp に固定のファイル名で書く |
ファイルが上書きされる |
| 3 | メモリを1リクエスト分で見積もる | メモリ不足でインスタンスが落ちる |
| 4 | CPU を多く使う処理を同時に動かす | すべてのリクエストが遅くなる |
| 5 | イベントループや GIL をブロックする | 同じインスタンスのリクエストがすべて止まる |
| 6 | 1つのリクエストでインスタンスがクラッシュする | 処理中のほかのリクエストも巻き添えで失敗する |
| 7 | コネクションプールのサイズが合っていない | 待ち行列ができる、または DB の接続数があふれる |
| 8 | ログにリクエスト ID を付けない | どのリクエストのログか追えない |
① グローバル変数にリクエストの情報を入れない
最も危険なのがこれです。別のユーザーの情報が、別のリクエストのレスポンスに混ざる という、情報漏えいにつながる事故になります。
// グローバル変数にリクエストごとの情報を入れている
let currentUser;
export async function handler(req, res) {
currentUser = await authenticate(req); // リクエスト A がセット
const data = await fetchFromDb(); // ← 待っている間にリクエスト B が currentUser を上書き
res.json({ user: currentUser, data }); // ← A のレスポンスに B のユーザーが入る
}
import { AsyncLocalStorage } from "node:async_hooks";
// リクエストごとの情報は、リクエストのスコープに閉じ込める
const requestContext = new AsyncLocalStorage();
export async function handler(req, res) {
const user = await authenticate(req);
await requestContext.run({ user, requestId: req.headers["x-request-id"] }, async () => {
const data = await fetchFromDb();
res.json({ user: requestContext.getStore().user, data });
});
}
AWS Lambda Managed Instances の Node.js ランタイムでは、リクエストごとの状態を InvokeStore に入れるよう推奨されています。Java ではスレッドセーフなコレクションや ThreadLocal を使います。
グローバルに置いてよいもの と 置いてはいけないもの を区別しましょう。
| グローバルに置いてよい | グローバルに置いてはいけない |
|---|---|
| SDK のクライアント、DB のコネクションプール | ログインしているユーザーの情報 |
| 読み取り専用の設定値 | リクエストの ID、トレースの ID |
| スレッドセーフなキャッシュ | リクエストごとに変わる計算の途中結果 |
② /tmp のファイル名にリクエスト ID を含める
# 同時に動くリクエストが同じファイルを上書きする
with open("/tmp/output.csv", "w") as f:
f.write(data)
import os, uuid
path = f"/tmp/{request_id or uuid.uuid4()}.csv"
try:
with open(path, "w") as f:
f.write(data)
upload(path)
finally:
os.remove(path) # 使い終わったら消す(ディスクもインスタンスで共有している)
③ メモリは「1リクエスト分 × 同時処理数」で見積もる
必要なメモリ ≒ ランタイムの基本使用量 + 1リクエストのピーク使用量 × 同時処理数
1リクエストで 50 MB を使う処理を、同時処理数 16 で動かすと、それだけで 800 MB 必要になります。メモリが足りなくなると、インスタンスが落ちて、処理中のリクエストがすべて失敗 します。
④ CPU を多く使う処理は同時処理数を下げる
CPU を多く使う処理を同時に動かしても、CPU の取り合いになるだけで、1リクエストあたりのレイテンシが悪化 します。Google Cloud Run functions の公式ドキュメントでも、1リクエストが CPU やメモリの大半を使う場合は、同時処理数を 1 にするよう案内されています。
AWS Lambda Web Functions では、レイテンシが悪化したら maxConcurrencyPerEnvironment を下げるよう推奨されています。
⑤ ランタイムごとの並行処理モデルを理解する
| 言語 | 並行処理の仕組み | 注意点 |
|---|---|---|
| Node.js | シングルスレッド + イベントループ | 同期的な重い処理(大きな JSON のパース、同期 I/O など)を書くと、全リクエストが止まる。必ず async/await で書く |
| Python | GIL があるので、スレッドでは CPU 処理が並列にならない | I/O 中心ならスレッドや asyncio で効果がある。Google Cloud Run functions では、スレッド数を同時処理数以上にする(例: 同時処理数 8 なら THREADS=8)。Azure Functions(Flex Consumption)の Python は既定の同時処理数が 1
|
| Java / .NET | マルチスレッド | スレッドセーフなコードを書く。共有するオブジェクトは不変にするか、ロックや同期化されたコレクションを使う |
| Go | goroutine | もともと並行処理に強い。共有データは mutex かチャネルで守る |
⑥ 障害の影響範囲(ブラストラジアス)が広がる
1インスタンス = 1リクエストなら、1つのリクエストでインスタンスが落ちても、影響はそのリクエストだけです。マルチコンカレンシーでは、同じインスタンスで処理中だったリクエストがすべて巻き添え になります。
- 例外を握りつぶさず、リクエスト単位で必ずキャッチ する
- メモリリークが起きないようにする(インスタンスが長く生きるので、リークが溜まりやすい)
- 呼び出し元は リトライと冪等性 を前提に作る
⑦ コネクションプールのサイズを合わせる
DB への最大接続数 ≒ インスタンス数の上限 × 1インスタンスのプールサイズ
- プールサイズが同時処理数より小さいと、プールの空き待ち が発生してレイテンシが悪化する
- プールサイズを大きくしすぎると、インスタンスが増えたときに DB の最大接続数を超える
- インスタンス数の上限(
max-instancesなど)も合わせて設定し、DB の上限を超えないようにする
⑧ ログには必ずリクエスト ID を付ける
複数のリクエストのログが同じインスタンスから混ざって出力されます。構造化ログ(JSON)にリクエスト ID を必ず入れて、リクエスト単位で追えるようにしておきましょう。
導入の進め方
- 同時処理数 1 で動作を確認 する(従来と同じ状態)
- コードを点検する(グローバル変数、
/tmp、同期処理、スレッドセーフ) - 小さめの値から始める(Google Cloud Run functions の公式ドキュメントでは、ソースからデプロイする場合は 8 程度からを推奨)
- 負荷テスト で、レイテンシ、メモリ、エラー率を見ながら少しずつ上げる
- 本番ではメトリクスを監視する(AWS Lambda Web Functions なら
EnvironmentConcurrentRequests、AWS Lambda Managed Instances ならConcurrencyThrottles/CPUThrottles/MemoryThrottlesなど)
AWS Lambda Web Functions では、新しい関数は控えめな同時処理数から始まり、使用状況を学習して調整されます。そのため、最初の負荷テストでは実行環境が多めに使われることがあります。負荷テストは複数回行いましょう。
まとめ
| 観点 | ポイント |
|---|---|
| 対応サービス | Google Cloud Run functions、Azure Functions(Flex Consumption)、AWS Lambda Web Functions、AWS Lambda Managed Instances、さくら AppRun、Cloudflare Workers(自動)。AWS Lambda(Event Functions)だけが 1 で固定 |
| コスト削減 | I/O の待ち時間が長い処理では、同時処理数を上げるだけで 数分の1 になることもある。CPU 中心の処理では効果は小さい |
| ほかのメリット | コールドスタートの減少、DB の接続数の削減、キャッシュの共有、クォータに余裕ができる |
| 注意点 | グローバル変数による情報漏えい が最大のリスク。メモリの見積もり、ランタイムの並行処理モデル、障害の影響範囲、コネクションプールにも注意 |
マルチコンカレンシーは、「設定値を1つ変えるだけで安くなる」機能に見えます。実際には コードがスレッドセーフであることが前提 の機能です。AWS Lambda(Event Functions)からほかのサービスに移す場合や、AWS Lambda Web Functions に切り替える場合は、まずコードの点検から始めましょう。
次回は、マルチクラウド間の移しやすさ(ポータビリティ) を比べる予定です。
参考
- Scaling Lambda Web Functions(AWS)
- Scaling Lambda Managed Instances(AWS)
- Lambda Managed Instances のベストプラクティス(AWS)
- AWS Lambda Managed Instances で実行環境ごとの最大同時実行数をカスタマイズしてみた(DevelopersIO)
- Announcing AWS Lambda Web Functions(AWS News Blog)
- AWS Lambda 料金
- Cloud Run の同時実行について(Google Cloud)
- Cloud Run の料金(Google Cloud)
- Concurrency in Azure Functions(Microsoft Learn)
- Azure Functions の料金
- Cloudflare Workers Pricing
- AppRun コントロールパネル操作ガイド(さくらのクラウド)
- さくらのAppRunとは?料金と共用型・専有型の違い(issoh)
FaaS比較シリーズ 記事一覧
| 回 | 記事 |
|---|---|
| #1 | AWS Lambda を整理する ― 2026年11月版・5つの形態と制約・料金・設計のツボ |
| #2 | 主要CSPのFaaSを横並びで比較する ― AWS Lambdaを軸にGCP・Azure・Cloudflare・さくらのクラウドを整理(2026年11月版) |
| #3 | 運用編 ― デプロイ・監視・ローカルとクラウドの差分を5サービスで比較する(2026年11月版) |
| #4 | 1インスタンスあたりの同時処理数(マルチコンカレンシー)を比較する ― 対応サービス・コスト削減効果・実装の注意点(2026年11月版)(この記事) |
| #5 | FaaS VS コンテナ実行基盤 ― どこからコンテナのほうが安くなるのか?損益分岐点を5社で試算する(2026年11月版) |
| #6 | FaaSとは何だったのか ― 12年の変遷・強み・基盤技術・セキュリティから定義を考え直す |
| #7 | もし今、自分がFaaSを設計するなら ― 12の設計判断とFaaSの未来予想 |