Amazon API Gatewayのレスポンスストリーミング(15分間)をCDK × Hono × Lambda Web Adapter構成で試してみた

Amazon API Gatewayのレスポンスストリーミング(15分間)をCDK × Hono × Lambda Web Adapter構成で試してみた

2025.12.02

はじめに

Amazon API Gatewayにおける最大15分のレスポンスストリーミングのサポートが発表されました。

https://aws.amazon.com/jp/blogs/compute/building-responsive-apis-with-amazon-api-gateway-response-streaming/

https://docs.aws.amazon.com/apigateway/latest/developerguide/response-transfer-mode.html

APIGatewayではタイムアウト制限で29秒の壁が存在しました。本発表により15分間のストリーミングが可能になりました。(この値はService Quotasでアカウントレベルで引き上げ可能な値ではありますが、15分という要求はハードルが高いように思います。)

また記事にもあるとおりAIチャットボットを構築する際に、ストリーミングは必須の要件になっています。これはUX上の体感速度を上げるだけではなく、ユーザーに早い段階でAIが自走する方向性を知らせ、停止するきっかけを与える意味でも非常に価値が高いです。

今回はLambda Web Adapterを利用してこの構成が可能か試してみました。メリットしてはNode.jsのawslambdaグローバルライブラリに依存しないこと、アプリの可搬性を高めることが可能です。言語やFW問わず、ストリーミングが出来る意味でもメリットが大きいです。

実装

実装は以下のリポジトリに配置しています。

https://github.com/shuntaka9576/lambda-web-adapter-apig-streaming

CDK実装

実装の全体像はこちらです。APIタイプはREST APIを利用していて、コンテナLambda(with Lambda Web Adapter)をCDK経由でコンテナビルド、デプロイしています。

https://github.com/shuntaka9576/lambda-web-adapter-apig-streaming/blob/3fe876123f60cd0d2303a9213dd7fb8d22d40356/iac/lib/api-stack.ts#L1-L63

Lambda統合リクエストのレスポンス転送モードにSTREAM、タイムアウトに15分を設定しています。

https://github.com/shuntaka9576/lambda-web-adapter-apig-streaming/blob/3fe876123f60cd0d2303a9213dd7fb8d22d40356/iac/lib/api-stack.ts#L40-L57

環境変数には AWS_LWA_INVOKE_MODEresponse_stream を指定してます。これはLambda関数の呼び出しモードで、今回はstreamingをするため指定しています。推測ですが、SSEのレスポンスをLambda Web Adapter側でLambdaのフォーマットに変換していると思われます。

https://github.com/shuntaka9576/lambda-web-adapter-apig-streaming/blob/3fe876123f60cd0d2303a9213dd7fb8d22d40356/iac/lib/api-stack.ts#L24-L26

アプリケーション実装

Honoを使って、Lambda特有のコードを一切使わず、以下のパスを定義しています

  • /Hello from Hono! が返却
  • /stream で 15分間 1秒おきにメッセージを返却するストリーミングレスポンス

https://github.com/shuntaka9576/lambda-web-adapter-apig-streaming/blob/3fe876123f60cd0d2303a9213dd7fb8d22d40356/server/src/index.ts#L1-L25

デプロイする

CDKをデプロイすると、APIGatewayのエンドポイントが取得できますので、こちらを利用して動作確認をします

$ pnpm cdk deploy

✨  Synthesis time: 0.74s

web-app-stack: deploying... [1/1]
web-app-stack: creating CloudFormation changeset...

 ✅  web-app-stack

✨  Deployment time: 33.88s

Outputs:
web-app-stack.RestApiEndpoint0551178A = https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/
web-app-stack.RestApiUrl = https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/

APIGatewayにリクエストしてみる

まずは普通に / でレスポンスが返却されることを確認します。

$ curl https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/
{"message":"Hello from Hono!"}%

ストリーミングを試します。

$ curl https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/stream
data: Message 1

data: Message 2

data: Message 3

data: Message 4

data: Message 5

data: Message 6

(中略)

data: Message 892

data: Message 893

data: Message 894

data: Message 895

data: Message 896

data: Message 897

data: Message 898

data: Message 899

curl: (92) HTTP/2 stream 1 was not closed cleanly: INTERNAL_ERROR (err 2)

900秒=15分でタイムアウトしていることが確認できました。

実際に動作している様子は以下です。
CleanShot 2025-12-02 at 14.29.53

さいごに

Lambda Function URLsだとWAFが設定できなかったり、CloudFront OAC + Lambda Function URLsの場合ストリーミングだけなら良いのですが、POST/PUTメソッドを利用する場合コンテンツハッシュを計算するLambda@Edgeが必要です。最も手軽でセキュアにストリーミングできる手段として良いですね。使っていきたいと思いました!

このブログで一番時間がかかったのは15分間待つことでした。これだけあればチャットボットは十分ですね!特にLambda専用コードは書かずにストリーミングができたので、言語やFW問わず、Lambda Web Adapterを足してデプロイすればサーバレスで長いストリーミングが出来そうですね。

参考資料

この記事をシェアする

FacebookHatena blogX

関連記事