サーバーレスとは — FaaS と BaaS の理解
ダイチは週末の午後、カフェでノートパソコンを広げた。画像リサイズ処理のLambda移行に向けて、まずは「サーバーレスとは何か」を正しく理解するところから始めようと思っていた。
「サーバーレス」という言葉は少し誤解を招く。サーバーが存在しないわけではない。AWS のデータセンターにはサーバーがある。ただ、そのサーバーの管理をあなたが行わなくていい——それがサーバーレスの本質だ。
サーバーレスの二つの柱
サーバーレスアーキテクチャは大きく二つのカテゴリに分かれる。
FaaS — Function as a Service
コードを「関数」単位で実行する仕組み。AWS Lambda がその代表格だ。
- イベントに応じてトリガーされる: HTTPリクエスト、S3へのファイルアップロード、SQSへのメッセージ投入など
- ステートレス: 各実行は独立しており、実行間で状態を保持しない
- 短命: 最大15分(Lambda の場合)
- 自動スケーリング: 同時リクエスト数に応じて自動的にインスタンスが増える
BaaS — Backend as a Service
データベース、認証、ストレージなどのバックエンド機能を、マネージドサービスとして利用する仕組み。
| BaaS カテゴリ | AWS サービス | 用途 |
|---|---|---|
| データベース | DynamoDB, Aurora Serverless | データ永続化 |
| オブジェクトストレージ | S3 | ファイル保存 |
| 認証 | Cognito | ユーザー管理 |
| メッセージキュー | SQS, SNS | 非同期通信 |
| API管理 | API Gateway | HTTP エンドポイント |
INFO
サーバーレスアーキテクチャとは「FaaS + BaaS の組み合わせでアプリケーションを構築するアプローチ」と理解すると分かりやすい。Lambdaだけがサーバーレスではない。
Lambda の実行モデル
ダイチが最も知りたかったのは「Lambda は具体的にどう動くのか」だった。
実行フロー
コールドスタートとは、Lambdaの実行コンテナが初めて起動される時間のこと。コンテナのプロビジョニング、ランタイムの読み込み、関数コードの初期化が発生する。Ruby では通常100〜500ms程度かかる。
ウォームスタートは、既に起動済みのコンテナが再利用される場合。ハンドラの実行だけなので数ms〜数十msで応答する。
同時実行の仕組み
3つのリクエストが同時に来れば、3つのLambdaインスタンスが並行して実行される。EC2のように「サーバーが足りない」という状況は起きない(同時実行数の上限はあるが、デフォルト1000で申請により増やせる)。
サーバーレスのトレードオフ
「サーバーレスは万能ではない」とダイチは資料に書き込んだ。
向いているユースケース
- 不規則なトラフィック: セール時だけ急増するECサイトのAPIなど
- イベント駆動処理: ファイルアップロード後の変換処理、通知送信など
- マイクロサービスの個々の機能: 独立した小さな処理単位
- バッチ処理: 定時実行のデータ集計など
向いていないユースケース
- 長時間実行処理: Lambda の最大実行時間は15分
- 低レイテンシが必須: コールドスタートが問題になる
- 大量のメモリが必要: 最大10GBだが、それを超える処理
- 常時接続が必要: WebSocket(API Gateway の WebSocket APIで対応可能ではある)
WARNING
サーバーレスへの移行は段階的に行うのが賢明。「全てをLambdaに」ではなく、「この処理はLambdaに向いているか」を都度判断する。
Rails との概念比較
ダイチはRailsエンジニアとして、Lambdaのモデルをよく知っている概念に置き換えて理解しようとした。
| Rails | Lambda |
|---|---|
ApplicationController | Lambda ハンドラ関数 |
before_action | Lambda Layer / ミドルウェア |
config/routes.rb | API Gateway のルーティング |
config/environments/ | 環境変数 |
Gemfile | Gemfile + Lambda Layer |
| Puma プロセス | Lambda 実行コンテナ |
rails console | Lambda テスト呼び出し |
Rails では rails server で常駐プロセスが起動し、リクエストを受け付け続ける。Lambda では「コードをデプロイしておき、リクエストが来たときだけ起動する」という発想の転換が必要だ。
Lambda のランタイムと実行環境
Lambda がサポートするランタイムは多岐にわたる。
# Ruby 3.2 での Lambda ハンドラの基本構造
# handler: lambda_function.lambda_handler と設定する場合
def lambda_handler(event:, context:)
# event: トリガーからのデータ(Hash)
# context: 実行環境の情報(残り時間、関数名など)
puts "Function name: #{context.function_name}"
puts "Remaining time: #{context.get_remaining_time_in_millis}ms"
puts "Event: #{event.inspect}"
# レスポンスは Hash で返す
{
statusCode: 200,
body: JSON.generate({ message: 'Hello from Lambda!' })
}
endevent オブジェクトはトリガーによって異なる。API Gateway からのHTTPリクエストであれば、HTTPメソッド、パス、ヘッダー、ボディが含まれる。S3からのトリガーであれば、バケット名とオブジェクトキーが含まれる。
サーバーレスの責任モデル
従来のEC2 vs Lambdaで、何を管理する必要があるかが大きく変わる。
| 管理項目 | EC2 | Lambda |
|---|---|---|
| ハードウェア | AWS | AWS |
| ハイパーバイザー | AWS | AWS |
| OS | あなた | AWS |
| ランタイム | あなた | AWS(選択のみ) |
| アプリコード | あなた | あなた |
| スケーリング | あなた | AWS |
| 可用性 | あなた | AWS |
| パッチ適用 | あなた | AWS |
ダイチが担当していた「深夜3時のサーバー障害対応」の多くは、「あなた」の行に書かれた管理項目から発生していた。Lambdaに移行することで、管理すべき範囲がアプリケーションコードだけに絞り込まれる。
まとめ
ダイチはカフェのノートを閉じた。整理できた概念をSlackのメモチャンネルに書き残す。
- サーバーレス = サーバーが無いのではなく、サーバーの管理をしなくていい
- FaaS(Lambda)+ BaaS(DynamoDB, S3 etc.)の組み合わせ
- イベント駆動、ステートレス、自動スケーリングが特徴
- 向き・不向きを見極めることが大事
次のステップは、実際に手を動かすことだ。画像リサイズ処理のLambda移行、その第一歩として「Hello World」から始めよう。