⏰
Amplify + Next.js 30秒以上のサーバ処理はタイムアウトとなる
要点
- Amplify + Next.js(App Router)でフロントから呼び出すサーバ処理が30秒以上の場合、リクエストは504 Gateway Timeoutエラーとなる
- ServerActionsとAPI Routesにおいて確認
- 2025/02現在、30秒の上限を変更することはできない
- 時間のかかる処理をAmplify外に移管し、ポーリング処理で状況を確認することで回避可能
該当Issue
タイムアウトの時間を引き上げる要望Issueが、AmplifyのGitHubリポジトリ上で作成されています。
ポーリング処理による対応方法
サーバ処理が30秒を超えている場合、ポーリング処理に切り替えることでタイムアウトを回避可能です。
元の処理
次のサーバ処理(ServerActions)呼び出しは、実行に30秒以上かかるのでAmplify上ではタイムアウトするとします。
なお、下記の例では簡略化のためにエラー処理などを省略しています。
page.tsx
const handleClick = async () => {
await executeRequest();
};
// (中略...)
<button onClick={handleClick}>Click</button>
action.ts
export async function executeRequest() {
// 実行に30秒以上かかる
const res = await fetch("https://...");
const data = await res.json();
return data;
}
ポーリング導入後の処理
Next.jsから呼び出すサーバ処理を、それぞれ30秒以内に完了する非同期リクエストAPIとポーリングAPIに変更します。時間のかかっていた部分は、Amplify外の非同期処理(Lambdaなど)に移管します。
ここでは移管したコードは省略し、Next.jsとしての実装の変更を記述します。
page.tsx
const handleClick = async () => {
await executeAsyncRequest();
startPolling();
};
const startPolling = () => {
// 10秒ごとにデータ状態を確認する
const intervalId = setInterval(async () => {
const data = await fetchPollingData();
if (data.isSucceeded) {
// 処理完了後、必要な操作(今回はダウンロード)を実行して定期実行を解除
downloadData(data);
clearInterval(intervalId);
}
}, 10000);
};
// (中略...)
<button onClick={handleClick}>Click</button>
action.ts
export async function executeAsyncRequest() {
// 非同期処理(Lambdaなど)を開始するAPIを呼び出す
const res = await fetch("https://.../start-async");
const data = await res.json();
return data;
}
export async function fetchPollingData() {
// データ状態(DBなど)を確認するAPIを呼び出す
const response = await fetch("https://.../polling");
const data = await response.json();
return data;
}

NCDC株式会社( ncdc.co.jp/ )のエンジニアチームです。 募集中のエンジニアのポジションや、採用している技術スタックの紹介などはこちら( github.com/ncdcdev/recruitment )をご覧ください! ※エンジニア以外も記事を投稿することがあります
Discussion