🐣

Amplify ConsoleでNext.js ISRの再生成が失敗するときの対処法

2021/11/24に公開

Amplify ConsoleでNext.jsのISRするコードをデプロイしたときに、revalidateに指定した秒数が経過した後の再生成が行われず、ISRするページが503エラーになる事象に困らされました。

この事象が発生する理由と対処方法について記録します。

再生成が行われない理由

結論は、Default Lambda@Edge for Next CloudFront distributionからNext.js Regeneration Lambdaを発火させるためのSQSに対してのメッセージ送信に失敗していたためです。

まず、Amplify ConsoleがNext.jsをデプロイするとき、内部的にServerless Next.js Componentを使用しています。
Serverless Next.js Componentが作成するリソースについては以下の記事を読むと分かりやすいと思います。

今回の記事においては、Default Lambda@Edgeの以下の部分が重要です。

ISRの処理が発生する場合このLambdaが "Next.js Regeneration Lambda" を着火させるためのSQSにメッセージを送信する
https://zenn.dev/laiso/articles/8c619c38bd7b7b

Amplify Consoleはコードを解析して必要なリソースを作成してくれるわけですが、初回デプロイ時にISRをしないコード(getStaticPropsでreturnするオブジェクトにrevalidateが指定されていない)の状態でデプロイを行い、2回目以降のデプロイでISRを行うコードをデプロイすると、Default Lambdaに対してsqs::SendMessageの権限が何故か割り当てられません。
そのため、2回目以降のデプロイで初めてISRを行うコードに変更していると、初回のリクエストではキャッシュが存在しないのでSSRした結果を返してrevalidateに指定した秒数分キャッシュしてくれるのでしばらくは正常に表示できますが、revalidateに指定した秒数が経過してバックグラウンドで新しいキャッシュを生成するためにDefault LambdaがSQSに再生成の処理を発火させるためのメッセージを送ろうとしても権限が割り当てられていないためエラーが発生し、503エラーで帰ってきます。

解消する方法

2021/11/24時点では手動でDefault Lambdaに対してsqs::SendMessageの権限を割り当てるしかありません。

Amplify Consoleが生成するリソース(LambdaやSQSなど)の情報はAmplify Consoleのダッシュボードのdeploymentタブから確認できます。
AWSのコンソールからDefault Lambdaの設定画面に行く方法と合わせて以下で紹介されています。
https://github.com/aws-amplify/amplify-console/blob/main/FAQ.md#access-lambda-edge-logs

こちらの設定タブから実行ロールを編集できるので以下のポリシーをアタッチしましょう。

        {
            "Effect": "Allow",
            "Resource": "arn:aws:sqs:us-east-1:253925498289:<SQS-ID>.fifo",
            "Action": [
                "sqs:SendMessage"
            ]
        }

sqs:SendMessageの権限が割り当てられると、Default LambdaからSQSにメッセージ送信できるようになるので、ISRの再生成が行われ、ページも正常に表示できるようになります。

将来的にはAmplify Console側で対応してほしい

同じようなissueがいくつか立っていたので同じように困っている人がいるようです。
初回デプロイ以降にISRを行うコードに書き換えるケースは全然あると思うので、個人的にはAmplify Consoleがコードの変更を検知して自動でsqs:SendMessageの権限を割り当てるようになってほしいなと思います。
https://github.com/aws-amplify/amplify-console/issues/2347

Discussion