はじめに
AWS re:Invent 2025 で、AWS Lambda の新機能 「Lambda Durable Functions」 が発表されました。これまで AWS Lambda は 1 回の実行につき最大 15 分 という制限があり、「数十分〜数日待ってから再開する」といった処理は、Step Functions や外部データストアを組み合わせる必要がありました。Lambda Durable Functions を利用すると、ワークフローの実行状態を最大 1 年間保持でき、途中まで実行した処理を、指定したタイミングで安全に再開できます(※ 1 回あたりの Lambda 実行時間の上限は従来どおり 15 分です)。
想定されるユースケース
Lambda Durable Functions は、以下のようなケースで特に威力を発揮します。
- ユーザー登録・申し込みから 数十分〜数日後 に通知を送信する処理
- 無料トライアル開始後、期限前にリマインドメールを送るフロー
- 管理者やユーザーの 承認操作を待ってから再開するワークフロー
- 外部 API の制限を考慮した 長時間ジョブの分割実行
- 一時的な障害発生後、途中状態から安全に再実行したい処理
従来は Step Functions や DynamoDB などを組み合わせて実装していたような処理を、
よりシンプルに構築できるようになります。
それでは、実際に Lambda Durable Functions を使ったハンズオンをやってみましょう!
ハンズオン概要
このハンズオンでは、AWS Lambda の新機能である Durable Functions(永続実行)を使用して、ユーザーの無料トライアル開始から20分後に自動的に通知を送信するワークフローを構築します。
全体アーキテクチャ
- Amazon SNS(Standard):メール配信(Topic + Subscription)
- AWS Lambda(Durable Functions 有効):20分待って SNS Publish
手順
ステップ 1:SNS トピック作成 & Subscription
1.1 SNS トピックの作成
- AWS マネジメントコンソールで SNS を開きます。
- 左メニュー 「トピック」 → 「トピックの作成」 をクリックします。
- 以下を設定します。
- 種別:Standard
- 名前:
DurableReminderTopic
- 「トピックの作成」 をクリックします。
- 作成後に表示される Topic ARN を控えます(あとで Lambda の環境変数に入れます)。
1.2 メール購読(Subscription)の作成
- 作成したトピック詳細画面で 「サブスクリプションの作成」 をクリックします。
- 以下を設定します。
- プロトコル:Eメール
- エンドポイント:通知を受け取りたいメールアドレス
- 「サブスクリプションの作成」 をクリックします。
- 入力したメールアドレス宛に届くメールの 「Confirm subscription」 をクリックし、購読を確定します。
- SNS コンソールへ戻り、サブスクリプションが 「確認済み」 になっていることを確認します。
ステップ 2:Lambda(Durable Functions)を作成
2.1 Lambda 関数の作成
- AWS マネジメントコンソールで Lambda を開きます。
- 「関数の作成」 → 「一から作成」 を選びます。
- 以下を設定します。
- 関数名:
MyDurableSnsFunction - ランタイム:Node.js 24.x
- (重要)Durable execution(永続実行)を有効化
- 関数名:
- 「関数の作成」 をクリックします。
2.2 Durable 側の設定
Durable Functions は “待機してから再開する” ため、永続実行の設定が重要です。
- 関数画面の Durable永続設定を開きます。
- 以下を目安に設定します。
- ExecutionTimeout(永続実行タイムアウト):30分
ExecutionTimeout が短いと、20分待つ前に永続実行がタイムアウトして失敗します。
2.3 環境変数の設定
- 「設定」 → 「環境変数」 を開き、「編集」 をクリックします。
- 以下を追加します。
- キー:
SNS_TOPIC_ARN - 値:ステップ 1 で控えた SNS Topic ARN
- キー:
- 保存します。
ステップ 3:IAM(権限)の設定
Durable Functions は内部でチェックポイント(状態保存/取得)を使うため、Durable用の権限が必要です。
ただし コンソールで Durable Function として作成した場合、チェックポイント関連の権限は自動で付与されます
ここでは追加で必要な SNS Publish 権限だけ最小で付与します。
3.1 実行ロールに sns:Publish を付与
- Lambda 関数画面 → 「設定」 → 「アクセス権限」 を開きます。
- 実行ロールのリンクをクリックして IAM へ移動します。
- 「許可を追加」→「ポリシーをアタッチ」 を選びます。
- ポリシー一覧から
AmazonSNSFullAccessを検索し、チェックを入れます。 - 「許可を追加」 をクリックしてポリシーをアタッチします。
ステップ 4:Lambda コード を用意
4.1 作業ディレクトリ作成
ローカルで以下を実行します。
mkdir durable-sns-demo
cd durable-sns-demo
npm init -y
npm install @aws/durable-execution-sdk-js @aws-sdk/client-sns
4.2 index.mjs を作成
import { withDurableExecution } from "@aws/durable-execution-sdk-js";
import { SNSClient, PublishCommand } from "@aws-sdk/client-sns";
const snsClient = new SNSClient({});
export const handler = withDurableExecution(async (event, context) => {
console.log("受信イベント:", JSON.stringify(event));
// CLI invoke: { "userId": "xxx" }
// Function URL等: { body: "{\"userId\":\"xxx\"}" } も想定して吸収
const body =
typeof event?.body === "string" ? JSON.parse(event.body) : (event ?? {});
const userId = body?.userId;
if (!userId) {
return {
statusCode: 400,
body: JSON.stringify({ error: "userId is required" }),
};
}
console.log(`[開始] userId=${userId}`);
// 20分待機(1200秒)
await context.wait({ seconds: 1200 });
// 外部副作用(SNS Publish)は step に閉じ込める
await context.step("publish-followup-mail", async () => {
const message = `【無料トライアル】${userId}さん、開始から20分経過しました。使い方ガイドはこちら…`;
await snsClient.send(
new PublishCommand({
TopicArn: process.env.SNS_TOPIC_ARN,
Subject: "無料トライアル:オンボーディングのご案内",
Message: message,
})
);
return { ok: true };
});
console.log("[完了] SNS送信に成功しました。");
return {
statusCode: 200,
body: JSON.stringify({ message: "Workflow completed" }),
};
});
4.3 ZIP を作成
zip -r deploy.zip .
ステップ 5:Lambda へアップロード
- Lambda コンソール → 対象関数を開きます。
- 「コード」 タブで 「アップロード元」→「.zip ファイル」 を選択します。
-
deploy.zipをアップロードします。 - 保存します。
ステップ 6:エイリアス作成
Durable Functions は エイリアスでの呼び出しが前提になります。
安全のため、エイリアス prod を作ります。
- Lambda 関数画面で 「エイリアス」 を開きます。
- 「エイリアスを作成」 をクリックします。
- 以下を設定します。
- 名前:
prod - バージョン:
$LATEST
- 名前:
- 作成します。
ステップ 7:Lambda コンソールからテスト実行(Durable Functions)
Lambda コンソールの 「テスト」機能を使って、Durable Functions を 非同期で実行します。
7.1 テストイベントの設定
-
Lambda 関数画面を開き、右上の 「テスト」 をクリックします。
-
イベントアクションで
「保存されたイベントを編集」(または新規作成)を選択します。 -
以下を設定します。
-
永続実行名(オプション)
※ Durable Execution を識別するための名前です
test -
呼び出しタイプ
非同期 -
イベント名
TestEvent -
イベント JSON
{ "userId": "ユーザー名" }
-
永続実行名(オプション)
-
「保存」 をクリックします。
7.2 テスト実行
- 設定を保存後、右上の 「テスト」 をクリックします。
- ステータスが 成功 になることを確認します。
非同期実行のため、ここでは処理完了を待ちません。
「成功」は 受け付けられたことを意味します。
7.3 実行直後の確認(CloudWatch Logs)
テスト実行後、まず Durable Function が起動し、待機処理に入っていることを確認します。
- Lambda 関数画面 → 「モニタリング」 を開きます。
- 「CloudWatch のログを表示」 をクリックします。
- 最新のログストリームを開き、以下のログが出ていることを確認します。
受信イベント: {"userId":"ユーザー名"}
[開始] userId=ユーザー名
7.4 再開後の確認(Durable による再実行)
待機時間20分が経過すると、Durable Functions によって処理が再開され、
SNS 送信処理が実行されます。
CloudWatch Logs には、次のログが追加されます。
[完了] SNS送信に成功しました。
続いて、Lambda の実行レポートが出力されます。
{
"type": "platform.report",
"record": {
"status": "success",
"metrics": {
"durationMs": 1704.706,
"billedDurationMs": 2326
}
}
}
ここで重要なのは、
- 待機時間(20分)は duration に含まれていない
- 実際に課金されるのは、
「起動 → 状態保存 → 再開 → SNS送信」の 実行時間のみ
という点です。
7.5 メール受信の確認
同じタイミングで、SNS から以下の内容のメールが届きます。
- 件名:無料トライアル:オンボーディングのご案内
- 宛先:ステップ1で購読したメールアドレス
これで、
「非同期起動 → Durable による待機 → 再開 → SNS送信」
が正しく動作していることを確認できます。
クリーンアップ
ハンズオンが終わったら、不要なリソースを削除します。
SNS トピックの削除
- SNS → トピック →
DurableReminderTopicを選択します。 - 「削除」 をクリックします。
- 確認ダイアログで指示どおり入力し、削除します。
※ トピックを消すとサブスクリプションも一緒に消えます。
Lambda 関数の削除
- Lambda → 関数一覧で
MyDurableSnsFunctionを選択します。 - 「アクション」→「削除」 を実行します。
CloudWatch Logs の削除
- CloudWatch → ロググループを開きます。
-
/aws/lambda/MyDurableSnsFunctionを選択します。 - 「アクション」→「ロググループの削除」 を実行します。
まとめ
このハンズオンでは、AWS Lambda Durable Functions を使用して、長時間待機を伴うワークフローを実装しました。
Durable Functions の主な利点は以下の通りです。
-
待機中はコンピュート課金が発生しない
処理の状態は永続化されますが、待機中に Lambda が実行され続けることはなく、
課金されるのは「実際に処理が動いた時間」のみです。 -
長時間ワークフローを Lambda 単体で実装できる
最大 1 年間の状態保持が可能なため、
「数十分〜数日後に再開する」処理を追加サービスなしで実現できます。 -
リプレイにより安全に再実行できる
障害や再起動が発生しても、保存されたチェックポイントから処理を再開でき、
ワークフロー全体の信頼性が向上します。
