Durable Functionsの「最大1年間実行可能」の意味を確認してみた #AWSreInvent

Durable Functionsの「最大1年間実行可能」の意味を確認してみた #AWSreInvent

「最大1年間実行可能」の意味を誤解しないようにしましょう!
2025.12.03

リテールアプリ共創部@大阪の岩田です。

re:Invent 2025にてLambda Durable Functions がリリースされました。

このDurable Functionsの売りとして「最大1年間実行可能」というものがあります。公式ドキュメントには以下のように記載されています。

Lambda durable functions enable you to build resilient multi-step applications and AI workflows that can execute for up to one year while maintaining reliable progress despite interruptions. When a durable function runs, this complete lifecycle is called a durable execution, which uses checkpoints to track progress and automatically recover from failures through replay, re-executing from the beginning while skipping completed work.

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

「最大1年間実行可能」だけ聞くとLambdaのタイムアウト上限が15分より長くなったと勘違いするかもしれませんが、実際にはそう単純な話ではありません。ということで実際にDurable Functionsを実行しながら検証してみました。

やってみる

実際にDurable executionを有効化したLambda Functionを作成して確認していきます。

まず重要なのがDurable executionを有効化していてもLambda Function自体のタイムアウト値は15分が上限で変わらないということです。

タイムアウト設定

つまり以下のようなコードは実行できないということです。

import time

@durable_execution
def lambda_handler(event, context) -> dict:
    time.sleep(60 * 15)
    return {
        "statusCode": 200,
        "body": '',
    }

で、Durable executionを有効化した場合は別途永続的な実行ライフサイクル全体に適用されるタイムアウト値が設定可能です。この上限が366日…「最大1年間実行可能」ということですね。

durable-timeout.jpg

この2つのタイムアウト値の違いについては公式ドキュメントで詳細に解説されています。

https://docs.aws.amazon.com/lambda/latest/dg/durable-basic-concepts.html#durable-configuration-basic

ざっくり解説すると永続設定のタイムアウト値はDurable executionの開始~終了までに適用されるタイムアウト値です。実行タイムアウトを366日に指定した場合、Lambdaのコードでcontext.wait(Duration.from_days(365))を実行してもタイムアウトにならないということです。一方で基本設定から設定するタイムアウト値はDurable executionの各永続オペレーションから呼び出されるLambda Functionの実行に対するタイムアウト値となります。

理解を深めるために色々なパターンで実行を試してみましょう。

1.14分のSleepを含むステップ✕3を実行する場合

以下のように14分のSleepを含むステップ✕3で構成されるDurable executionを試してみます。一般設定のタイムアウト値は15分、Durable executionのタイムアウトは366日に設定しています。

from aws_durable_execution_sdk_python.config import Duration
from aws_durable_execution_sdk_python.context import DurableContext, StepContext, durable_step
from aws_durable_execution_sdk_python.execution import durable_execution
import time

@durable_step
def step1(step_context: StepContext) -> str:
    step_context.logger.info("step1")
    time.sleep(840)
    return "step1"

@durable_step
def step2(step_context: StepContext) -> str:
    step_context.logger.info("step2")
    time.sleep(840)
    return "step2"

@durable_step
def step3(step_context: StepContext) -> str:
    step_context.logger.info("step3")
    time.sleep(840)
    return "step3"

@durable_execution
def lambda_handler(event, context) -> dict:
    context.step(step1())
    context.step(step2())
    context.step(step3())
    return {
        "statusCode": 200,
        "body": '',
    }

実行結果は以下の通りです。

14分のSleepを含むステップ✕3で構成されるDurable execution

step1については問題なく正常終了していますが、step2については一度エラーでInvocationCompletedとなっているのが分かります。対象のログの詳細を確認すると以下のようにSandbox.Timedoutエラーとなっているのが分かります。

{
  "EventId": 5,
  "EventTimestamp": "2025-12-03T05:44:41.346Z",
  "EventType": "InvocationCompleted",
  "InvocationCompletedDetails": {
    "EndTimestamp": "2025-12-03T05:44:41.341Z",
    "Error": {
      "Truncated": false,
      "Payload": {
        "ErrorType": "Sandbox.Timedout",
        "ErrorMessage": "RequestId: c7fc9ab6-6867-44d8-b951-f0dd9f34af6c Error: Task timed out after 900.00 seconds"
      }
    },
    "RequestId": "c7fc9ab6-6867-44d8-b951-f0dd9f34af6c",
    "StartTimestamp": "2025-12-03T05:29:40.834Z"
  }
}

これはstep1の段階で14分を消費したため、step2で1分Sleepすると15分の上限に抵触してしまうということですね。

その後自動的にstep2がリトライされますが、リトライ時はstep1のチェックポイントから実行が継続するため、step2開始時点ではLambdaの実行時間の消費はほぼ0となっています。よって14分間のSleepも問題なく実行可能です。

該当時間帯に出力されたログは以下の通りでした。
14分のSleepを含むステップ✕3で構成されるDurable execution実行ログ

step2,step3はそれぞれ2回実行されていることが分かります。

2.context.wait()で15分間のwaitを2回実行する場合

続いて以下のようにcontext.wait(Duration.from_minutes(15))で15分のwaitを2回実行するDurable executionを試してみます。一般設定のタイムアウトは10秒、Durable executionのタイムアウトは31分に設定しています。

wait以外には簡単な処理しか実行しないので、一般設定のタイムアウト上限10秒に抵触することは無いはずです。

