Amaozn API Gateway の Lambda プロキシ統合を使用している場合に、「Lambda 関数のタイムアウト時」にクライアントにどのようなエラーレスポンスが返るのか検証してみた
こんにちは、製造ビジネステクノロジー部の若槻です。
AWS Lambda 関数では3秒から900秒の間でタイムアウトを設定することができます。これによりシステム提供側にとってはコストを最適化できたり、ユーザー側にとってはレスポンス時間が保証されるなどのメリットがあります。
今回は、Amaozn API Gateway の Lambda プロキシ統合を使用している場合に、Lambda 関数のタイムアウト時にクライアントにどのようなエラーレスポンスが返るのか検証する機会があったので共有します。
やってみた
環境構築
Lambda ハンドラーのコード
Serverless Express を使用して実装した Lambda ハンドラーのコードです。Serverless Express は Lambda プロキシ統合による Lambda-lith アプローチを実装する際によく使用されるパッケージです。
import serverlessExpress from "@codegenie/serverless-express";
import cors from "cors";
import express, { Request, Response } from "express";
const app = express();
app.use(cors());
app.use(express.json());
app.get("/companies", (_: Request, res: Response): void => {
// Lambda 関数のタイムアウトを 3 秒に設定しているため、5 秒待機する
setTimeout(() => {
res.status(200).send({ message: "Hello, world!" });
}, 5000);
});
export const handler = serverlessExpress({ app });
AWS CDK コード
AWS CDK の LambdaRestApi コンストラクトを使用して Lambda プロキシ統合の REST API を作成します。
import * as cdk from "aws-cdk-lib";
import * as apigateway from "aws-cdk-lib/aws-apigateway";
import * as lambda_nodejs from "aws-cdk-lib/aws-lambda-nodejs";
import * as aws_lambda from "aws-cdk-lib/aws-lambda";
import { Construct } from "constructs";
export class MainStack extends cdk.Stack {
constructor(scope: Construct, id: string, props: cdk.StackProps) {
super(scope, id, props);
/**
* Lambda Function
*/
const handler = new lambda_nodejs.NodejsFunction(this, "Handler", {
entry: "src/rest-api-router.ts",
tracing: aws_lambda.Tracing.ACTIVE, // AWS X-Ray によるトレースを有効化
});
/**
* API Gateway REST API
*/
new apigateway.LambdaRestApi(this, "RestApi", {
handler,
deployOptions: {
//実行ログの設定
dataTraceEnabled: true,
loggingLevel: apigateway.MethodLoggingLevel.INFO,
// アクセスログの設定
accessLogDestination: new apigateway.LogGroupLogDestination(
new cdk.aws_logs.LogGroup(this, "AccessLogGroup", {
logGroupName: "/aws/api/RestApi",
removalPolicy: cdk.RemovalPolicy.DESTROY,
})
),
tracingEnabled: true, // AWS X-Ray によるトレースを有効化
},
});
}
}
動作確認
REST API のエンドポイントにリクエストを送信して、Lambda 関数でタイムアウトを発生させます。
curl でリクエストをすると 502 ステータスコードおよび {"message": "Internal server error"}
というメッセージのレスポンスが返りました。
$ curl -s -w "\nステータスコード: %{http_code}\n" https://b2cvv2sind.execute-api.ap-northeast-1.amazonaws.com/prod/companies
{"message": "Internal server error"}
ステータスコード: 502
関数の Error
CloudWatch メトリクスを確認すると、エラーが発生していることがわかります。
API Gateway の実行ログ上でも API Gateway が 502 エラーを返していることがわかります。
104.28.243.105 - - [14/May/2025:08:37:51 +0000] "GET /{proxy+} HTTP/1.1" 502 36 7f23382e-c73e-4e10-b9b0-f37c79983cf2
一方で API Gateway のアクセスログを確認すると、Lambda 関数は 200 エラーを返し、さらに API メソッドは 502 エラーを返していることがわかります。
(7f23382e-c73e-4e10-b9b0-f37c79983cf2) Endpoint response body before transformations:
{
"errorMessage": "2025-05-14T08:37:55.098Z bbbb7425-3d0f-446a-a7fa-0af3db88014c Task timed out after 3.01 seconds"
}
(7f23382e-c73e-4e10-b9b0-f37c79983cf2) Lambda execution failed with status 200 due to customer function error: 2025-05-14T08:37:55.098Z bbbb7425-3d0f-446a-a7fa-0af3db88014c Task timed out after 3.01 seconds. Lambda request id: bbbb7425-3d0f-446a-a7fa-0af3db88014c
(7f23382e-c73e-4e10-b9b0-f37c79983cf2) Method completed with status: 502
これは Lambda 関数はランタイムエラー時に 200 エラーを返すのに対し、
関数コードまたは Lambda ランタイムからエラーが返された場合、Lambda からのレスポンスのステータスコードは 200 OK です。
Lambda でタイムアウトが発生した場合は下記ドキュメントで言うところの「誤った形式でレスポンスが返された場合」に該当し、それを受け取った API Gateway は 502 エラーに変換してクライアントには返しているためです。
では正しい形式のレスポンスは何かというと、下記ドキュメントに記載されている形式となります。今回の Lambda からのレスポンスは {"errorMessage": "..."}
だったので誤った形式であるということになります。
{
"isBase64Encoded": true|false,
"statusCode": httpStatusCode,
"headers": { "headerName": "headerValue", ... },
"multiValueHeaders": { "headerName": ["headerValue", "headerValue2", ...], ... },
"body": "..."
}
また AWS X-Ray のトレースは次のようになりました。こちらでも Lambda 関数がエラーになった上でステータスコード 200 を返しているのに対して、API Gateway が 502 エラーを返していることがわかります。
おわりに
Amaozn API Gateway の Lambda プロキシ統合を使用している場合に、Lambda 関数のタイムアウト時にクライアントにどのようなエラーレスポンスが返るのか検証する機会があったので共有しました。
どなたかの参考になれば幸いです。
参考
以上