> ## 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.

# Depot management

> Dynamically assign trips to optimal depot sites based on proximity, cost, capacity, and operating hours

# Depot Selection

The VRP solver can dynamically select the best depot for each trip based on proximity, cost, waste stream compatibility, and operating hours. Instead of pre-assigning fixed locations, the solver evaluates multiple candidate sites and picks the optimal one per trip.

## Overview

Depot selection is essential for waste collection, logistics with intermediate stops, and any scenario where vehicles must visit a facility mid-route to unload. The solver supports:

* Multiple depots with different locations, costs, and capacities
* Operating hours as time windows on each depot
* Per-dimension capacity for selective unloading (e.g., tip only one compartment)
* Cost-based trade-offs between routing efficiency and cost

<Info>
  Depots are optional. When no `depots` are provided, the solver operates in standard routing mode. Adding depots enables the solver to automatically insert depot visits into routes where beneficial.
</Info>

## Basic Configuration

Define your depot in the `depots` array of the request. Each depot has a location, service duration, and capacity:

```json theme={null}
{
  "resources": [
    {
      "name": "truck-1",
      "capacity": [8000],
      "shifts": [{
        "from": "2024-03-15T06:00:00Z",
        "to": "2024-03-15T17:00:00Z",
        "start": {"latitude": 51.054, "longitude": 3.717},
        "end": {"latitude": 51.054, "longitude": 3.717}
      }]
    }
  ],
  "jobs": [
    {
      "name": "collection-1",
      "location": {"latitude": 51.067, "longitude": 3.724},
      "load": [280],
      "duration": 360
    },
    {
      "name": "collection-2",
      "location": {"latitude": 51.034, "longitude": 3.679},
      "load": [350],
      "duration": 360
    }
  ],
  "depots": [
    {
      "name": "transfer-station-north",
      "location": {"latitude": 51.090, "longitude": 3.660},
      "duration": 900,
      "capacity": [80000]
    },
    {
      "name": "transfer-station-south",
      "location": {"latitude": 51.012, "longitude": 3.675},
      "duration": 900,
      "capacity": [80000]
    }
  ]
}
```

<Info>
  When you omit `capacity`, the depot defaults to unlimited capacity across all load dimensions — vehicles unload all compartments. To restrict which compartments are unloaded, provide an explicit `capacity` array where `0` means "do not unload this dimension".
</Info>

### Depot Fields

| Field      | Type    | Required | Description                                             |
| ---------- | ------- | -------- | ------------------------------------------------------- |
| `name`     | string  | Yes      | Unique identifier for the depot (max 255 characters)    |
| `location` | object  | Yes      | Geographic coordinates (`latitude`, `longitude`)        |
| `duration` | integer | No       | Service/unloading time in seconds (default: 0)          |
| `capacity` | array   | No       | Multi-dimensional capacity matching job load dimensions |
| `cost`     | number  | No       | Per-visit cost in EUR (default: 0)                      |
| `windows`  | array   | No       | Operating hours as time windows                         |

## Operating Hours

Restrict when depots accept visits by adding time windows. The solver treats depot time window violations as hard constraints — it avoids scheduling visits outside operating hours.

```json theme={null}
{
  "depots": [
    {
      "name": "recycling-center",
      "location": {"latitude": 51.076, "longitude": 3.742},
      "duration": 900,
      "windows": [
        {
          "from": "2024-03-15T08:00:00Z",
          "to": "2024-03-15T17:00:00Z"
        }
      ]
    }
  ]
}
```

<Warning>
  If all depots have restrictive time windows and vehicle shifts extend beyond those hours, late collections may not be able to visit any depot. Ensure at least one depot's operating hours covers the full shift duration.
</Warning>

## Cost-Based Depot Selection

Assign a per-visit cost to each depot to model disposal fees. The solver balances routing efficiency against disposal cost — it may choose a more distant but cheaper depot when the savings justify the extra travel.

```json theme={null}
{
  "depots": [
    {
      "name": "premium-facility",
      "location": {"latitude": 51.082, "longitude": 3.648},
      "cost": 50.0,
      "duration": 600
    },
    {
      "name": "budget-facility",
      "location": {"latitude": 51.029, "longitude": 3.730},
      "cost": 15.0,
      "duration": 900
    }
  ]
}
```

### Tuning the Cost Trade-Off

Control how aggressively the solver avoids expensive depots using the `depotCostWeight` in the `weights` configuration:

```json theme={null}
{
  "weights": {
    "depotCostWeight": 5
  }
}
```

| Value         | Behavior                                                                    |
| ------------- | --------------------------------------------------------------------------- |
| `1` (default) | Balanced trade-off between travel time and depot cost                       |
| `> 1`         | Stronger preference for cheaper depots, even at the expense of extra travel |
| `0`           | Depot cost is ignored; selection is based only on proximity and constraints |

## Multi-Compartment Unloading

Depots support per-dimension capacity, enabling selective unloading. When a vehicle visits a depot, only the load dimensions where the depot has capacity (> 0) are reset.

```json theme={null}
{
  "resources": [
    {
      "name": "compartment-truck",
      "capacity": [8000, 5000, 3000],
      "shifts": [{
        "from": "2024-03-15T06:00:00Z",
        "to": "2024-03-15T17:00:00Z",
        "start": {"latitude": 51.054, "longitude": 3.717},
        "end": {"latitude": 51.054, "longitude": 3.717}
      }]
    }
  ],
  "depots": [
    {
      "name": "general-waste-tip",
      "location": {"latitude": 51.095, "longitude": 3.695},
      "duration": 900,
      "capacity": [8000, 0, 0]
    },
    {
      "name": "recycling-center",
      "location": {"latitude": 51.018, "longitude": 3.661},
      "duration": 900,
      "capacity": [0, 8000, 8000]
    }
  ]
}
```

