n8n Webhookタイムアウトの解決方法を示すサーバーとネットワークケーブルのイメージ

n8nでWebhookを本番運用していると、外部サービスからの呼び出しがタイムアウトエラーになり、処理自体は完了しているのにエラー扱いされる現象に悩まされることがあります。実はn8nには標準で約60〜64秒のタイムアウト制限があり、これに気づかず設計すると必ず発生する問題です。

そこで今回は、インフラエンジニアの視点で「n8n Webhookタイムアウト」の仕組みと解決策の実践を行ってみました!設定例を交えて解説しますので、ぜひ皆さんも記事を読んで試してみてください!

この記事で分かること

  • n8nのWebhookタイムアウトが発生する仕組みと、セルフホスト・Cloudでの違い
  • タイムアウトの原因を「処理時間」と「プロキシ設定」の2パターンに切り分ける方法
  • N8N_WEBHOOK_TTL、非同期設計、Nginx/Traefik設定変更という3つの解決策

n8nのWebhookタイムアウトが起きる仕組み

n8nのWebhookノードは、リクエストを受け取ってから応答を返すまでの時間に上限を設けています。この上限はデフォルトで60秒から64秒程度に設定されており、内部処理のバッファを含めるとおよそ64秒でタイムアウトが発生します。ワークフローの処理がこの時間内に完了しないと、外部サービス側には504 Gateway Time-outなどのエラーが返されます。この時n8n側では処理が正常終了していても、呼び出し元からは失敗として記録されてしまうのが厄介な点です。

n8nのWebhookタイムアウトで確認すべき点

  • デフォルトのタイムアウトは約60〜64秒であること
  • n8n本体だけでなく前段のプロキシ設定も影響すること
  • 処理が正常終了していてもエラー表示される場合があること

ここで、セルフホストとn8n Cloudで対処方法は変わるのかという疑問が出てくると思います。

大きな差としては、「セルフホストのみ環境変数によるタイムアウト延長が可能」ということです。これにより、Cloud環境では非同期設計への変更が実質的に唯一の解決策になることになります。

今話題の、「Respond to Webhookによる即時応答パターン」というやつですね!

比較すると、以下のようになります。

項目セルフホストn8n Cloud
タイムアウト延長N8N_WEBHOOK_TTLで可能不可
プロキシ設定変更Nginx/Traefik側で可能不可(運営側管理)
推奨対策環境変数+プロキシ設定非同期設計への変更

「n8n Webhookタイムアウトの原因特定って難しそう…」と感じるかもしれませんが、この記事を読めば初心者の方でも大丈夫!順を追って原因の切り分けから設定変更まで解説します。

原因を切り分ける2つのパターン

手順1:処理が重くタイムアウト時間内に終わらないケース

ワークフロー内でAI生成、外部API呼び出し、大量データの加工などの重い処理を直列に実行していると、処理時間がデフォルトの60秒を超えてしまいます。特にHTTP Requestノードで複数の外部APIを順番に呼び出す構成や、AIエージェントノードで生成に時間がかかる場合は、合計処理時間が想定より長くなりがちです。

見分け方として、n8nの実行ログでWebhookトリガーから最終ノードまでの実行時間を確認します。エラーが発生した実行の合計時間が55秒から65秒付近に集中している場合は、処理時間そのものがタイムアウトに近づいていることが原因です。

# 確認ポイント
Executions > 対象の実行を開く > 実行時間(Duration)を確認
55秒〜65秒に集中していれば処理時間が原因の可能性が高い

手順2:プロキシ(Nginx等)側のタイムアウト設定が原因のケース

もう一つの典型的な原因は、n8n本体ではなく前段のリバースプロキシ側でタイムアウトが発生しているケースです。セルフホスト環境でNginxやTraefikを経由してWebhookを公開している場合、プロキシのデフォルトタイムアウトが60秒程度に設定されていることが多く、n8n側の設定を延長してもプロキシ側で先に接続が切断されてしまいます。

このケースを見分けるには、n8nの実行履歴で処理自体は正常終了しているにもかかわらず、呼び出し元のクライアントには504エラーが返っている状態を確認します。n8n側の実行が成功しているのに外部サービス側だけがエラーを受け取っている場合は、プロキシのproxy_read_timeoutなどの設定を見直す必要があります。

# ファイル名: check_proxy.sh
curl -o /dev/null -s -w "response_code:%{http_code} time:%{time_total}\n" https://your-n8n-domain/webhook/xxxx

解決する3つの方法

手順1:環境変数N8N_WEBHOOK_TTLでタイムアウト時間を延長する

セルフホスト環境であれば、環境変数N8N_WEBHOOK_TTLを設定することでWebhookのタイムアウト時間を延長できます。単位は秒で、例えば300を指定すると5分までタイムアウトを延長できます。

基本的に方法Aがおすすめです。この後の説明も、方法Aを元に行います。

方法A:docker-composeで環境変数を追加(おすすめ)

docker-compose.ymlのenvironmentセクションに追記し、コンテナを再起動して反映させます。

# ファイル名: docker-compose.yml
services:
  n8n:
    image: n8nio/n8n
    environment:
      - N8N_WEBHOOK_TTL=300
    ports:
      - "5678:5678"

方法B:.envファイルに直接記載(お試し向け)

単一サーバーで手軽に試す場合は.envファイルに直接記載する方法もあります。

# ファイル名: .env
N8N_WEBHOOK_TTL=300