from aws_durable_execution_sdk_python.config import Duration
from aws_durable_execution_sdk_python.context import DurableContext, StepContext, durable_step
from aws_durable_execution_sdk_python.execution import durable_execution

@durable_step
def my_step(step_context: StepContext, i: int) -> str:
    step_context.logger.info(f"my_step:{i}")
    return f"my_step:{i}"

@durable_execution
def lambda_handler(event, context) -> dict:
    
    context.step(my_step(1))
    context.wait(Duration.from_minutes(15))

    context.step(my_step(2))
    context.wait(Duration.from_minutes(15))    

    return {
        "statusCode": 200,
        "body": msg,
    }

実行結果は以下の通りでした。

context.wait()で15分間のwaitを2回実行する場合の実行結果

一般設定のタイムアウト値10秒に抵触することなく問題なく実行完了してるのが分かります。

CW Logsに出力されたログは以下の通りでした。

context.wait()で15分間のwaitを2回実行する場合のログ

my_step:1のログが出力された約15分後にmy_step:2のログが出力されています。

3.15分のSleepを含むステップを実行する場合

以下のように15分のSleepを含むステップを実行するDurable executionを試してみます。一般設定のタイムアウトは15分、Durable executionのタイムアウトは1時間に設定しています。

from aws_durable_execution_sdk_python.config import Duration
from aws_durable_execution_sdk_python.context import DurableContext, StepContext, durable_step
from aws_durable_execution_sdk_python.execution import durable_execution
import time

@durable_step
def fifteen_min_sleep(step_context: StepContext) -> str:
    step_context.logger.info("start 15min_sleep")
    time.sleep(900)
    return "fifteen_min_sleep"


@durable_execution
def lambda_handler(event, context) -> dict:
    context.step(fifteen_min_sleep())
    return {
        "statusCode": 200,
        "body": '',
    }

実行結果は以下の通りです。

一般設定のタイムアウト値15分に抵触するためfifteen_min_sleepのステップが異常終了を繰り返しています。

15分のSleepを含むステップを実行した結果

ログの詳細を確認すると、以下のようにSandbox.Timedoutのエラーが発生しているのが分かります。

{
  "EventId": 3,
  "EventTimestamp": "2025-12-03T06:46:55.722Z",
  "EventType": "InvocationCompleted",
  "InvocationCompletedDetails": {
    "EndTimestamp": "2025-12-03T06:46:55.714Z",
    "Error": {
      "Truncated": false,
      "Payload": {
        "ErrorType": "Sandbox.Timedout",
        "ErrorMessage": "RequestId: 938edc30-89e0-4191-ad93-9998c3c502ff Error: Task timed out after 900.00 seconds"
      }
    },
    "RequestId": "938edc30-89e0-4191-ad93-9998c3c502ff",
    "StartTimestamp": "2025-12-03T06:31:55.150Z"
  }
}

何度かInvocationCompletedを繰り返した後、Durable executionのタイムアウト値1時間に抵触して最終的にはExecutionTimedOutで異常終了しています。

該当時間帯のメトリクスを確認するとExecutionTimedOutが1件確認できました。

CloudWatchに出力されたExecutionTimedOutのメトリクス

4.8分のSleepを含むステップ✕2で構成され、Durable executionのタイムアウトが15分の場合

以下のように8分のSleepを含むステップ✕2で構成されるDurable executionを試してみます。一般設定のタイムアウトは10分、Durable executionのタイムアウトは15分に設定しています。

from aws_durable_execution_sdk_python.config import Duration
from aws_durable_execution_sdk_python.context import DurableContext, StepContext, durable_step
from aws_durable_execution_sdk_python.execution import durable_execution
import time

@durable_step
def step1(step_context: StepContext) -> str:
    step_context.logger.info("step1")
    time.sleep(480)
    return "step1"

@durable_step
def step2(step_context: StepContext) -> str:
    step_context.logger.info("step2")
    time.sleep(480)
    return "step2"

@durable_execution
def lambda_handler(event, context) -> dict:
    context.step(step1())
    context.step(step2())
    return {
        "statusCode": 200,
        "body": '',
    }

実行結果は以下の通りでした。先程の検証パターン3と類似ですが最終的にはDurable executionのタイムアウト値15分に抵触してDurable execution自体がエラーで終了しています。違いとしてstep2が一度SandBox.TImedoutで異常終了していますが、これは今まで見てきたようにstep1の8分 + step2の8分→合計16分が一般設定のタイムアウト値15分を超えているからですね。

8分のSleep✕2ステップでDurable executionのタイムアウトに抵触した場合

CW Logsのログからもstep2が自動的に2回実行されていることがわかります。

8分のSleep✕2ステップでDurable executionのタイムアウトに抵触した場合のログ

まとめ

Durable Functionsのタイムアウトについて確認してみました。「最大1年間実行可能」とはいえ個々のステップは15分以内に収まるように実装する必要があるので注意しましょう。またwait()waitForCallback()waitForCondition()といった待機操作以外にCPUバウンドな処理の実行時間が長い場合は、一般設定のタイムアウト値15分に抵触して自動リトライが走る可能性が高いので冪等な実装を心がけましょう。

こういった注意点はドキュメントにベストプラクティスとして紹介されているので、Durable Functionsを採用する際は必ず目を通しておきましょう。

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

参考

この記事をシェアする

FacebookHatena blogX

関連記事