What it means: The backend accepted the request but did not finish its response within Envoy's route timeout, so Envoy answered 504.
Free online tool — HTTP status code checker: instant results, no signup.
Requests the address and shows the status code and what the server sends back.
When the route's timer fires, Envoy's router aborts the upstream request with the response flag UT (UpstreamRequestTimeout) and, when the timeout response code is 504 Gateway Timeout (the normal case), sends the body upstream request timeout (router.cc). The response therefore looks like this:
HTTP/1.1 504 Gateway Timeout
server: envoy
upstream request timeoutThe timer is the route timeout. Its documentation says: "If not specified, the default is 15s. This spans between the point at which the entire downstream request (i.e. end-of-stream) has been processed and when the upstream response has been completely processed", and "This timeout includes all retries" (route_components.proto). So a backend that streams a large response for more than 15 seconds can be cut off even though it started answering quickly.
This is not a connect problem: the connection worked. Failures to connect show up as upstream connect error with a 503.
| Setting | Where | Effect |
|---|---|---|
Route timeout | Envoy route config | Total budget for the request, including retries; 15 s when not set; 0 disables it |
Retry per_try_timeout | Route retry policy | Budget for each attempt; if unset, each attempt can use the whole route timeout, so a timed-out request is not retried |
x-envoy-upstream-rq-timeout-ms | Request header | Overrides the route timeout per request when the proxy trusts the caller's Envoy headers |
Istio VirtualService timeout | Istio | Istio's request timeout is disabled by default, so in a mesh this error usually comes from an explicit timeout on the route |
| Gateway or ingress settings | Envoy Gateway, Contour, API gateways | Products expose the same route timeout under their own names |
The per-try note matters for diagnosis: with a 5xx retry policy and no per-try timeout, a request that times out is not retried, because the total budget is already spent (RetryPolicy.per_try_timeout). In Istio, the default request timeout is disabled (Istio request timeouts), so look for a timeout: line in the VirtualService first.
A timeout in Envoy does not stop the work in your application. The backend may still finish the job after the client got a 504, so retried POSTs can run twice unless the endpoint is idempotent.
kubectl exec deploy/productpage -c istio-proxy -- curl -s -o /dev/null -w 'ttfb=%{time_starttransfer} total=%{time_total}\n' http://reviews:9080/report A total above the route timeout confirms the cause.istioctl proxy-config route deploy/productpage -o json | grep -n '"timeout"', or read your Envoy route config. No value means 15 s in plain Envoy.per_try_timeout lower than the route timeout if you rely on retries.timeout to 0 and rely on idle_timeout instead, which bounds silence rather than total duration.curl -s -o /dev/null -w '%{http_code} %{time_total}s\n' https://example.com/report
# 200 3.412sThe status must be 200 and the total time comfortably below the route timeout, not just under it: a response at 14.8 s against a 15 s limit will fail again under load. The access log should stop showing UT for the route. The HTTP status checker shows the status code and headers of your public URL from outside your network.
HTTP status codes are three-digit numbers that the server returns for every request. They tell the browser and search crawlers what happened: success, redirect, or error.
Enter a code or keyword — instant result with description.
1xx Informational, 2xx Success, 3xx Redirect, 4xx Client Error, 5xx Server Error.
For each code: typical causes and concrete steps to resolve.
How each code affects indexing and link juice transfer in Google.
choosing correct status
redirect optimization
5xx error diagnostics
landing page check
HTTP monitor alerts when response code changes or 5xx appears.
Sign up freeThe route timeout defaults to 15 seconds when it is not set. It covers the time from the end of the client request to the end of the upstream response and includes all retries.
No. Istio disables the request timeout by default, so an upstream request timeout in a mesh usually comes from a timeout set in a VirtualService, a gateway or the application itself.
The route timeout counts until the response has been completely processed, so a long download or stream hits it. Disable the route timeout for that route and use idle_timeout instead.
Only if a per_try_timeout is set below the route timeout. Without it, one attempt uses the whole budget and nothing is left for a retry.
Not necessarily. The proxy stops waiting, but the application may still complete the request, so make retried writes idempotent.
Free plan — 10 monitors, checks every 5 min, no card required. Upgrade for 1-minute interval and multi-region monitoring.