502・503・504 の違いと切り分け方
502 Bad Gateway・503 Service Unavailable・504 Gateway Timeout は いずれも「サーバー側で処理できなかった」ことを示す5xxエラーですが、意味と調べる場所は明確に異なります。 この違いを押さえると、障害対応の初動もAPI設計も迷いません。
502 = the upstream returned an invalid response. 503 = the service itself is temporarily unavailable. 504 = the upstream did not respond in time.
TL;DR
- 502: 中継役(ゲートウェイ)が上流から不正な応答を受けた、または接続できない
- 503: サービス自身が一時的に処理不能(過負荷・メンテナンス)
- 504: 上流の応答が時間切れ(遅い処理・タイムアウト不整合)
1. 比較表 / Comparison
| 観点 | 502 Bad Gateway | 503 Service Unavailable | 504 Gateway Timeout |
|---|---|---|---|
| 意味 | 上流から不正な応答 | 一時的に処理不能 | 上流の応答が時間切れ |
| 主な原因 | 上流のクラッシュ・接続拒否・設定ミス | アクセス集中・メンテナンス・ヘルスチェック全滅 | 遅いSQL・外部API待ち・タイムアウト不整合 |
| 誰が返すか | ゲートウェイ(LB・プロキシ) | サーバー本体またはLB | ゲートウェイ(LB・プロキシ) |
| 訪問者の対処 | 少し待って再読み込み | Retry-Afterや案内に従って待つ | 待つ。フォーム再送信は履歴確認後 |
| 運営者が最初に見る場所 | 上流の起動状態とエラーログ | 容量・ヘルスチェック・メンテ計画 | 処理時間と各層のタイムアウト値 |
| Retry-Afterの慣行 | 通常付けない | 付けるのが推奨 | 通常付けない |
2. 判断フロー / Decision flow
ポイントは「誰が異常を検出したか」です。503はサービス自身の宣言、 502と504は中継役が上流の異常を検出した結果で、その内訳が「不正応答なら502・時間切れなら504」です。
3. API・LB設計でどれを返すべきか / Which to return
- 計画メンテナンス:
Retry-After付きの503。復帰予定をクライアントに伝えられる唯一の選択肢です - 過負荷で受付を絞る: 503。ロードシェディングやキュー溢れも503が適切です
- ヘルスチェック全滅: LBは転送先が無いため502または503を返します(AWS ALBは503、多くのnginx構成は502)。どちらになるかは製品仕様を確認します
- 上流の応答待ちが時間切れ: 504。ゲートウェイのタイムアウト値とアプリの処理時間の不整合を疑います
- アプリのバグで不正応答: 中継役が502に変換します。アプリ自身が例外を握って500を返すのとは区別されます
Use 503 with Retry-After for planned maintenance and load shedding. Let the gateway emit 502 for invalid upstream responses and 504 for upstream timeouts — do not fake these from the app.
4. 監視・アラート運用での違い / Monitoring
| コード | 初動で疑うこと | 確認するもの |
|---|---|---|
| 502急増 | デプロイ直後のクラッシュ・接続設定の変更 | 直近のデプロイ履歴、上流プロセスの生存、エラーログ |
| 503急増 | 容量不足・ヘルスチェック失敗 | RPS、オートスケール状況、正常ターゲット数 |
| 504急増 | 遅い処理の混入・タイムアウト不整合 | レイテンシ分布(p95/p99)、遅いSQL、各層のタイムアウト値 |
3つを同じ「5xxエラー」として1本のアラートにまとめると、初動で見る場所が定まりません。 コード別にダッシュボードを分け、502はデプロイイベントと、503は容量メトリクスと、 504はレイテンシと並べて表示するのが定石です。
5. ログでの見え方 / Log examples
nginxのアクセスログでは、3つのコードは次のように現れます。upstream_response_time の値が切り分けの決め手になります。
# 502: 上流に接続できない(応答時間はほぼ0)
10.0.0.1 - [26/Jul/2026:12:00:01 +0900] "GET /api/users HTTP/1.1" 502 559 upstream_response_time=0.001
# 503: 自身が処理不能(メンテモードや過負荷)
10.0.0.1 - [26/Jul/2026:12:00:02 +0900] "GET /api/users HTTP/1.1" 503 197 upstream_response_time=-
# 504: タイムアウトまで待って諦めた(応答時間=タイムアウト値)
10.0.0.1 - [26/Jul/2026:12:00:03 +0900] "GET /api/report HTTP/1.1" 504 167 upstream_response_time=60.001502は即座に失敗するため応答時間が極端に短く、504はタイムアウト設定値ちょうどまで待った形跡が残ります。 503で upstream_response_time が空なら、上流に到達する前に自身が返しています。
6. nginxで実際に再現する / Reproducing with nginx
nginxをリバースプロキシとして使い、上流(upstream)を止める・遅らせるだけで502と504を手元で再現できます。 以下は最小構成です。upstream ブロックで転送先を指定し、proxy_pass で中継します。
upstream backend {
server 127.0.0.1:8080;
}
server {
listen 8888;
location / {
proxy_pass http://backend;
proxy_connect_timeout 3s;
proxy_read_timeout 5s;
}
}この状態で上流(127.0.0.1:8080)のプロセスを止めてアクセスすると502が返り、 nginxの実装では error_log に次の形式の行が記録されます。
2026/08/21 12:00:01 [error] 1234#0: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 10.0.0.1, server: _, request: "GET /api/users HTTP/1.1", upstream: "http://127.0.0.1:8080/api/users", host: "example.com"次に上流を起動したまま応答を proxy_read_timeout より遅くする(例えばアプリ側で10秒スリープさせる)と504が返り、 nginxの実装では次の形式の行が記録されます。
2026/08/21 12:00:10 [error] 1234#0: *2 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 10.0.0.1, server: _, request: "GET /api/report HTTP/1.1", upstream: "http://127.0.0.1:8080/api/report", host: "example.com"エラーコード (111: Connection refused) は「接続自体を拒否された」ことを、(110: Connection timed out) は「接続または応答待ちが規定時間を超えた」ことを示すLinuxのerrno相当の番号で、 502と504の区別はこの番号とメッセージ文言(connect() failed か upstream timed out か)で機械的に判定できます。
7. Cloudflare配下での見分け方 / Behind Cloudflare
Cloudflareのようなリバースプロキシ型CDNを経由している場合、502や504が「Cloudflare自身が生成したもの」か 「オリジンサーバーが生成し素通りしたもの」かを区別する必要があります。判断材料は次の通りです。
- レスポンスヘッダの
cf-ray: Cloudflareを経由したリクエストには必ず付与されます。 このヘッダの有無自体は「Cloudflareを通ったか」の確認にしかならず、どちらが生成したかの判定には使えません - エラーページの見た目: Cloudflareが自ら生成する502/504(Cloudflare独自のエラー画面、 エラーコード欄に「Error 502」「Error 504」とCloudflareのロゴ付きで表示される)は、 オリジンが返すエラーページ(アプリやnginxのデフォルトエラーページ、または独自のカスタムエラーページ)とHTML構造・文言が異なります。 ブラウザで開いたときにCloudflareのブランドが入ったページなら、Cloudflare層で止まっている可能性が高いです
Server/Viaヘッダ: Cloudflareが応答を生成した場合はServer: cloudflareが付きますが、 オリジンのエラーがそのまま通過した場合もCloudflareがヘッダを付け替えるため、このヘッダ単独では発生源を断定できません。 後述のcurlでの切り分けと合わせて確認します
実務上は、Cloudflareのダッシュボード(Analytics & Logs)でエッジ側のステータスコード分布を確認し、 オリジンのアクセスログのコードと突き合わせるのが最も確実です。エッジのみで502が出てオリジンログに記録が無ければ、 Cloudflareからオリジンへの接続自体が失敗しています。
8. curlでの切り分けワンライナー / Diagnosing with curl
どの層がエラーを生成したかは、応答ヘッダとタイミングの両方から絞り込みます。まず詳細な通信ログとヘッダを確認します。
curl -sv https://example.com/api/users -o /dev/null-v の出力に含まれる Server: と Via: ヘッダを見ます。Server: cloudflare や Via: にCDN・プロキシ名が入っていれば、そのレイヤーを経由したことが分かります。 オリジン側のWebサーバー名(Server: nginx 等)がそのまま見えている場合は、CDNがヘッダを書き換えずに素通りさせています。
次に、応答コードと所要時間を同時に取得し、タイムアウト起因かどうかを判定します。
curl -s -o /dev/null -w '%{http_code} %{time_total}s\n' https://example.com/api/report%{time_total} がゲートウェイやCDNのタイムアウト設定値(例えば30秒や60秒)にほぼ一致していれば504の典型パターンです。 逆に1秒未満で502が返る場合は、接続自体を即座に拒否されている(タイムアウトではなく接続不可)と判断できます。 502と503の切り分けには -w にヘッダ確認を組み合わせ、Retry-After の有無も見ます。
curl -s -o /dev/null -D - https://example.com/ | grep -i 'retry-after\|http/'9. Retry-Afterの実挙動 / How Retry-After actually behaves
Retry-After ヘッダはRFC 9110で秒数指定とHTTP-date指定の2形式が認められています。
# 形式1: 秒数指定(相対時間)
Retry-After: 120
# 形式2: HTTP-date指定(絶対時刻、RFC 7231形式)
Retry-After: Fri, 21 Aug 2026 12:05:00 GMT秒数指定は実装が単純でクロックのずれの影響を受けないため、多くのサーバー実装で採用されています。 HTTP-date指定は複数のプロキシ層を経由してヘッダが転送される間に時間が経過しても、絶対時刻なので誤差が生じにくい利点があります。
GooglebotはRetry-Afterを尊重してクロール頻度を調整することが案内されていますが、 指定した時間が経過すれば必ず即座に再クロールされるとは限らず、あくまでクロール優先度の調整材料の一つとして扱われます。 主要ブラウザはRetry-Afterを自動リロードには使わず、ページの表示情報として扱う(自動での再送信は行わない)のが一般的です。 API向けのHTTPクライアントライブラリでは、リトライ機構がRetry-Afterを自動的に読み取ってバックオフ時間に反映するものと、 無視して独自の指数バックオフのみを行うものが混在するため、外部APIを呼ぶ側は使用ライブラリの挙動をドキュメントで確認する必要があります。
10. 間違いやすいパターン / Common pitfalls
- 過負荷で502と503が混在する: ワーカーが落ちれば502、受付制限に達すれば503と、上流の「落ち方」で分かれるため混在は珍しくありません
- CDNが独自に503を返す: オリジンは正常でもCDN側のレート制限やWAFが503を返すことがあります。どの層の応答かをヘッダで確認します
- メンテ画面を200で返す: 検索エンジンがメンテ画面を本来のコンテンツとして扱い、インデックスを汚染します。必ず503+Retry-Afterで返します
11. よくある質問 / FAQ
ブラウザに出たコードだけで原因は特定できる?
できません。同じ502でもLBが返したのかプロキシが返したのかで調査対象が変わります。運営者はレスポンスヘッダ(Server等)とログで「どの層が生成したか」を最初に特定します。
アプリから502や504を自分で返してもいい?
推奨しません。502と504は「中継役が観測した上流の異常」を表すコードなので、アプリ自身のエラーは500、過負荷なら503を返し、502/504はゲートウェイに任せると切り分けが単純になります。
3つとも出るサイトはどこが悪い?
過負荷が進行すると503(受付制限)→502(ワーカークラッシュ)→504(処理遅延)が同時多発します。この場合は個々のコードより容量とボトルネックの解消が先です。
Retry-Afterは秒数指定とHTTP-date指定のどちらを使うべき?
実装の単純さと誤差の少なさから秒数指定が広く使われていますが、どちらもRFC 9110で正式に認められた形式です。 受け取る側のクライアントが両形式に対応しているとは限らないため、自作のリトライ処理を書く場合は両方をパースできるようにしておくと安全です。
12. English summary
All three are gateway-related 5xx errors, but they point to different failures.502 Bad Gateway means the gateway received an invalid response or could not connect to the upstream — check whether the upstream process is alive.503 Service Unavailable means the service itself is temporarily unable to serve requests due to overload or maintenance — return it with a Retry-After header.504 Gateway Timeout means the upstream did not respond within the time limit — profile slow queries and align timeout values across CDN, load balancer, proxy, and application. In monitoring, alert on each code separately: 502 correlates with deployments, 503 with capacity, and 504 with latency.
よくある質問 / FAQ
- 502と504はどう違う?
- どちらもゲートウェイが上流とやり取りできなかったエラーですが、502は「不正な応答を受けた・接続できない」、504は「制限時間内に応答が届かなかった」です。502は上流のクラッシュや設定ミス、504は遅い処理が典型原因です。
- 503と502はどちらがサイト側の問題?
- どちらもサイト側の問題です。違いは応答の出どころで、503はサービス自身が「今は処理できない」と宣言する応答、502は中継役が上流の異常を検出して返す応答です。
- メンテナンス時に返すべきコードは?
- Retry-Afterヘッダ付きの503です。200でメンテナンス画面を返すと検索エンジンがその内容を本来のページとして扱う恐れがあり、502や504は障害と区別できなくなります。
- 5xxが混在する時はどこから調べる?
- どの層がそのコードを生成したかの特定が先です。CDN・LB・リバースプロキシ・アプリのログを同じ時刻とリクエストIDで突き合わせ、最初に異常を検出した層を見つけます。過負荷時は上流の落ち方によって502と503が混在します。
- What is the difference between 502, 503 and 504?
- 502 means the gateway received an invalid response from the upstream. 503 means the service itself is temporarily unable to handle requests, typically due to overload or maintenance. 504 means the upstream did not respond within the time limit.
- モニタリングでは3つをどう使い分けて対応する?
- 502はデプロイ直後のクラッシュや接続設定を、503は容量とヘルスチェックを、504は遅い処理と各層のタイムアウト整合を最初に確認します。コード別にアラートを分けると初動が速くなります。
- Retry-Afterは秒数指定とHTTP-date指定のどちらを使うべき?
- 実装の単純さと誤差の少なさから秒数指定が広く使われていますが、どちらもRFC 9110で正式に認められた形式です。受け取る側のクライアントが両形式に対応しているとは限らないため、自作のリトライ処理を書く場合は両方をパースできるようにしておくと安全です。