This document explains how to configure timeout and deadline settings for
Route Optimization API requests. Not setting these values or setting them incorrectly
can cause connection or response quality issues.

You define the timeout in the request body and the deadline in the request
header. The Route Optimization API processes the request within the time limit defined
by these parameters, respecting the shortest time value.

Configuring timeouts and deadlines lets you manage processing time in the
following ways:

- **Increase processing time:**
  - Solve high-complexity requests.
  - Obtain a higher quality response.
- **Decrease processing time:**
  - Solve low-complexity requests faster than the default.
  - Solve a request in less time but get a lower-quality response.

> [!NOTE]
> **Note:** Timeout and deadline parameters only apply when [`solvingMode`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/projects/optimizeTours.md.txt#body.request_body.FIELDS.solving_mode) is set to its default value of `DEFAULT_SOLVE`. Other `solvingMode` options, such as `VALIDATE_ONLY`, `DETECT_SOME_INFEASIBLE_SHIPMENTS`, or `TRANSFORM_AND_RETURN_REQUEST` typically don't require timeout adjustments because they are significantly faster.

## Understand your timeout and deadline needs

Review this section before configuring your timeouts and deadlines to verify you
understand how your endpoint and protocol choices affect these settings.

The following guidelines can help you confirm if you are using the right setup
for your objectives.

- Use **non-blocking endpoints** for continuous and repeated requests and for complex requests that benefit from longer solving times.
- Use **blocking endpoints** for small requests and quick delivery of results, accepting a quality trade-off.
- Use **gRPC:** for your day-to-day workflow, particularly for production applications.
- Use **REST** for testing, experiments, or one-off requests.

Click the button below to see a diagram that can help you determine which
sections of this document are most relevant to your setup.

[Open diagram in separate tab](https://developers.google.com/static/maps/documentation/route-optimization/images/timeouts-diagram.svg)

## Set the `timeout` parameter

Set the value for the [`timeout`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/projects/optimizeTours.md.txt#body.request_body.FIELDS.timeout) parameter in the request body to specify
the maximum time the server works on a request before returning a response. The
actual time spent may be shorter than the allotted time if the API finds an
optimal solution before reaching the maximum allotted time.

Set the [`timeout`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/projects/optimizeTours.md.txt#body.request_body.FIELDS.timeout) parameter using the [duration protocol
buffer](https://protobuf.dev/reference/protobuf/google.protobuf/#duration),
which is a duration in seconds that can range from 1 second to 1800 seconds.
Increase this value for up to 3600 seconds using
[`allowLargeDeadlineDespiteInterruptionRisk`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/projects/optimizeTours.md.txt#body.request_body.FIELDS.allow_large_deadline_despite_interruption_risk).

### Recommended `timeout` values

The following table lists recommended [`timeout`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/projects/optimizeTours.md.txt#body.request_body.FIELDS.timeout) values based on request
complexity and the number of shipments and vehicles.

| **Number of shipments and vehicles** | **No constraints** | **Loose time windows and load constraints or long routes** | **Tight time windows, load constraints, complex constraints, or very long routes** |
|---|---|---|---|
| 1 - 8 | 2s | 2s | 5s |
| 9 - 32 | 5s | 10s | 20s |
| 33 - 100 | 15s | 30s | 60s |
| 101 - 1,000 | 45s | 90s | 180s |
| 1,001 - 10,000 | 120s | 360s | 900s |
| 10,001 or more | 60s + 120s per 10k shipments | 360s per 10k shipments | 900s per 10k shipments |

## Set the deadline

Set the deadline in the request header to define the maximum time the
Route Optimization API spends processing a request. The following subsections describe
how to set deadlines for REST and gRPC requests.

### REST requests

When using REST to call a blocking endpoint, you can extend the deadline beyond
the default of 60 seconds, which is often too short for complex requests. You
must do this even if you have already specified a longer deadline in the request
body, since the default deadline overrides any `timeout` values set in the
request body that are larger than 60 seconds.

Extend the deadline beyond the default 60 seconds by setting the
`X-Server-Timeout` request header. Unlike in the request body, the value of the
header is the number of seconds, but without an "s" suffix. The maximum value
you can set for this header aligns with the [`timeout`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/projects/optimizeTours.md.txt#body.request_body.FIELDS.timeout) parameter's
restrictions.

The following code sample shows an HTTP header with `X-Server-Timeout` set to
1800 seconds.

```console
curl -X POST 'https://routeoptimization.googleapis.com/v1/projects/:optimizeTours' \
-H "Content-Type: application/json" \
-H "X-Server-Timeout: 1800" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
--data @- << EOM
{
  "model": {
    ...
  }
}
EOM
```

### Client libraries and gRPC requests

You don't need to configure a deadline when using client libraries or gRPC. The
default deadline when using them is 3600 seconds, the maximum request time for
this API. Configure solving time by only setting the timeout property in the
request body.

## Parameters that affect timeouts and deadlines

The following parameters affect how both timeouts and deadlines function:

- Control the maximum request deadline with `allowLargeDeadlineDespiteInterruptionRisk`.
- Define the behavior of the search, balancing solution quality against latency with `searchMode`.

### `allowLargeDeadlineDespiteInterruptionRisk`

The [`allowLargeDeadlineDespiteInterruptionRisk`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/projects/optimizeTours.md.txt#body.request_body.FIELDS.allow_large_deadline_despite_interruption_risk) parameter increases the
maximum request deadline to 3600 seconds. If this parameter is not set, the
maximum value for both the timeout and deadline parameters is 1800 seconds.

Set [`allowLargeDeadline DespiteInterruptionRisk`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/projects/optimizeTours.md.txt#body.request_body.FIELDS.allow_large_deadline_despite_interruption_risk) to `true` to
increase the value of the timeout and deadline parameters to up to 3600 seconds.

> [!NOTE]
> **Note:** Setting [`allowLargeDeadline DespiteInterruptionRisk`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/projects/optimizeTours.md.txt#body.request_body.FIELDS.allow_large_deadline_despite_interruption_risk) to `true` acknowledges that longer requests carry a higher risk of interruption, which can result in an error instead of a valid result.

The allowed values for [`allowLargeDeadline DespiteInterruptionRisk`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/projects/optimizeTours.md.txt#body.request_body.FIELDS.allow_large_deadline_despite_interruption_risk) are the
following:

- `true`: Increases the maximum value for timeout and deadline parameters to 3600 seconds while acknowledging the interruption risk.
- `false` (default): Keeps the maximum value for the timeout and deadline parameters of 1800 seconds.

If you believe you need a timeout longer than 3600 seconds, contact your Google
representative.

### `searchMode`

The [`searchMode`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/projects/optimizeTours.md.txt#body.request_body.FIELDS.search_mode) parameter controls how the optimizer searches for
solutions, allowing you to prioritize either a quicker response (lower latency)
or a higher quality solution.

When you prioritize higher solution quality, the optimizer takes a fair amount
of time to find a high-quality solution. For these longer requests, consider
setting a longer timeout and using non-blocking endpoints to avoid connection
issues.

The allowed values for [`searchMode`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/projects/optimizeTours.md.txt#body.request_body.FIELDS.search_mode) are the following:

- `SEARCH_MODE_UNSPECIFIED` (default): An unspecified search mode, equivalent to `RETURN_FAST`.
- `RETURN_FAST`: Stops the search after finding the first good solution.
- `CONSUME_ALL_AVAILABLE_TIME`: Spends all available time searching for better solutions. The API does not use all available time if it finds an optimal solution early.

## Enable keepalive pings

When you make requests to blocking endpoints with a timeout longer than 60
seconds, keepalive pings help prevent connection loss while you wait for a
response. Keepalive pings are small packets sent to maintain connection
activity, and to detect and prevent connection loss.

Configure these parameters based on the API protocol you use:

- **REST:** Configure keepalive on the TCP connection level.
- **gRPC:** Configure keepalive pings on the underlying TCP socket or directly in the gRPC protocol.

The following sections explain how to set up keepalive pings for both protocols.

### REST keepalive

Configuring keepalive pings when you use REST depends on your HTTP client
library. Client libraries and tools, such as `curl`, might provide specific
configuration options or enable pings automatically.

If your library exposes the underlying TCP socket, you can configure keepalive
pings directly on the TCP socket using options like `SO_KEEPALIVE`. Do this by
using functions like `setsockopt()` or their equivalent.

This [function hosted on GitHub](https://github.com/googlemaps/js-route-optimization-app/blob/fb99a7f531da506304658cbe058303651a5d56bf/python/gmpro/json/cfr_api.py#L95) demonstrates how to set this up correctly
for the Python built-in HTTP client.

Find more details on TCP-level keepalive in the [TLDP keepalive
overview](https://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html) or in your
HTTP client library documentation.

### gRPC keepalive

gRPC offers its own built-in keepalive mechanism as part of the protocol. See
the [gRPC keepalive guide](https://grpc.io/docs/guides/keepalive/) for
instructions on how to set this up in your client language.

> [!NOTE]
> **Note:** gRPC servers might refuse clients that send too many pings. Avoid setting the keepalive ping frequency too high.

#### gRPC sample request with keepalive

The following example shows how to make an [`optimizeTours`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/projects/optimizeTours.md.txt) request using
the Python client library and gRPC-level keepalive pings.

```python
from google.maps import routeoptimization_v1 as ro
from google.maps.routeoptimization_v1.services.route_optimization.transports import grpc as grpc_transport
import sys

_REQUEST_TIMEOUT_SECONDS = 1800
_KEEPALIVE_PING_SECONDS = 30

def create_channel(*args, **kwargs):
  raw_options = kwargs.pop("options", ())
  options = dict(raw_options)
  options["grpc.keepalive_time_ms"] = _KEEPALIVE_PING_SECONDS * 1000
  options["grpc.keepalive_timeout_ms"] = 5000
  # Allow any number of pings between the request and the response.
  options["grpc.http2.max_pings_without_data"] = 0
  print(f"Using options: {options}", file=sys.stderr)
  return grpc_transport.RouteOptimizationGrpcTransport.create_channel(
      *args,
      options=list(options.items()),
      **kwargs,
  )

def create_grpc_transport(*args, **kwargs):
  if "channel" in kwargs:
    raise ValueError(
        "`channel` is overridden by this function, and must not be provided."
    )
  return grpc_transport.RouteOptimizationGrpcTransport(
      *args,
      channel=create_channel,
      **kwargs,
  )

def run_optimize_tours(request):
  client = ro.RouteOptimizationClient(transport=create_grpc_transport)
  return client.optimize_tours(request, timeout=_REQUEST_TIMEOUT_SECONDS)
```