AWS Lambda Managed Instances でコールドスタートが発生しないことを確認してみた

AWS Lambda Managed Instances でコールドスタートが発生しないことを確認してみた

結論: 初回実行時でもコールドスタート(Init フェーズ)は発生しない。
2025.12.21

こんにちは、製造ビジネステクノロジー部の若槻です。

AWS re:Invent 2025 で AWS Lambda 関数の新タイプである Lambda Managed Instances (LMI) が発表されました。

https://aws.amazon.com/jp/blogs/news/introducing-aws-lambda-managed-instances-serverless-simplicity-with-ec2-flexibility/

LMI では Lambda 関数が EC2 インスタンス上で稼働するため、定常的なリクエストをコスト効率よく処理することが可能となります。

加えて、実行環境がインスタンス上で常に起動していることになるため、コールドスタートが抑制されるというメリットもあります。

今回は、Lambda Managed Instances の Lambda 関数でコールドスタートが発生しないことを、デフォルト Lambda 関数と比較しつつ、実際に確認してみました。

確認してみた

Lambda ハンドラーコード

関数のハンドラーコードです。

src/handler.ts
import { Logger } from "@aws-lambda-powertools/logger";
import { Context } from "aws-lambda";

/**
 * ロガーの初期化
 */
const logger = new Logger();

/**
 * ハンドラー
 */
export const handler = async (context: Context): Promise<void> => {
  logger.addContext(context);

  logger.info("Hello, LMI");
};

ハンドラー外での AWS SDK クライアントの初期化という、コールドスタート発生時に init 処理に時間を要する典型的なコードパターンを使用しています。

CDK コード

リソースの作成には AWS CDK を使用しました。

VPC は予め作成したものを使用します。

VPC 定義コード
lib/constructs/vpc.ts
import * as ec2 from "aws-cdk-lib/aws-ec2";
import { Construct } from "constructs";

/**
 * VPC 実装
 *
 * MEMO: VPC から各種 AWS サービスへのネットワーク経路確保のために NAT Gateway を配置する
 */
export class VpcConstruct extends Construct {
  public readonly vpc: ec2.Vpc;
  constructor(scope: Construct, id: string) {
    super(scope, id);

    this.vpc = new ec2.Vpc(this, "Default", {
      subnetConfiguration: [
        /**
         * NAT Gateway を配置するためのパブリックサブネット
         */
        {
          name: "Public",
          subnetType: ec2.SubnetType.PUBLIC,
        },

        /**
         * Lambda 関数を配置するためのプライベートサブネット
         */
        {
          name: "PrivateIsolated",
          subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
        },
      ],
    });
  }
}

比較のために、デフォルト設定の Lambda 関数も作成します。

デフォルト Lambda 関数定義コード
packages/iac/lib/constructs/default-function.ts
import * as lambda from "aws-cdk-lib/aws-lambda";
import * as lambda_nodejs from "aws-cdk-lib/aws-lambda-nodejs";
import { Construct } from "constructs";

/**
 * デフォルト Lambda 関数実装
 *
 * MEMO: LMI との比較のために作成
 */
export class DefaultFunctionConstruct extends Construct {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    new lambda_nodejs.NodejsFunction(this, "Default", {
      entry: "src/handler.ts",
      runtime: lambda.Runtime.NODEJS_24_X, // Lambda Managed Instances では Node.js 18.x 以上が必須
      tracing: lambda.Tracing.ACTIVE, // コールドスタート発生状況の観測のために、AWS X-Ray を有効化
    });
  }
}

LMI 作成の定義は以下となります。

lib/sample-stack.ts
import * as cdk from "aws-cdk-lib";
import * as ec2 from "aws-cdk-lib/aws-ec2";
import * as lambda from "aws-cdk-lib/aws-lambda";
import * as lambda_nodejs from "aws-cdk-lib/aws-lambda-nodejs";
import { Construct } from "constructs";

import { DefaultFunctionConstruct } from "./constructs/default-function";
import { VpcConstruct } from "./constructs/vpc";

export class SampleStack extends cdk.Stack {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    /**
     * VPC 作成
     */
    const vpcConstruct = new VpcConstruct(this, "Vpc");
    const vpc = vpcConstruct.vpc;

    /**
     * セキュリティグループ作成
     *
     * MEMO: Capacity Provider 用に作成
     */
    const securityGroup = new ec2.SecurityGroup(this, "SecurityGroup", {
      vpc,
    });

    /**
     * Capacity Provider 作成
     *
     * MEMO: LMI のコア要素となるリソース
     */
    const capacityProvider = new lambda.CapacityProvider(
      this,
      "CapacityProvider",
      {
        subnets: vpc.selectSubnets({
          subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
        }).subnets,
        securityGroups: [securityGroup],
      },
    );