In this example:

* **general-waste-tip** only accepts dimension 0 (general waste). When a vehicle visits, only the first compartment is unloaded.
* **recycling-center** accepts dimensions 1 and 2 (recyclables). The vehicle keeps its general waste loaded.

<Info>
  A depot with `capacity: [0, 0, 0]` for a given dimension means that compartment is **not unloaded** at that depot. This enables independent compartment tipping.
</Info>

## Forcing a Depot Visit Before End of Shift

By default, the solver may finish a route by driving directly to the shift end location while the vehicle still carries load. For waste collection and similar workflows, this is rarely the desired behavior — the truck should drop its load at a depot before parking.

Set `unloadBeforeEndShift: true` on a shift to require a depot stop after the shift's last job whenever the vehicle still has non-zero load. The flag lives on the shift (not on the resource) so different shifts of the same resource can have different end-of-shift policies.

```json theme={null}
{
  "resources": [
    {
      "name": "truck-1",
      "capacity": [8000],
      "shifts": [{
        "from": "2024-03-15T06:00:00Z",
        "to": "2024-03-15T17:00:00Z",
        "start": {"latitude": 51.054, "longitude": 3.717},
        "end": {"latitude": 51.054, "longitude": 3.717},
        "unloadBeforeEndShift": true
      }]
    }
  ],
  "depots": [
    {
      "name": "transfer-station",
      "location": {"latitude": 51.086, "longitude": 3.732},
      "duration": 900,
      "capacity": [80000]
    }
  ]
}
```

The constraint is **load-aware**: if the route's last job leaves the vehicle empty (e.g., a balanced pickup-and-delivery route, or a route where every job carries `load: [0]`), no depot detour is forced. It is also gated on having depots configured — if the request contains no `depots`, the flag is dormant and produces no violation.

| Last-job state                                               | `unloadBeforeEndShift: true` behavior |
| ------------------------------------------------------------ | ------------------------------------- |
| Vehicle carries load AND a depot is assigned to the last job | Satisfied — no violation              |
| Vehicle carries load AND no depot assigned                   | `End Depot` hard violation            |
| Vehicle ends empty (all load dimensions are 0)               | No violation, depot detour not forced |
| No depots configured in the request                          | Feature dormant, no violation         |

## Constraints

The solver enforces four depot-related constraints:

| Constraint          | Type | Description                                                                                                                               |
| ------------------- | ---- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `Depot Time Window` | Hard | Depot visits must occur within the depot's operating hours                                                                                |
| `Depot Capacity`    | Hard | Total load delivered to a depot across all vehicles during the planning period must not exceed its capacity                               |
| `End Depot`         | Hard | When `unloadBeforeEndShift` is set on a shift, the last job of that shift must have a depot assigned whenever load remains on the vehicle |
| `Depot Cost`        | Soft | Per-visit cost penalizes expensive depots, weighted by `depotCostWeight`                                                                  |

These appear in the `violations` section of the response when active.

## Real-World Example: Waste Collection

A complete waste collection request with 3 waste streams, strict load compatibility, and geographically distributed depots:

```json theme={null}
{
  "resources": [
    {
      "name": "truck-1",
      "capacity": [8000, 8000, 8000],
      "loadCompatibility": [
        [8000, 0, 0],
        [0, 8000, 0],
        [0, 0, 8000]
      ],
      "tags": ["General Waste", "Recycling", "Paper"],
      "category": "TRUCK",
      "shifts": [{
        "from": "2024-03-15T06:15:00Z",
        "to": "2024-03-15T16:00:00Z",
        "start": {"latitude": 51.054, "longitude": 3.717},
        "end": {"latitude": 51.054, "longitude": 3.717},
        "breaks": [{"type": "DRIVE", "driveTime": 16200, "duration": 2700}]
      }]
    }
  ],
  "jobs": [
    {
      "name": "general-waste-pickup-1",
      "location": {"latitude": 51.082, "longitude": 3.745},
      "load": [280, 0, 0],
      "duration": 360,
      "tags": [{"name": "General Waste", "hard": true}]
    },
    {
      "name": "recycling-pickup-1",
      "location": {"latitude": 51.040, "longitude": 3.669},
      "load": [0, 350, 0],
      "duration": 360,
      "tags": [{"name": "Recycling", "hard": true}]
    }
  ],
  "depots": [
    {
      "name": "transfer-station",
      "location": {"latitude": 51.086, "longitude": 3.732},
      "duration": 900,
      "windows": [{"from": "2024-03-15T08:00:00Z", "to": "2024-03-15T17:00:00Z"}]
    }
  ]
}
```

<Tip>
  Combine depots with [load compatibility](/guides/vrp/features/load-compatibility) to enforce per-trip waste stream segregation. The solver ensures each trip collects only one waste type and visits an appropriate depot to unload.
</Tip>

## Related Features

<CardGroup cols={2}>
  <Card title="Load Compatibility" icon="shield-halved" href="/guides/vrp/features/load-compatibility">
    Restrict which load types can coexist on a vehicle per trip
  </Card>

  <Card title="Capacity Management" icon="box" href="/guides/vrp/features/capacity-management">
    Configure multi-dimensional vehicle capacity constraints
  </Card>

  <Card title="Cost Optimization" icon="coins" href="/guides/vrp/features/cost-optimization">
    Set up cost-based optimization with financial trade-offs
  </Card>

  <Card title="Break Management" icon="mug-hot" href="/guides/vrp/features/break-management">
    Configure driver breaks and rest periods
  </Card>
</CardGroup>
