> ## Documentation Index
> Fetch the complete documentation index at: https://docs.solvice.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Limits

> Size, time and value limits on a V3 Routing API request, and what you get when you exceed one

## Overview

These limits apply to `POST /v3/routing/solve`, `/v3/routing/evaluate` and `/v3/routing/suggest`. Most are checked before any travel times are fetched, so an oversized request fails fast and is reported by `?validate_only=true` as well.

A request over a count limit gets a `400` whose `errors[]` item has code `limit_exceeded`, the `limit` and the `actual` count your request has:

```json 400 Bad Request theme={null}
{
  "status": "BAD_REQUEST",
  "code": "invalid_request",
  "message": "the request has 10250 tasks (jobs + shipments); the maximum is 10000",
  "request_id": "req_5c1e8a3f9d02b746",
  "errors": [
    {
      "code": "limit_exceeded",
      "pointer": "/problem/jobs",
      "message": "the request has 10250 tasks (jobs + shipments); the maximum is 10000",
      "limit": 10000,
      "actual": 10250
    }
  ]
}
```

See [Errors](/guides/vrp/v3/errors) for the full error body.

## Request

| Limit | Value | When you exceed it |
| - | - | - |
| Body size | 10 MiB, measured after decompression | `413`, code `payload_too_large` |
| Body compression | `Content-Encoding: gzip`, or none | `415`, code `unsupported_media_type` |
| Content type | `application/json` | `415`, code `unsupported_media_type` |
| Problems listed in one error response | 100 | The `message` says the list was cut; fix those and resend |

## Solve time

| Limit | Value | When you exceed it |
| - | - | - |
| `options.time_limit_s` on solve | Default `1`. Maximum `300`. `0` is raised to 100 ms | `400`, item `limit_exceeded`, pointer `/options/time_limit_s` |
| `options.time_limit_s` on suggest | No default: the search runs to completion. Maximum `300`. `0` is raised to 100 ms | `400`, item `limit_exceeded`, pointer `/options/time_limit_s` |
| `options.max_suggestions` on suggest | Default `5`. `0` returns all. Maximum `100` | No error: a larger value is lowered to `100` |

`time_limit_s` is whole seconds and counts search time only. Fetching travel times and waiting for a free solver are not deducted from it, so the request takes somewhat longer than the budget you set; set your HTTP client timeout accordingly. Evaluate takes no `options` because it does not search.

## Problem size

| Limit | Value | When you exceed it |
| - | - | - |
| Tasks: `jobs` plus `shipments` | 10,000 | `400`, item `limit_exceeded`, pointer `/problem/jobs` (`/problem/shipments` when there are no jobs) |
| `vehicles` | 2,000 | `400`, item `limit_exceeded`, pointer `/problem/vehicles` |
| Stops in total | 65,535, counting every job, both stops of every shipment, a start and an end for every vehicle shift, and the reload visits each shift may make | `400` |
| Distinct locations | 65,535 | `400` |
| `quotas` | 65,535 | `400`, item `limit_exceeded`, pointer `/problem/quotas` |
| Reloads at one depot in one shift | 8. The solver plans no more than that. List more than one depot in `shifts[].reloads` to allow more reloads in a shift | A `plan` with more is a `400`, item `invalid_value`, pointer `/plan/routes/{i}/stops/{k}`. This is checked when the plan is matched to the problem, so `?validate_only=true` does not report it |

## Capacity, skills and tags

| Limit | Value | When you exceed it |
| - | - | - |
| Capacity dimensions | 4 distinct names, counted across every `demand`, `delivery`, `capacity` and `initial_load` in the request | `400`, item `limit_exceeded`, pointer `/problem/vehicles`. The message lists the names found |
| Required skills | 256 distinct combinations of skill `name` and `min_level` across all tasks. Skills that only vehicles have do not count | `400`, item `limit_exceeded`, pointer `/problem/jobs` |
| Task tags | 256 distinct values across `jobs[].tags` and `shipments[].tags`. `serves_tags` and `preferred_tags` on the vehicle side do not count | `400`, item `limit_exceeded`, pointer `/problem/jobs` |
| `eligible_vehicles` | 256 distinct vehicle sets across all tasks, after `allowed` and `excluded` are resolved. A set equal to the whole fleet does not count | `400`, item `limit_exceeded`, pointer `/problem/jobs` |
| Per-task `service_factors` | When any task sets it: vehicle shifts multiplied by task stops must not exceed 10,000,000 | `400`, item `limit_exceeded`, pointer `/problem/jobs` |