    /**
     * LMI 用 Lambda 関数作成
     */
    const lmiFunction = new lambda_nodejs.NodejsFunction(this, "LmiFunction", {
      entry: "src/handler.ts",
      runtime: lambda.Runtime.NODEJS_24_X, // LMI では Node.js 22.x 以上が必須
      memorySize: 2048, // LMI では 2048MB 以上が必須
      tracing: lambda.Tracing.ACTIVE, // コールドスタート発生状況の観測のために、AWS X-Ray を有効化
    });

    /**
     * Capacity Provider に Lambda 関数を追加
     */
    capacityProvider.addFunction(lmiFunction);

    /**
     * 比較のためのデフォルト設定の Lambda 関数作成
     */
    new DefaultFunctionConstruct(this, "DefaultFunction");
  }
}

確認結果

それぞれの Lambda 関数を3回連続で呼び出した際の実行時間は下記の通りとなりました。デフォルト Lambda では 1 回目の呼び出しに1秒弱かかっているのに対し、LMI はいずれの実行も 0.02 秒で応答しています。2 回目以降の呼び出しでは両者とも高速に応答していますが、いずれの実行も LMI の方がわずかに高速です。

デフォルト LMI
1回目 0.807s 0.017s
2回目 0.058s 0.023s
3回目 0.042s 0.011s

X-Ray のトレースを確認したところ、デフォルト Lambda では 1 回目の実行で Init フェーズが記録されており、やはりコールドスタートが発生していることがわかります。

一方で LMI では 1 回目の実行でも Init フェーズが発生が無く、コールドスタートは発生していません。

結果として、LMI ではコールドスタートが発生しないことが確認できました!

トラブルシュート

CDK ではランタイムバージョンの明示的な指定が必要

LMI でサポートされている Lambda のランタイムバージョンは、従来 Lambda に比べてサポート範囲が最新のバージョンのみとなっています。Node.js の場合は 22 以上となります。

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

また NodejsFunction コンストラクトでランタイムバージョンを明示的に指定していない場合は、CDK デプロイ時に次のエラーが発生します。

8:55:42 PM | CREATE_FAILED        | AWS::Lambda::Function                 | LambdaFunctionBF21E41F
Resource handler returned message: "Runtime Enum nodejs16.x does not support specified feature: Lambda Managed Instances (Service: Lambda, Status Code: 400, Request ID: 775b935f-0cdb-45
97-8ed1-755181991c5a) (SDK Attempt Count: 1)" (RequestToken: 0b0e7e16-980b-8f79-1a44-63310f922e12, HandlerErrorCode: InvalidRequest)

VPC から各種 AWS サービスへのネットワーク経路確保が必要

LMI の関数から各種 AWS サービスにアクセスさせるためには、NAT Gateway や VPC エンドポイントで VPC からのネットワーク経路を確保する必要があります。

ネットワーク経路が確保されていない場合は、下記のように CloudWatch Logs のイベントログが作成されないなどが起きえるので注意しましょう。

LMI でのログ出力上では全てコールドスタート扱いになる?

Lambda ハンドラーでは Powertools for AWS Lambda (TypeScript) を使用してログ出力を行っていますが、LMI でのログ出力上では全てコールドスタート扱いになってしまうようです。

デフォルト Lambda を実行した場合は、1 回目の実行のみ cold_start":true が出力され、2 回目以降は cold_start":false が出力されます。

一方で、同じコードで LMI を実行した場合は、1 回目から 3 回目まで全て cold_start":true が出力されてしまいます。

現状としては混乱を生む挙動となっているので、LMI での Powertools の対応が進むことを期待したいですね。

おわりに

今回は Lambda Managed Instances の Lambda 関数でコールドスタートが発生しないことを、デフォルト Lambda 関数と比較しつつ確認してみました。

サービス発表時の AWS ブログで「初回リクエストのレイテンシに影響するコールドスタートを排除します」とあり、本当かなーと半信半疑でしたが、実際に確認してみると如実にコールドスタートが起きないことが分かりました。

ただし、同ブログには「キャパシティプロバイダーが最大プロビジョニング容量に達し、追加キャパシティがまだ立ち上げ中の場合、リクエストを一時的に 429 ステータスコードで制限します。」ともあり、トラフィック急増時にスケーリングが間に合わずにリクエストが制限される可能性はあるので、トラフィックパターンに応じてスケーリングポリシーやインスタンス選定の検討は必要そうですね。

参考

  • CDK コード参考

https://dev.classmethod.jp/articles/shoma-implemented-aws-lambda-managed-instances-with-aws-cdk/

以上

この記事をシェアする

FacebookHatena blogX

関連記事