[新機能] 最大1年間実行可能なAWS Lambda Durable Functionsがリリースされたので、公式のサンプルコードを試してみた! #AWSreInvent

[新機能] 最大1年間実行可能なAWS Lambda Durable Functionsがリリースされたので、公式のサンプルコードを試してみた! #AWSreInvent

2025.12.03

リテールアプリ共創部 マッハチームのるおんです。

AWS re:Invent 2025にて、AWS Lambda Durable Functions が発表されました!

https://aws.amazon.com/about-aws/whats-new/2025/12/lambda-durable-multi-step-applications-ai-workflows/

今回は、Durable Functionsの概要の紹介と実際に公式ドキュメントにあるサンプルコードを試してみて挙動を確認してみたいと思います。

Lambda Durable Functionsとは

https://docs.aws.amazon.com/lambda/latest/dg/durable-functions.html

Lambda関数内で 最大1年間実行可能な復元力のあるマルチステップアプリケーション を構築できる新機能です。
これまでマルチステップのワークフローを構築する際は、Step Functionsを使うか、自前で状態管理やリトライロジックを実装する必要がありました。しかし、Durable Functionsを使えば、通常のシーケンシャルなコードを書くだけ で、自動的にチェックポイントの保存とリトライ処理が行われるようになります。

さらに、Lambda関数の15分間実行時間という制約があるため、長期間のワークフローを実現するには様々な工夫が必要でした。しかし、Durable Functionsを使えば、最大1年間実行可能 なワークフローを1つのLambda関数で構築できるようになります。

主な特徴

特徴 説明
復元力のあるコード記述 組み込みチェックポイント機能により、障害処理が自動化
最大1年間の実行 長時間のワークフローでも継続的に実行可能
コスト効率 待機中はコンピュート料金が発生しない
運用の簡潔性 インフラストラクチャ管理不要、状態管理とリトライは自動処理

想定されるユースケース

  • 決済フロー: 支払い・在庫・配送の複数サービス間調整
  • AIワークフロー: モデル呼び出しチェーンと人間のフィードバック組み込み
  • 注文処理: 複数システム間の複雑な調整
  • 業務自動化: 従業員オンボーディングや承認プロセス

チェックポイント・リプレイの仕組み

Durable Functionsの核となるのが チェックポイント・リプレイ機構 です。

how_durable_works

動作の流れ

  1. 関数が実行され、各ステップが完了するたびに チェックポイント が保存される
  2. 障害が発生した場合wait()による待機が完了した場合、関数は 最初から再実行(リプレイ) される
  3. リプレイ時、完了済みのチェックポイントはスキップ され、保存された結果が使用される
  4. 未完了のステップから処理が再開される

これにより、開発者は通常のシーケンシャルなコードを書くだけで、自動的に復元力のあるワークフローが実現されます。

Durable Execution SDK

Durable Execution SDKを使用し、Lambda関数内に組み込むことでDurable Functionsの機能を利用することができます

https://docs.aws.amazon.com/lambda/latest/dg/durable-execution-sdk.html

プリミティブ 説明
context.step() ビジネスロジックに自動リトライとチェックポイント機能を追加。完了したステップはリプレイ時にスキップ
context.wait() 指定期間実行を一時停止。待機中はコンピュート料金なし
context.createCallback() 外部システムからの入力を待機(人間の承認フローなど)
context.parallel() 複数の操作を並列実行
context.map() 配列の各要素に対して操作を実行
context.invoke() 他のLambda関数を呼び出し

https://github.com/aws/aws-durable-execution-sdk-js

やってみた

実際にLambda Durable Functionsを試してみました。
公式ドキュメント内のサンプルコードを実装して挙動を確認してみます。

https://docs.aws.amazon.com/lambda/latest/dg/durable-getting-started.html

前提条件

  • 現在、US East (Ohio)リージョン でのみ利用可能
  • Python 3.13/3.14 または Node.js 22/24 ランタイムが必要
  • 新規作成時のみ Durable Functionsを有効化可能(既存関数の変更は不可)

今回はNode.jsで試してみます。

1. Lambda関数の作成

AWSコンソールでLambda関数を新規作成します。
リージョンをUS East (Ohio)に変更して、Lambda関数を作成します。「Durable execution」 セクションが表示されていることが確認できますね。

スクリーンショット 2025-12-03 3.43.04
関数を作成します。

「Durable execution」を有効化している場合は、@aws/durable-execution-sdk-jsが既にインストールされており、最初のindex.mjs内にサンプルコードが既に用意されています。

スクリーンショット 2025-12-03 3.53.03

2. コードの修正とデプロイ

今回は公式ドキュメントで解説されているコードをそのまま使って試してみたいので、以下のコードに置き換えてみます。

index.mjs
import { withDurableExecution } from "@aws/durable-execution-sdk-js";

export const handler = withDurableExecution(
  async (event, context) => {
    const orderId = event.orderId;

    // ステップ1: 注文のバリデーション
    const validationResult = await context.step(async (stepContext) => {
      stepContext.logger.info(`Validating order ${orderId}`);
      return { orderId, status: "validated" };
    });

    // ステップ2: 決済処理
    const paymentResult = await context.step(async (stepContext) => {
      stepContext.logger.info(`Processing payment for order ${orderId}`);
      return { orderId, status: "paid", amount: 99.99 };
    });

    // 外部確認をシミュレートするために10秒待機
    await context.wait({ seconds: 10 });

    // ステップ3: 注文の確定
    const confirmationResult = await context.step(async (stepContext) => {
      stepContext.logger.info(`Confirming order ${orderId}`);
      return { orderId, status: "confirmed" };
    });

    return {
      orderId: orderId,
      status: "completed",
      steps: [validationResult, paymentResult, confirmationResult]
    };
  }
);