手順2:Webhook→Respond to Webhook→重い処理という非同期設計に変更する

最も安定した解決方法は、Webhookが受信したらすぐに応答を返し、重い処理は後続で非同期に実行する設計に変更することです。具体的には、Webhookノードの直後にRespond to Webhookノードを配置し、200 OKなどの即時応答を返してから、後続で本来の重い処理を実行します。

設定手順としては、まずWebhookノードのRespondパラメータをUsing Respond to Webhook nodeに変更します。次に、Webhookノードの直後にRespond to Webhookノードを接続し、レスポンス内容を設定します。その後、実際の重い処理ノード群を並列または直列に接続します。

{
  "webhookNode": { "respond": "responseNode" },
  "respondToWebhookNode": {
    "responseCode": 200,
    "responseBody": { "status": "accepted" }
  }
}

外部サービス側で処理完了の通知が必要な場合は、処理完了後にコールバック用のHTTP Requestノードを追加し、外部サービスへ結果をPOSTする構成にすると、ポーリング不要で完了通知まで実現できます。

手順3:Nginx/Traefikのproxy_read_timeout設定を変更する

Nginxをリバースプロキシとして使っている場合は、proxy_read_timeoutディレクティブの値をn8n側のN8N_WEBHOOK_TTLと同等以上に設定します。

# ファイル名: nginx.conf
location /webhook/ {
    proxy_pass http://localhost:5678;
    proxy_read_timeout 300s;
    proxy_send_timeout 300s;
}

Traefikを利用している場合は、サービス定義にforwardingTimeoutsのタイムアウト設定を追加します。

# ファイル名: traefik-dynamic.yml
http:
  serversTransport:
    n8n-transport:
      forwardingTimeouts:
        dialTimeout: "10s"
        responseHeaderTimeout: "300s"

設定変更後は必ずリロードし、n8n側のN8N_WEBHOOK_TTLと数値を揃えておくことで、どちらか一方だけが先にタイムアウトする事態を防げます。

タイムアウトを未然に防ぐワークフロー設計

設計段階での対策

タイムアウトは事後対応よりも、設計段階で防ぐほうが運用コストを抑えられます。まず、Webhookトリガーの直後には常にRespond to Webhookを置き、即時応答を返す構成をデフォルトルールにすることをおすすめします。ただ、特に工夫が思いつかなかったため、そこも含めて設計方針をチェックリスト化してみました!

何度か検証し、今回はWebhook受付を軽量化する設計パターンを整理することにしました。

重い処理は別のサブワークフローやキューイングに切り出し、メインのWebhook受付フローを軽量に保つことで、処理時間の増減がタイムアウトに直結しなくなります。

推奨される設計パターン

  • 即時応答パターン
    Webhook直後にRespond to Webhookを配置し、200 OKを即座に返す
  • サブワークフロー分離
    重い処理をExecute Workflowノードで別ワークフローに切り出す
  • 並列実行の活用
    直列に多数の外部API呼び出しを行わず、可能な限り並列実行に変更する

この構成にすることで、処理時間が延びてもクライアント側のタイムアウトには影響しなくなり、運用が安定しました。

監視ルールの導入

さらにn8nの実行ログを定期的に監視し、実行時間が30秒を超える処理があれば早期に非同期化を検討する運用ルールを設けておくと、タイムアウトの再発を防げます。

ただ、これも手動でログを確認するだけですが、以下のように監視条件を設定しています。

# 監視ルール例
Executions画面でDuration列をソート
30秒を超える実行が継続する場合は非同期設計へ移行を検討

この運用ルールを取り入れてから、タイムアウトエラーの再発はほぼなくなりました。

n8n Webhookタイムアウト対策で気になった点

基本的に不満点は少なく、設計変更さえ行えば安定運用できるため、対応しない手はないと感じました!ただ、実際に運用して少し気になったことがあったので、それを共有しておきます。

気になった点1:n8n Cloudでは環境変数を変更できない

n8n Cloudを利用している場合、N8N_WEBHOOK_TTLをはじめとする環境変数を直接編集することができません。そのため長時間処理が発生するワークフローでは、非同期設計への変更が実質的に唯一の解決策となります。

気になった点2:プロキシとn8n両方の設定を揃える必要がある

N8N_WEBHOOK_TTLだけを延長しても、前段のNginxやTraefikのタイムアウト設定がそのままだと、プロキシ側で先に接続が切断されてしまいます。両方の設定値を必ず揃えておく必要がある点は、見落としやすい部分だと感じました。

まとめ:よくある質問

Q1. N8N_WEBHOOK_TTLはどこに設定すればいいですか?

セルフホスト環境のdocker-compose.ymlや.envファイルに環境変数として追記し、n8nコンテナを再起動することで反映されます。n8n Cloudでは設定できません。

Q2. Respond to Webhookノードを使うと処理結果を返せなくなりますか?

いいえ、即時応答後に別途コールバック用のHTTP Requestノードを使えば、処理完了時に結果を外部サービスへ通知できます。

Q3. n8n Cloudでタイムアウトを延長する方法はありますか?

n8n Cloudでは環境変数の直接編集ができないため、Webhook→Respond to Webhook→重い処理という非同期設計に変更することが実質的な解決策になります。

Q4. プロキシ設定とN8N_WEBHOOK_TTLはどちらを先に変更すべきですか?

どちらか一方だけを変更すると、設定していない側で先にタイムアウトが発生します。両方の値を同時に見直し、同等以上の数値に揃えることをおすすめします。