Lambda SnapStartとは
AWS Lambda SnapStartは、関数の初期化済みスナップショットを保存し、コールドスタート時にそれを復元することで、起動時間を大幅に短縮する機能です。
対応言語
| ランタイム | サポート状況 |
|---|---|
| Java 11, 17, 21 | ✓ 完全サポート |
| Python 3.12+ | ✓ サポート |
| .NET 8 | ✓ サポート |
| Node.js | 今後対応予定 |
仕組み
通常のコールドスタート:
1. コンテナ起動
2. ランタイム初期化
3. 関数コード読み込み
4. 初期化コード実行
5. ハンドラー実行
→ 合計: 2-10秒(Javaの場合)
SnapStart:
1. キャッシュされたスナップショットを復元
2. ハンドラー実行
→ 合計: 200-500ms
スナップショットのライフサイクル
flowchart TB
subgraph FirstDeploy["初回デプロイ時"]
F1["1. 関数を初期化"]
F2["2. 初期化後のメモリ状態をスナップショット"]
F3["3. スナップショットをキャッシュに保存"]
F1 --> F2 --> F3
end
subgraph LaterStart["以降の起動時"]
L1["1. キャッシュからスナップショットを復元"]
L2["2. afterRestore フックを実行"]
L3["3. ハンドラーを実行"]
L1 --> L2 --> L3
end
FirstDeploy --> LaterStart
設定方法
AWS Console
Lambda > 関数 > 設定 > 一般設定 > SnapStart
→ "PublishedVersions" を選択
AWS SAM
# template.yaml
Resources:
MyFunction:
Type: AWS::Serverless::Function
Properties:
Runtime: java21
Handler: com.example.Handler::handleRequest
SnapStart:
ApplyOn: PublishedVersions
AutoPublishAlias: live
Terraform
resource "aws_lambda_function" "example" {
function_name = "my-function"
runtime = "java21"
handler = "com.example.Handler::handleRequest"
snap_start {
apply_on = "PublishedVersions"
}
}
resource "aws_lambda_alias" "live" {
name = "live"
function_name = aws_lambda_function.example.function_name
function_version = aws_lambda_function.example.version
}
ランタイムフック
Java (CRaC)
import org.crac.Context;
import org.crac.Core;
import org.crac.Resource;
public class Handler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent>, Resource {
private Connection dbConnection;
public Handler() {
// 初期化時に登録
Core.getGlobalContext().register(this);
// DB接続を確立
this.dbConnection = createConnection();
}
@Override
public void beforeCheckpoint(Context<? extends Resource> context) {
// スナップショット前にDB接続をクローズ
dbConnection.close();
}
@Override
public void afterRestore(Context<? extends Resource> context) {
// 復元後にDB接続を再確立
this.dbConnection = createConnection();
}
@Override
public APIGatewayProxyResponseEvent handleRequest(
APIGatewayProxyRequestEvent event,
Context context) {
// ハンドラーロジック
}
}
Python
import boto3
from aws_lambda_powertools import Logger
logger = Logger()
# グローバル変数(スナップショットに含まれる)
db_client = None
def init_db():
global db_client
db_client = boto3.client('dynamodb')
# 初期化フェーズで実行
init_db()
# 復元後に再初期化が必要な場合
def on_restore():
global db_client
# 接続をリフレッシュ
db_client = boto3.client('dynamodb')
def handler(event, context):
# スナップショットから復元されたdb_clientを使用
return db_client.get_item(...)
注意点
一意性の確保
// 悪い例: スナップショット時の値が使い回される
private final String uniqueId = UUID.randomUUID().toString();
// 良い例: リクエストごとに生成
public APIGatewayProxyResponseEvent handleRequest(...) {
String uniqueId = UUID.randomUUID().toString();
// ...
}
ネットワーク接続
// スナップショット前に接続を閉じる
@Override
public void beforeCheckpoint(Context<? extends Resource> context) {
httpClient.close();
dbConnection.close();
}
// 復元後に再接続
@Override
public void afterRestore(Context<? extends Resource> context) {
httpClient = HttpClient.newHttpClient();
dbConnection = dataSource.getConnection();
}
パフォーマンス比較
Spring Boot (Java 17):
- 通常: 6,000ms
- SnapStart: 400ms (93%削減)
Quarkus (Java 17):
- 通常: 1,500ms
- SnapStart: 200ms (87%削減)
Python:
- 通常: 800ms
- SnapStart: 150ms (81%削減)
料金
追加料金なし
- SnapStart自体は無料
- 通常のLambda料金のみ
- スナップショットストレージも無料
ベストプラクティス
✓ 初期化コードを最適化(重い処理は初期化時に)
✓ beforeCheckpoint/afterRestoreフックを適切に実装
✓ 一意性が必要な値はリクエストごとに生成
✓ 接続プールは復元後にリフレッシュ
✓ バージョン/エイリアスを使用
まとめ
Lambda SnapStartは、コールドスタートの問題を劇的に改善する機能です。特にJavaなど起動時間が長いランタイムで効果が大きく、追加料金なしで利用できます。適切なランタイムフックの実装により、本番環境で安全に活用できます。
← 一覧に戻る