Skip to content

Request timeouts

Page as Markdown

    

Configure request timeouts in ambient mesh via waypoint proxies to prevent latency in upstream services from cascading into failures.

When a client encounters latency in an upstream service, the client can wait indefinitely, becoming unavailable and propagating failure throughout the network. Request timeouts mitigate this problem by severing the connection after a set period, ensuring that calls succeed or fail within a predictable timeframe.

By default, Istio does not apply a timeout to HTTP requests. This means that without configuration, a slow or unresponsive upstream can stall a client indefinitely. When you configure a timeout, be mindful of the tradeoff: a timeout that is too long delays failure detection and lets latency accumulate; a timeout that is too short causes requests to fail unnecessarily while waiting on a service that would have responded in time.

In this guide, you learn how to set up request timeouts in your ambient mesh.

Note

Request timeouts are supported at the edge of a cluster using a gateway, or when a workload is enrolled in the waypoint layer.

Before you begin

  1. Install an ambient mesh in your cluster.

  2. Label the default namespace to add it to the ambient mesh.

    kubectl label ns default istio.io/dataplane-mode=ambient
  3. Create a waypoint for the default namespace. A waypoint is required because this resiliency feature configures Layer 7 (L7) proxy behavior. For more information on using waypoints, see Configure waypoints.

    istioctl waypoint apply -n default --enroll-namespace --wait

Configure request timeouts

  1. To test request timeouts, deploy the httpbin service and a curl client.

    kubectl apply -f https://raw.githubusercontent.com/istio/istio/1.30.0/samples/httpbin/httpbin.yaml
    kubectl apply -f https://raw.githubusercontent.com/istio/istio/1.30.0/samples/curl/curl.yaml
  2. Test latency by simulating an endpoint with a 2-second delay. The httpbin application has an /delay/{delay} endpoint that simulates a response delay of the length requested.

    kubectl exec deploy/curl -- curl httpbin:8000/delay/2

    In the output, confirm that Time Total and Time Spent show a value of 2 seconds (0:00:02):

      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100   432  100   432    0     0    214      0  0:00:02  0:00:02 --:--:--   214
    
  3. Create an HTTPRoute resource to configure calls to httpbin with a 500ms timeout.

    kubectl apply -f - <<EOF
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: httpbin
    spec:
      parentRefs:
      - group: ""
        kind: Service
        name: httpbin
        port: 8000
      rules:
      - backendRefs:
        - name: httpbin
          port: 8000
        timeouts:
          request: 500ms
    EOF

    Note

    The Gateway API also defines an optional backendRequest timeout duration. Unlike request, which covers the full round trip including retries, backendRequest caps each individual backend attempt. This is useful when you have retries configured: for example, a request of 2s with a backendRequest of 500ms allows up to four retry attempts, each with a 500ms budget, bounded by the 2s total.

  4. Verify the timeout by making another call to httpbin.

    kubectl exec deploy/curl -- curl -v httpbin:8000/delay/2

    In the output, a 504 “Gateway Timeout” response is returned:

    * IPv6: (none)
    * IPv4: 10.96.103.171
    *   Trying 10.96.103.171:8000...
    * Established connection to httpbin (10.96.103.171 port 8000) from 10.244.0.37 port 45612
    * using HTTP/1.x
    > GET /delay/2 HTTP/1.1
    > Host: httpbin:8000
    > User-Agent: curl/8.16.0
    > Accept: */*
    >
    * Request completely sent off
    < HTTP/1.1 504 Gateway Timeout
    < content-length: 24
    < content-type: text/plain
    < date: Tue, 07 Jul 2026 17:42:22 GMT
    < server: istio-envoy
    < x-envoy-decorator-operation: httpbin.default.svc.cluster.local:8000/*
    <
    * Connection #0 to host httpbin left intact
    upstream request timeout
    
  5. You can also confirm the timeout by using the time command.

    time kubectl exec deploy/curl -- curl -v httpbin:8000/delay/2

    In the output, the total elapsed time is slightly above the 500ms timeout:

    kubectl exec deploy/curl -- curl -v httpbin:8000/delay/2  0.08s user 0.04s system 18% cpu 0.650 total
    

Cleanup

Delete the sample resources.

kubectl delete httproute httpbin
kubectl delete -f https://raw.githubusercontent.com/istio/istio/1.30.0/samples/httpbin/httpbin.yaml
kubectl delete -f https://raw.githubusercontent.com/istio/istio/1.30.0/samples/curl/curl.yaml

FAQs

Is it important to first remove existing timeouts from my applications, or can I just overlay mesh timeouts on top of them as they are?

Removing the logic from your applications and maintaining all resilience configuration in the mesh layer is simpler. However, leaving application-level timeouts in place is not harmful. Consider which timeout takes precedence. For example, an application-level timeout of 100ms preempts a 200ms timeout configured through Istio.

What should I set my timeout to?

In Understanding Distributed Systems, Robert Vitillo suggests setting timeouts to the 99.9th percentile latency of a service. If the client is waiting longer than the time it normally takes for 99.9% of requests to respond, sever the connection.

This principle is based on an acceptable false timeout rate of 0.1% of requests, where you accept that 1 in every 1000 requests times out erroneously.

You can use the observability features of ambient mesh to determine this latency number.