サーバーレス関数(FaaS)とは?4大プラットフォームの選び方と落とし穴
サーバーレス関数(FaaS)の仕組みを最短で理解。コールドスタートや状態を持てない制約、AWS Lambda/Cloud Run/Workers/Vercelの選び方を、判断表とコード付きで整理します。
初めて作ったWebhookの受け口を、僕はうっかり常時起動のサーバーに乗せていました。月の請求を見て青ざめます。1日に数回しか叩かれない処理のために、24時間動きっぱなしのサーバー代を払っていたんです。
「これ、呼ばれた時だけ動いてくれればいいのに」
その「呼ばれた時だけ動く」を実現するのが、サーバーレス関数、いわゆる FaaS(Function as a Service) です。名前は仰々しいけど、考え方はシンプル。電気のスイッチみたいなもので、使う瞬間だけ点いて、終わったら消える。点きっぱなしの電気代は払わなくていい。
ただ、この「消える」性質が曲者で、知らずに使うと別の場所で痛い目を見ます。今日はFaaSの仕組みと、4つの主要プラットフォームの選び方を、僕の失敗込みで整理します。
この記事の要点
- FaaSは「呼ばれた瞬間だけ動いて、終わったら消える」コードの実行方式。サーバーの常時管理が要らない。
- 安いし楽。ただし**コールドスタート(最初の起動が遅い)と状態を持てない(記憶がリセットされる)**という2大制約がある。
- 主要4つは性格が違う。AWS Lambdaは万能型、Cloud Runはコンテナ派、Cloudflare Workersはエッジ最速、Vercelはフロント一体型。
- 選び方は「何とつなぐか」「どこで動かすか」で9割決まる。迷ったら下の判断表で。
- 各プラットフォームの具体的なデプロイ手順は、個別記事へリンクで案内します。
FaaSって、結局どういう仕組み?
普通のWebサーバーは、お店でいうと「24時間営業の店員さん」です。お客さんが来ても来なくても、レジの前に立って待っている。誰も来ない深夜でも給料は発生します。
FaaSはこれを「呼び鈴を押されたら出てくる店員さん」に変えます。リクエストが来た瞬間にコードが起動して、処理を返したら引っ込む。次に呼ばれるまで、お金はかかりません。
もう少し具体的に書くと、FaaSはこんな流れで動きます。
- HTTPリクエストやイベント(ファイルがアップされた、時刻になった、等)が届く
- クラウド側がその場でコードを起動する
- コードが処理してレスポンスを返す
- しばらく呼ばれないと、起動した環境ごと破棄される
ポイントは2番と4番です。サーバーを自分で立てて、OSを更新して、落ちたら再起動して……という運用が丸ごと消えます。これがFaaSの一番おいしいところ。
逆に言うと、4番の「破棄される」せいで、普通のサーバーなら当たり前にできることができなくなります。そこが次の話です。
メリットとデメリットを正直に並べる
魔法ではないので、向き不向きがあります。先に表で全体像を。
| 観点 | FaaSのメリット | FaaSのデメリット |
|---|---|---|
| お金 | 呼ばれた回数だけ課金。アイドル時は基本ゼロ | 大量に呼ばれ続けると常時サーバーより割高になることも |
| 運用 | サーバー管理・OS更新・スケール設定が不要 | ログやデバッグがローカルと違い、追いにくい |
| 起動 | アクセス急増に自動で追従する | コールドスタートで初回が遅い |
| 状態 | ステートレスで水平にスケールしやすい | 関数内に状態を保持できない |
| 実行時間 | 短い処理に最適 | 長時間バッチには制限時間が壁になる |
向いているのは、短くて・状態を外に逃がせて・回数が読めない処理です。Webhookの受け口、画像のサムネ生成の入口、フォーム送信の処理、定期実行のジョブ、軽いJSON API。このあたりはFaaSの独壇場です。
逆に、何時間も回るバッチ処理、常に同じ接続を保ちたいWebSocket、毎秒大量に叩かれ続ける基幹APIは、無理にFaaSにすると後述の制約に殴られます。素直にコンテナや専用サーバーを選んだほうが楽なこともあります。
落とし穴1:コールドスタート(最初の一発が遅い)
FaaSで最初にぶつかるのがこれです。
しばらく呼ばれていない関数は、環境ごと破棄されています。なので次に呼ばれると、クラウドはまず実行環境を一から立ち上げるところから始めます。コードを読み込み、ランタイムを起動し、ようやく処理に入る。この立ち上げ時間が「コールドスタート」です。
体感だと、軽い関数で数百ミリ秒、重い依存を抱えた関数だと数秒かかることもあります。一度温まれば(ウォームスタート)次からは速いんですが、また放置されると冷えます。
僕がやらかしたのは、ユーザーが直接待つログイン画面の裏にコールドスタートしやすい関数を置いたこと。深夜にアクセスして「初回だけやたら遅い」とクレームが来ました。対策はいくつかあります。
- ユーザーが直接待つ画面の真後ろに、重い関数を置かない
- 依存パッケージを減らして起動を軽くする
- どうしても速度が要るなら、常に温めておく仕組み(プロビジョンドコンカレンシー等)を検討する
- そもそもコールドスタートがほぼ無いプラットフォーム(後述のWorkers)を選ぶ
「初回が遅い」は仕様です。設計で逃がすものだと思っておくと、慌てません。
落とし穴2:状態を持てない(記憶がリセットされる)
これがFaaS最大の制約です。慣れるまで何度もハマります。
関数は処理が終わると破棄されるので、関数の中に何かを覚えさせることはできません。たとえば「グローバル変数にカウンターを置いて、呼ばれるたびに増やす」みたいなコードは、動くように見えて動きません。次の呼び出しが別の環境で起動したら、カウンターはゼロに戻っているからです。
具体的に、やりがちな失敗を挙げます。
- ログイン状態を関数のメモリに保持する → 次のリクエストで消える
- アップロード途中のファイルを一時変数に溜める → 途中で別環境に飛んで壊れる
- 「2回目の呼び出しは無視」をメモリ上のフラグで判定する → フラグが共有されず二重実行
ではどうするか。答えは一貫していて、状態は全部、外のストレージに逃がすです。データベース、KVストア、オブジェクトストレージ。関数自身は「来たデータを処理して、結果を外に書いて、返す」だけの、記憶を持たない係に徹します。
この「ステートレスに徹する」発想こそが、FaaSが自動で大量スケールできる理由でもあります。どの環境で動いても結果が同じだから、クラウドは安心していくつでもコピーを起動できるわけです。制約と利点は表裏一体なんですね。
落とし穴3:「一度だけ実行」を信じてはいけない
もうひとつ、状態と並んで大事なのが**冪等性(べきとうせい)**です。
聞き慣れない言葉ですが、意味は「同じリクエストが何回来ても、結果が壊れない性質」のこと。なぜこれが要るかというと、FaaSを呼ぶ側(Webhookの送信元、キュー、ユーザーのブラウザ)は、タイムアウトや失敗を疑うと平気で同じリクエストを再送するからです。
決済のWebhookを想像してください。処理に時間がかかってタイムアウトすると、送信元は「届かなかったかも」と判断してもう一度送ってきます。冪等性を考えていないと、ここで二重決済が発生します。これは事故です。
対策は「同じリクエストかどうかを見分ける鍵」を持つこと。idempotency-keyヘッダーや、外部のイベントID、注文IDをユニークキーとして外部ストアに保存し、すでに処理済みなら同じ結果を返すだけにします。下のコードで、その最小形を動かしてみます。
コピペで動く:冪等性つきの最小ハンドラー
プラットフォーム固有の話に入る前に、FaaSの「中身」がどんな形か手元で動かしてみましょう。AWS Lambda風のHTTPイベントを受け取り、冪等性を効かせる最小のハンドラーです。クラウドにデプロイせず、Node.jsだけで動きます。外部パッケージも要りません。
// handler.mjs
import crypto from "node:crypto";
// 注意: これはローカル確認用。本番ではこのMapを
// 外部ストア(DynamoDB / KV / DBのユニーク制約)に置き換える
const seen = new Map();
function json(statusCode, body) {
return { statusCode, headers: { "content-type": "application/json" }, body: JSON.stringify(body) };
}
export async function handler(event = {}) {
const method = event.requestContext?.http?.method ?? "GET";
const path = event.rawPath ?? "/";
// 受け付けるのは POST /orders だけ
if (method !== "POST" || path !== "/orders") {
return json(404, { error: "not_found" });
}
// 冪等性キーが無ければ弾く(再送を見分けられないため)
const key = event.headers?.["idempotency-key"];
if (!key) return json(400, { error: "idempotency_key_required" });
// 同じキーで来たら、処理し直さず前回の結果を返す
if (seen.has(key)) {
return json(200, { ...seen.get(key), replay: true });
}
// 本体の処理(ここでは注文受付)
let body;
try {
body = JSON.parse(event.body ?? "{}");
} catch {
return json(400, { error: "invalid_json" });
}
if (!Number.isFinite(body.amount) || body.amount <= 0) {
return json(400, { error: "invalid_order" });
}
const accepted = { orderId: crypto.randomUUID(), status: "accepted", amount: body.amount };
seen.set(key, accepted); // 結果を記録(本番は外部ストアへ)
return json(202, accepted);
}
// --- ローカル確認: 同じイベントを2回投げてみる ---
const event = {
rawPath: "/orders",
requestContext: { http: { method: "POST" } },
headers: { "idempotency-key": "demo-001" },
body: JSON.stringify({ amount: 3200 }),
};
console.log("1回目:", (await handler(event)).body);
console.log("2回目:", (await handler(event)).body); // replay: true が付く
実行はこれだけ。
node handler.mjs
2回目のレスポンスに"replay":trueが付けば、同じリクエストの再送を壊さず処理できています。注目してほしいのは、結果を覚えているseenが関数の外に置く前提だとコメントしている点です。落とし穴2と3が、コードの形でつながっているのが見えると思います。本番ではこのMapを、次の各プラットフォームのストレージに置き換えます。
4大プラットフォームの選び方
ここからが本題の「選び方」です。主要4つは、どれも「呼ばれた時だけ動く」点は同じですが、得意分野がはっきり分かれます。まず一覧で。
| プラットフォーム | 一言で言うと | 得意な処理 | 状態の置き場 | 詳しい記事 |
|---|---|---|---|---|
| AWS Lambda | 万能・連携の王様 | AWSサービスとの連携、業務API、非同期ジョブ | DynamoDB / S3 | AWS Lambda入門 |
| Cloud Run | コンテナをそのまま動かす | 既存Dockerイメージ、重めの処理、移植性重視 | Cloud SQL / Firestore | Cloud Run入門 |
| Cloudflare Workers | エッジで世界一速い起動 | 軽いAPI、認証、リダイレクト、キャッシュ制御 | KV / D1 / R2 | Cloudflare Workers入門 |
| Vercel Functions | フロントと一体 | Next.jsアプリのAPI、OG画像生成、Middleware | 外部DB / Vercel KV | Vercel Edge実務ガイド |
それぞれ、どんな時に選ぶかを掘り下げます。
AWS Lambda:迷ったらここ、特にAWSを使っているなら
すでにS3にファイルを置いている、DynamoDBにデータがある、SQSでキューを回している——こういうAWSの世界に住んでいるなら、Lambdaが圧倒的に楽です。同じ権限の仕組み(IAM)でつながり、イベントの種類も豊富。「S3にファイルが置かれたら起動」「毎朝9時に起動」みたいなトリガーが標準でそろっています。
弱点はコールドスタートがそれなりにあること、そしてIAM権限の設定が初心者には難しいことです。最初の関数の作り方やトリガー4種の選び方は、AWS Lambda入門に手順をまとめています。
Cloud Run:コンテナ資産があるなら最有力
「FaaSは便利だけど、ランタイムやパッケージの制約に縛られたくない」「すでにDockerで動くものがある」。そういう人にはGoogle CloudのCloud Runが刺さります。
厳密にはCloud Runは「コンテナを動かすサービス」で純粋なFaaSとは少し毛色が違いますが、リクエストが無ければゼロまでスケールして課金が止まる点はFaaSと同じ感覚で使えます。Dockerイメージさえあれば、言語もパッケージも自由。移植性が高いのが最大の魅力です。手順はCloud Run入門へ。
Cloudflare Workers:とにかく速さとエッジが欲しいなら
コールドスタートにうんざりしているなら、Workersを試す価値があります。世界中のエッジ(ユーザーに近い拠点)で動き、起動がほぼ一瞬。ユーザーに近い場所で実行されるので、応答も速いです。
軽いAPI、認証チェック、リダイレクト、A/Bテストの分岐、キャッシュ制御。このあたりはWorkersの得意領域です。ただしNode.jsとは完全互換ではなく、使えないパッケージがあったり、CPU実行時間の制限が独特だったりします。この壁の越え方はCloudflare Workers入門で実例つきで説明しています。
Vercel Functions:フロントと一緒に持ちたいなら
Next.jsでフロントを作っているなら、APIを別の場所に分けず、同じプロジェクトの中に置けるのがVercelの強みです。OG画像の生成、Middlewareでの認証、軽いAPIエンドポイント。フロントとバックを行き来する手間が消えます。署名検証やA/Bテストといった実務での使い方と落とし穴は、Vercel Edge実務ガイドにまとめました。
どう選ぶ?3つの質問で絞る
表を見ても迷うときは、自分にこの3問を投げると一気に絞れます。
- 何とつなぐ? すでにAWSにデータがあるならLambda。Google Cloudなら Cloud Run。特定クラウドに縛られていないなら次へ。
- コンテナ資産はある? 動くDockerイメージがあるなら Cloud Run が最短。無いなら次へ。
- 速さ重視? フロント一体? コールドスタートを避けたい・エッジで速くしたいなら Workers。Next.jsアプリと一緒に持ちたいなら Vercel。
正直、最初の1本ならどれを選んでも学びになります。完璧な選択を悩むより、小さい関数を1つデプロイして、コールドスタートと状態の制約を肌で感じるほうが何倍も早く理解できます。
よくある質問
Q. サーバーレスって、本当にサーバーが無いんですか? いいえ。サーバーはクラウド側にちゃんとあります。「自分で管理しなくていい」という意味で「レス」と呼んでいるだけです。サーバーの存在を意識しなくて済む、が正確なところです。
Q. コールドスタートはどのくらい遅いですか? 関数の重さ次第ですが、軽いもので数百ミリ秒、重い依存を抱えると数秒のこともあります。Cloudflare Workersのようにエッジで動くものはほぼ体感ゼロです。ユーザーが直接待つ画面の裏には、重い関数を置かない設計が無難です。
Q. なぜ関数の中に状態を持てないんですか? 処理が終わると実行環境ごと破棄され、次の呼び出しは別の環境で起動するかもしれないからです。メモリ上の変数は引き継がれません。状態はデータベースやKVなど外部ストレージに逃がすのが鉄則です。
Q. 結局どれを選べばいいですか? すでに使っているクラウドに合わせるのが一番楽です。AWSならLambda、Google Cloudなら Cloud Run。特に縛りがなく速さが欲しいならWorkers、Next.jsと一体ならVercel。上の3つの質問で絞ってください。
Q. 料金は本当に安くなりますか? 呼ばれる回数が少なく、波がある処理なら大きく下がります。逆に毎秒大量に叩かれ続ける処理だと、常時起動のサーバーより割高になることもあります。アクセスのパターン次第です。
まとめ:制約を知れば、FaaSは怖くない
FaaSは「呼ばれた時だけ動いて、終わったら消える」コードの実行方式です。サーバー管理から解放され、波のあるアクセスに自動で追従し、アイドル時はお金がかからない。小さなAPIやWebhook、定期ジョブの入口には、これ以上ない選択肢になります。
ただし「消える」性質から、コールドスタートで初回が遅い、関数に状態を持てない、同じリクエストが再送される、という3つの制約がついて回ります。これらは仕様であって、バグではありません。状態は外に逃がす、冪等性で再送を吸収する、重い関数はユーザーの真後ろに置かない——この3つを最初から設計に入れておけば、本番で青ざめることはぐっと減ります。
プラットフォーム選びは「何とつなぐか」「どこで動かすか」で9割決まります。各サービスの具体的なデプロイ手順は、AWS Lambda入門・Cloud Run入門・Cloudflare Workers入門・Vercel Edge実務ガイドに分けてまとめてあります。シークレットの安全な扱いはシークレット管理、API全体の設計はAPI開発の実践手順もあわせてどうぞ。公式の一次情報としては、AWS Lambda Documentationが出発点として読みやすいです。
僕自身、最初の請求で青ざめてからFaaSに乗り換え、今では小さな処理の大半をここに寄せています。コールドスタートと状態の制約に何度かやられましたが、一度コツを掴むと「呼ばれた時だけ動く」気軽さは手放せません。まずは下書きのWebhookでも、1本デプロイしてみてください。手を動かした時間が、表を眺めるより早く効きます。実務に効くテンプレートは教材一覧に、導入相談は研修・相談にまとめています。
無料PDF: Claude Code はじめてのチートシート
まずは無料PDFで基本コマンドと最初の使い方をまとめて確認してください。登録後はそのままテンプレート集や導入相談にも進めます。
スパムは送りません。登録情報は厳重に管理します。
Claude Codeを仕事で使える形にしませんか?
まず無料PDFで基本を固め、繰り返し使う作業はGumroad教材へ、チーム導入や権限設計は導入相談へ進めます。
この記事を書いた人
Masa
Claude Codeの実務活用、導入設計、収益導線改善を検証しているエンジニア。10言語の技術メディアを運営中。
関連書籍・参考図書
この記事のテーマに関連する書籍を楽天ブックスで探せます。
※ 当サイトは楽天市場のアフィリエイトプログラムに参加しています。上記リンクから商品をご購入いただくと、運営者に紹介料が支払われる場合があります。
関連記事
制作会社がClaude Codeに触らせる前に決める権限チェックリスト
クライアントサイトを壊さずにAI編集を使うための、制作会社向け権限と確認の型です。
SaaSサポートのバグ報告をClaude Codeで再現手順に変える実務フロー
問い合わせ文をそのまま開発へ投げず、再現手順、証拠、次の一手に整えるサポート向け手順です。
Obsidianの古いメモをClaude Codeの指示書に変える10分ルーチン
Obsidianに溜めたメモが毎回ゴミになる人へ。事実・決定・未確認に仕分けして、Claude Codeがそのまま動ける指示書に変える朝の10分の型を紹介します。