Lambda Managed Instances環境固有のレースコンディションについて確認してみた

Lambda Managed Instances環境固有のレースコンディションについて確認してみた

Lambda Managed Instancesでは1つの実行環境が同時に複数のリクエストを処理するので、/tmpディレクトリの扱いなどは注意が必要です。
2025.12.02

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

Lambda Managed Instancesでは基本的にLambdaのプログラミングモデルがそのまま利用可能ですが、通常のLambda実行環境とは異なる点があることに注意が必要です。
このブログでは/tmpディレクトリの利用を例としてLambda Managed Instances固有のレースコンディションについて検証していきます。

同時実行モデルに関する違い

コンピューティングタイプにLambda Managed Instancesを指定したLambda Functionは同時実行制御について通常のLambda Functionとは異なるモデルで動作します。

公式ドキュメントの記載は以下の通りです。

Lambda Managed Instances support multi-concurrent invocations, where one execution environment can handle multiple invocations at the same time. This differs from the Lambda (default) compute type, which provides a single concurrency model where one execution environment can run a maximum of one invoke at a time. Multi-concurrency yields better utilization of your underlying EC2 instances and is especially beneficial for IO-heavy applications like web services or batch jobs. This change in execution model means that thread safety, state management, and context isolation must be handled differently depending on the runtime.

Concurrency model

通常のLambdaは以下のようなモデルです。
通常のLambdaの同時実行モデル

1つのLambda実行環境が同時に処理するリクエストは最大1つだけです。複数のリクエストが発生した場合は複数のLambda実行環境が起動して並列で処理を行うことになります。

それに対してLambda Managed Instancesを利用する場合は以下のようなモデルになります。
Lambda Managed Instancesの同時実行モデル

1つのLambda実行環境が同時に複数のリクエストを処理します。

これらのモデルの違いから、Lambda Managed Instancesを利用する際は通常のLambdaとは異なる注意点が存在します。
詳細については以下ドキュメントに記載されています。

https://docs.aws.amazon.com/lambda/latest/dg/lambda-managed-instances-runtimes.html

ランタイムによって同時実行の実現方法がマルチプロセスだったりマルチスレッドだったりとマチマチなので、各ランタイムごとに固有の考慮事項が存在しますが、全ランタイム共通で記載されているのが/tmpディレクトリに関する考慮事項です。例えばPythonの場合は以下のように記載されています。

The /tmp directory is shared across all concurrent requests in the execution environment. Concurrent writes to the same file can cause data corruption, for example if another process overwrites the file. To address this, either implement file locking for shared files or use unique file names per process or per request to avoid conflicts. Remember to clean up unneeded files to avoid exhausting the available space.

ランタイムによってper process or per request の部分がper requestper thread or per requestに微妙に変化しますが、基本的に述べられていることはリクエストを跨いで/tmpディレクトリが共有されることに注意しようということです。

やってみる

実際にリクエストを跨いで/tmpディレクトリが共有されることを確認してみましょう。
Python3.14のランタイムで以下のコードを書きました。

import json
import os
import time

def lambda_handler(event, context):

    file_path = '/tmp/test.txt'    
    query_params = event.get('queryStringParameters') or {}
    
    if 'read' in query_params:        
        content = ''
        for i in range(100):
            time.sleep(0.1)
            if os.path.exists(file_path):
                with open(file_path, 'r') as f:
                    content = f.read()

            print(json.dumps({
                "i": i,
                "content": content.splitlines()
            }))
        
        return {
            'statusCode': 200,
            'body': json.dumps({})
        }
    
    request_id = context.aws_request_id       
    with open(file_path, 'a') as f:
        f.write(request_id + '\n')

    return {
        'statusCode': 200,
        'body': json.dumps({})
    }

やってることは簡単で、クエリパラメータにreadが存在する場合は100msスリープして/tmp/test.txtの中身をログに出力する処理を100回繰り返します。
逆にクエリパラメータにreadが存在しない場合は/tmp/test.txtにリクエストIDを追記します。

このLambdaをAPI GWの背後に配置してcurlコマンドでクエリストリングreadを付与したリクエストを発行しました。

curl "https://<API GWのエンドポイント>?read=true"

並行してabコマンドで100リクエストを発行してみました。

ab -n 100 -c 1 "https://<API GWのエンドポイント>"

まず通常のLambda実行環境の場合の結果です。

通常のLambda実行環境でテストした際のログ

CW Logsに出力されたログを確認するとログに出力された"content"はずっと空のままです。curlコマンドからのリクエストを処理しているLambda実行環境とabコマンドからのリクエストを処理しているLambda実行環境が分離されていることが読み取れます。

続いてLambda Managed Instancesの環境でテストした際のログです。

Lambda Managed Instancesの環境でテストした際のログ

ログに出力された"content"は最初空ですが、徐々に中身が増えていっています。この結果からcurlコマンドからのリクエストを処理しているLambda実行環境がabコマンドからのリクエストも処理していることが読み取れます。

まとめ

通常のLambda実行環境では発生しないLambda Managed Instances環境固有のレースコンディションについて確認してみました。
/tmpディレクトリ配下のファイルを読み書きするようなコードがあると不具合が発生するリスクがあるので注意しておきたいですね。この他にも通常のLambda実行環境と同様の仕様とLambda Managed Instances固有の仕様があるので、利用を検討する際はしっかりドキュメントを確認するようにしましょう。

1つの実行環境が複数リクエストを同時に処理するというモデルは複数リクエストを跨いだリソース共有が可能ということでもあるので、Lambda Managed Instancesにおいてはコネクションプーリングの考え方も変わってきそうですね。Pgpool-IIのようなミドルウェアをLambda Extensionsとして各Lambda実行環境にデプロイして各リクエストを処理する個々のプロセスやスレッドはExtensionに接続するといったモデルも有効かもしれません。

参考

この記事をシェアする

FacebookHatena blogX

関連記事