In a request with shipments and no jobs, the pointers shown as `/problem/jobs` in this table read `/problem/shipments`.

<Tip>
  The four-dimension limit counts names, not vehicles. A typo such as `wieght` on one job counts as a dimension of its own. When you hit this limit unexpectedly, read the names in the error message.
</Tip>

## Relations

| Limit | Value | When you exceed it |
| - | - | - |
| Participants in one `synchronized` relation | 8 | `400`, item `limit_exceeded`, pointer `/problem/relations/{i}` |
| Tasks linked together across vehicles by `synchronized` and `time_lag` relations, and the `ordered` relations that join them | 16 in one linked group | `400` |
| `ordered` relations that use `groups` | 1 per request, with at least 2 groups | `400` |

## Values

| Limit | Value | When you exceed it |
| - | - | - |
| Shift ids and depot ids | 1 to 128 characters | `400`, item `invalid_value`, pointer to the `id` |
| `drop_fee` | At most 1,000,000,000 | `400`, item `out_of_range` |
| `depots[].cost_per_visit` | At most 1,000,000,000 | `400`, item `out_of_range` |
| Service time after `service_factor` is applied | At most 100,000,000 seconds | `400`, item `out_of_range` |
| `speed_factor`, `service_factor` and `service_factors[].factor` | From 0.001 to 5 | `400`, item `out_of_range` |
| `limits.max_distance_m` and `limits.max_route_duration_s` | At most 2,147,483,647 | `400`, item `out_of_range` |

### Prices

Amounts are in your currency. Prices have lower ceilings than `drop_fee` and `depots[].cost_per_visit`.

| Field | Maximum | When you exceed it |
| - | - | - |
| `preferences[].violation_cost` | 21,474.83 per entry, and 21,474.83 for all entries of one task added together | `400`, item `out_of_range` |
| `target.per_late_hour` | 21,474.83 | `400`, item `out_of_range` |
| `time_windows[].cost` | 21,474.83 | `400`, item `invalid_value`, pointer to the task's `time_windows` |
| `time_windows[].per_late_hour` | 1,288,490 | `400`, item `out_of_range` |
| `objective.costs.per_late_hour` | 1,288,490 | `400`, item `out_of_range` |
| `objective.costs.per_travel_km` | 21,474,836 | `400`, item `out_of_range` |
| `objective.costs.per_route_hour`, `per_wait_hour` and `per_overtime_hour` | 77,309,411 | `400`, item `out_of_range` |

For a rule that must always hold, use the hard field and not a high price: `eligible_vehicles` in place of a large `violation_cost`, and a time window with no lateness price in place of a large lateness rate. See [Constraints](/guides/vrp/v3/constraints).

## Rate limits

Requests are also rate limited by the API gateway. A request over the rate limit is rejected with `429`, and that response does not use the routing error body: see [429 Too Many Requests](/guides/vrp/v3/errors#429-too-many-requests). The `x-ratelimit-limit` and `x-ratelimit-remaining` response headers report your rate limit and how much of it is left.

When the service is at capacity it answers `503` with a `Retry-After` header. See [Errors](/guides/vrp/v3/errors#503-service-unavailable).

<Columns cols={2}>
  <Card title="Errors" icon="triangle-exclamation" href="/guides/vrp/v3/errors">
    The error body and every code.
  </Card>

  <Card title="Performance" icon="gauge-high" href="/guides/vrp/v3/concepts/performance-guide">
    Choosing a time limit for your problem size.
  </Card>
</Columns>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.