はじめに

AWS資格試験の勉強をすると、しばしばLambdaのパフォーマンスを改善する方法として、 「(DB接続等の処理を)Lambdaハンドラー外に移動する」というやり方を目にします。

これが何故パフォーマンスの改善につながるのかを自分なりにまとめてみました。

結論

  • Lambda関数が「ウォームスタート」で開始した場合、ハンドラー外に書いたコードを再利用できるから

Lambdaのコールドスタートとウォームスタート

いきなり「ウォームスタート」というワードが出てきましたが、対になる言葉として「コールドスタート」も存在します。

これらのワードを理解するために、Lambda関数が呼び出された際の処理の流れを理解する必要があります。

Lambda関数が呼び出されると何が起きる?

Lambda関数が呼び出されると、AWS側でLambda関数の「実行環境」の準備が開始し、実行環境が起動した後にハンドラーコードが実行されます。

具体的には、以下の処理が実行されます。

  • PythonやNode.js等の環境の起動
  • 実行環境へコードをダウンロード
  • ハンドラー外に記述された初期化コードの実行
  • ハンドラーコードの実行

コールドスタートとは?

Lambda関数が始めて呼び出されたり、長らく起動していない状態から久しぶりに呼び出された場合は、実行環境の準備からハンドラーコードの実行までの一連の処理が必要となります。

この時、「コールドスタート」でLambda関数が呼び出されたことになります。

ウォームスタートとは?

一方で、一度Lambda関数の呼び出しが完了すると、実行環境は一定時間保持されます。

実行環境が保持されている間にLambda関数が呼び出された場合は、実行環境の準備が不要となりハンドラーコードの実行のみ行われます。

この時、「ウォームスタート」でLambda関数が呼び出されたことになります。

ここまでのまとめ

改めて、コールドスタートとウォームスタートの処理の違いをまとめます。

  • コールドスタート(初回または久しぶりにLambda関数が呼び出された場合)

    • PythonやNode.js等の環境の起動
    • 実行環境へコードをダウンロード
    • ハンドラー外に記述された初期化コードの実行
    • ハンドラーコードの実行
  • ウォームスタート(実行環境が保持されている時にLambda関数が呼び出された場合)

    • ハンドラーコードの実行

ハンドラーコードは、コールドスタート/ウォームスタートどちらの場合でも必ず実行されます。

一方で、ハンドラー外のコードは、ウォームスタートで呼び出された場合なら、コード(実行環境)の再利用ができます。

そのため、DB接続等の処理をハンドラー外に記載・移動することは、パフォーマンスの改善に繋がる可能性があるということになります。

このことは、『AWS Lambda 関数を使用するためのベストプラクティス』(https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/best-practices.html)にも記載されています。

ここまでの参考文献

動作確認

実際にハンドラー外にコードを記載すれば、コード(実行環境)を再利用できるか検証します。

検証に際し、以下のサイトを大変参考にさせていただきました。

実行するPythonコード

ローカルPCのPythonとLambda上で以下のコードを実行してみました。

from datetime import datetime

now_time_outside = datetime.now()


def lambda_handler(event, context):
    now_time_inside = datetime.now()

    print(f"now_time_outside: {now_time_outside}")
    print(f"now_time_inside: {now_time_inside}")

# ローカルPC上の場合は以下の通り記載
# def lambda_handler():
    # now_time_inside = datetime.now()

    # print(f"now_time_outside: {now_time_outside}")
    # print(f"now_time_inside: {now_time_inside}")

# lambda_handler()

ローカルPCでの実行結果

$ python3 -V
Python 3.10.12

# 1回目
$ python3 lambda_local.py
now_time_outside: 2025-04-06 23:20:37.826077
now_time_inside: 2025-04-06 23:20:37.826091

# 2回目
$ python3 lambda_local.py
now_time_outside: 2025-04-06 23:20:41.226870
now_time_inside: 2025-04-06 23:20:41.226884

# 3回目
$ python3 lambda_local.py
now_time_outside: 2025-04-06 23:20:45.833986
now_time_inside: 2025-04-06 23:20:45.834002

ローカルPCのPythonでは、コードを実行する度に、ハンドラー内/外両方のdatetime.now()が計算されています。

Lambda上での結果

ランタイムにPython 3.10を選択の上、その他はデフォルトでLambda関数を作成し、コードのデプロイ→テストを実行します。 create_lambda

  • 1回目 test_1

  • 2回目 test_2

  • 3回目 test_3

Lambda上で実行した場合は、ハンドラー内で定義した「now_datetime_inside」が実行される度に計算されています。

一方で、ハンドラー外で定義した「now_time_outside」は、1回目の実行結果である「2025-04-06 14:37:22.671652」が2回目、3回目の実行結果にも現れています。

上記より、ウォームスタート(2回目以降)で起動した場合は、確かにハンドラー外で定義したコードを含む実行環境が再利用されることがわかりました。

また、ハンドラー内のコードは毎回必ず実行されることも確認できました。

以上より、ハンドラー外にコードを記載・移動することで、コード(実行環境)を再利用できる可能性がある = パフォーマンスの改善に繋がる可能性があると言えそうです。

最後に

今回は、Lambdaのハンドラー外にコードを書く意義について調べてみました。

資格勉強をしているとよく目にするやり方なので、何となく理解していたつもりでしたが、手を動かすとより理解が深まった気がします。

今後はただ資格を取るだけでなく、理解があいまいな分野を地道に検証しながら、試験勉強していこうかと思います。