コードの変更が完了したら、デプロイしてみます。

スクリーンショット 2025-12-03 4.01.33

上記のコードのポイントを解説します。

ポイント解説

withDurableExecution でハンドラーをラップ

import { withDurableExecution } from '@aws/durable-execution-sdk-js';

+ export const handler = withDurableExecution(
  async (event, context) => {
    // ワークフローの処理
  }
);
  • withDurableExecution でハンドラーをラップすることで、Durable Functionsの機能が有効になり、第二引数にはDurableContextオブジェクトが渡されます。このオブジェクトは、この後使用するチェックポイントを作成するためのstep()wait()といった耐久性のある操作のためのメソッドを提供します。

context.step() でチェックポイントを設定

const paymentResult = await context.step(async (stepContext) => {
  return await paymentService.charge(amount);
});
  • context.step() でラップした処理は、完了時にチェックポイントが保存されます
  • リプレイ時は完了済みのステップがスキップされ、保存された結果が返されます
  • これにより、決済処理が2回実行されるような問題を防げます

リプレイ時にはここで保存されたチェックポイントが使用されるということですね。

context.wait() で待機(待機中はコンピュート料金なし)

await context.wait({ seconds: 10 }); // 10秒待機
  • context.wait() で指定期間の待機が可能です
  • 待機中はLambdaの実行が一時停止 され、コンピュート料金が発生しません
  • 最大1年間の待機が可能です

今回のサンプルコードでは、context.wait({ seconds: 10 }) で10秒間の待機を行っています。これは外部処理の完了を待つシミュレーションですが、実際のユースケースでは、人間の承認待ちや、スケジュールされた後続処理(例:24時間後にリマインダー送信)などに活用できます。 待機中はLambdaのコンピュート料金が発生しないため、長時間のワークフローでもコスト効率良く実装できます。

3. 動作確認

テストイベントを作成します。イベント JSONセクションに、以下を入力してテストを実行しました。

json
{
  "orderId": "order-12345"
}

すると各ステップが実行され、結果が出力されました。

スクリーンショット 2025-12-03 5.43.31

さらに詳細を確認したい場合は、新しく追加された 永続実行 タブを利用します。このタブでは、各実行の実行名が一覧表示され、現在のステータス(実行中、成功、または失敗)や詳細情報を確認できます。

スクリーンショット 2025-12-03 4.50.15

実行名を選択すると、その永続実行の詳細情報が確認できます。

  • 各ステップが完了した時期を示す実行タイムライン
  • チェックポイント履歴
  • 待機期間
  • ステップ結果

等が確認できます。
スクリーンショット 2025-12-03 4.53.29
スクリーンショット 2025-12-03 4.53.33

今回は、context.wait() で10秒待機させましたが、その後のLambda関数の挙動を確認してみたいと思います。
ドキュメントによると、完了した後はLambda関数はリプレイされ コードは再実行 されますが、完了したチェックポイントは スキップ され、完了した操作を再実行する代わりに 保存された結果が使用 されます。
このリプレイ機構により、一貫性が確保されると同時に、長時間の実行が可能になります。

今回で言うと以下のコードが実行された後、フロー画像の赤枠の部分に入ります。

await context.wait({ seconds: 10 }); // 10秒待機

how_durable_works (1)

完了済みのチェックポイントの関数はスキップされ、保存された結果が使用されます。
これを実際にCloudWatch Logsで確認してみると、最初のバリデーション処理のログメッセージ「Validating order」は1回しか表示されていないので、実際にスキップされていることが確認できました!

スクリーンショット 2025-12-03 5.13.35

注意点・制限事項

現在の制限

  • リージョン: 発表時点(2025年12月3日)ではUS East (Ohio) のみ
  • ランタイム: 発表時点(2025年12月3日)ではPython 3.13/3.14、Node.js 22/24 のみ
  • 既存関数への適用: 新規作成時のみ有効化可能
  • 決定論的なコード: リプレイ時に同じ結果を返すため、context.step() 外でランダムな値を生成しないこと

状態保持に関する注意点

チェックポイントに保存されるのは durable operation(stepwaitなど)の入出力のみ です。

// ❌ グローバル変数や return していない値は保持されない
let globalCounter = 0;

await context.step(async () => {
  globalCounter++; // リプレイ時にリセットされる
  doSomething();
  // return していないので結果が保持されない
});

// ✅ 次のステップに引き継ぎたい値は必ず return する
const result = await context.step(async () => {
  return { count: 1, data: "something" };
});

おわりに

AWS Lambda Durable Functionsは、マルチステップアプリケーションの構築を大幅に簡素化する画期的な機能です。

特に印象的だったのは以下の点です:

  • 通常のコードを書くだけ で復元力のあるワークフローが実現
  • 待機中はコンピュート料金なし でコスト効率が良い
  • チェックポイント・リプレイ機構 により障害からの自動復旧が可能

現在はUS East (Ohio)リージョンのみですが、今後他のリージョンへの展開も期待されます。東京リージョンで利用可能になったら、実際のプロジェクトにも積極的に取り入れていきたいと思います。

以上、どなたかの参考になれば幸いです。

参考

https://docs.aws.amazon.com/lambda/latest/dg/durable-functions.html

https://docs.aws.amazon.com/lambda/latest/dg/durable-execution-sdk.html

https://aws.amazon.com/about-aws/whats-new/2025/12/lambda-durable-multi-step-applications-ai-workflows/

https://github.com/aws/aws-durable-execution-sdk-js

https://aws.amazon.com/blogs/aws/build-multi-step-applications-and-ai-workflows-with-aws-lambda-durable-functions/

https://zenn.dev/aws_japan/articles/lambda-durable-functions

この記事をシェアする

FacebookHatena blogX

関連記事