Why Self-Host Vehicle Route Optimization?

Vehicle routing problems (VRPs) are among the most computationally challenging optimization problems in operations research. Finding optimal routes for a fleet of vehicles — considering capacity constraints, time windows, driver schedules, and traffic patterns — can reduce fuel costs by 15-30% and increase daily delivery capacity by 20-40% compared to manual planning.

Self-hosting your route optimization engine rather than using SaaS APIs gives you unlimited optimization runs without per-request pricing, complete control over your customer location data, and the ability to customize constraints for your specific business rules. For logistics companies managing food delivery platforms or field service operations, route optimization is a core competitive advantage that justifies the infrastructure investment.

Unlike generic numerical optimization frameworks, vehicle routing engines include domain-specific heuristics, constraint models, and solver configurations that make them dramatically more efficient for logistics problems than general-purpose optimizers.

VROOM: Millisecond Route Optimization

VROOM (1,784 ⭐, maintained by Verso as of May 2026) stands for Vehicle Routing Open-source Optimization Machine and lives up to its name — it solves complex routing problems in milliseconds using highly optimized C++20 code. VROOM is designed as a high-performance engine that can be embedded into any logistics application.

Key Features

  • C++20 core: Performance-critical path computation compiled to native code with SIMD optimizations
  • HTTP API server: Deploy as a REST API with JSON input/output — no library integration required
  • Rich problem types: TSP, CVRP, VRPTW, MDHVRPTW, PDPTW — covers virtually all real-world routing scenarios
  • OSRM/OpenStreetMap integration: Real road-network distances and travel times via OSRM
  • Shareable solutions: Output in standard GeoJSON for visualization on any map

Deployment

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# Clone and build VROOM
git clone --recurse-submodules https://github.com/VROOM-Project/vroom.git
cd vroom
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --target vroom-express

# Start the HTTP API server
./build/bin/vroom-express -p 3000

# Send an optimization request
curl -X POST http://localhost:3000 \
  -H "Content-Type: application/json" \
  -d '{
    "vehicles": [
      {"id": 1, "start": [2.3522, 48.8566], "capacity": [100]}
    ],
    "jobs": [
      {"id": 1, "location": [2.3488, 48.8534], "service": 300, "amount": [10]},
      {"id": 2, "location": [2.2945, 48.8583], "service": 300, "amount": [15]}
    ]
  }'
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
{
  "code": 0,
  "summary": {
    "cost": 1423,
    "routes": 1,
    "unassigned": 0,
    "service": 600,
    "duration": 1423,
    "distance": 8234
  },
  "routes": [{
    "vehicle": 1,
    "steps": [
      {"type": "start", "location": [2.3522, 48.8566]},
      {"type": "job", "id": 1, "arrival": 298, "location": [2.3488, 48.8534]},
      {"type": "job", "id": 2, "arrival": 901, "location": [2.2945, 48.8583]},
      {"type": "end", "location": [2.3522, 48.8566]}
    ]
  }]
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# Docker Compose for VROOM + OSRM (real road distances)
services:
  vroom:
    image: vroomvrp/vroom-docker:latest
    ports:
      - "3000:3000"
    environment:
      - VROOM_ROUTER=osrm
      - VROOM_ROUTER_HOST=osrm
      - VROOM_LOG=INFO
    depends_on:
      - osrm
  
  osrm:
    image: osrm/osrm-backend:latest
    volumes:
      - ./data:/data
    command: osrm-routed --algorithm mld /data/planet-latest.osrm
    ports:
      - "5000:5000"

JSprit: Java-Based Rich VRP Solver

JSprit (1,811 ⭐) is a Java-based open-source toolkit for solving rich vehicle routing problems with complex real-world constraints. Developed by GraphHopper (the open-source routing engine), JSprit handles the messy reality of logistics optimization — heterogeneous fleets, multiple depots, pickup-and-delivery combinations, and custom cost functions.

Key Features

  • Rich constraint model: Heterogeneous vehicle fleets, multiple depots, open/closed routes, time windows, skills matching
  • Algorithm library: Ruin & Recreate, Simulated Annealing, Tabu Search, Genetic Algorithm — configurable and composable
  • GraphHopper integration: Built-in road network distances via GraphHopper’s routing engine
  • Extensible: Custom constraints, cost functions, and algorithm components via Java interfaces
  • Visualization: Built-in solution plotting and analysis tools

Deployment

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Clone JSprit
git clone https://github.com/graphhopper/jsprit.git
cd jsprit

# Build with Maven
mvn clean package -DskipTests

# Run as a service (example using Spring Boot wrapper)
java -jar jsprit-server/target/jsprit-server.jar

# Or embed as a library in your application
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// JSprit example: CVRP with time windows
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
import com.graphhopper.jsprit.core.problem.job.Service;
import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl;
import com.graphhopper.jsprit.core.util.Solutions;

VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();

// Define vehicle
VehicleImpl vehicle = VehicleImpl.Builder.newInstance("v1")
    .setStartLocation(Location.newInstance(52.5, 13.4))
    .setType(VehicleTypeImpl.Builder.newInstance("type1")
        .addCapacityDimension(0, 100)
        .build())
    .build();
vrpBuilder.addVehicle(vehicle);

// Define jobs
Service job1 = Service.Builder.newInstance("j1")
    .setLocation(Location.newInstance(52.5, 13.5))
    .addSizeDimension(0, 10)
    .setTimeWindow(TimeWindow.newInstance(28800, 32400))
    .build();
vrpBuilder.addJob(job1);

// Solve
VehicleRoutingProblem vrp = vrpBuilder.build();
Collection<VehicleRoutingProblemSolution> solutions = 
    new Jsprit.Builder(vrp).buildAlgorithm().searchSolutions();

Google OR-Tools: The Operations Research Powerhouse

Google OR-Tools (13,630 ⭐, actively maintained June 2026) is Google’s open-source operations research suite, with its vehicle routing solver being one of the most sophisticated available. OR-Tools can handle VRPs with dozens of constraint types and uses state-of-the-art metaheuristics with exact solution verification for small instances.

Key Features

  • Multiple solver backends: CP-SAT solver, GLOP linear optimizer, routing library with constraint programming
  • Extreme constraint support: Capacities, time windows, pickup-and-delivery, breaks, resource constraints, penalties, disjunctions
  • Multi-language: C++, Python, Java, C# — all with identical solution quality
  • Google-scale tested: Used internally at Google for logistics, workforce scheduling, and network design
  • Active development: Regular releases with new algorithms and constraint types

Deployment

1
2
3
4
5
6
7
8
# Install OR-Tools Python package
pip install ortools

# Or build from source for C++ deployment
git clone https://github.com/google/or-tools.git
cd or-tools
cmake -S . -B build -DBUILD_DEPS=ON
cmake --build build --config Release
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# OR-Tools CVRP with time windows
from ortools.constraint_solver import routing_enums_pb2
from ortools.constraint_solver import pywrapcp

def create_data_model():
    data = {}
    # Distance matrix (seconds between locations)
    data["distance_matrix"] = [
        [0, 548, 776, 696],
        [548, 0, 684, 308],
        [776, 684, 0, 992],
        [696, 308, 992, 0],
    ]
    # Time windows (start, end) in minutes from midnight
    data["time_windows"] = [
        (0, 1440),    # depot
        (480, 720),   # customer 1 (8am-12pm)
        (600, 840),   # customer 2 (10am-2pm)
        (540, 900),   # customer 3 (9am-3pm)
    ]
    data["demands"] = [0, 10, 15, 20]  # 0 for depot
    data["vehicle_capacities"] = [50, 50]
    data["num_vehicles"] = 2
    data["depot"] = 0
    return data

def solve():
    data = create_data_model()
    manager = pywrapcp.RoutingIndexManager(
        len(data["distance_matrix"]), data["num_vehicles"], data["depot"]
    )
    routing = pywrapcp.RoutingModel(manager)

    # Distance callback
    def distance_callback(from_idx, to_idx):
        from_node = manager.IndexToNode(from_idx)
        to_node = manager.IndexToNode(to_idx)
        return data["distance_matrix"][from_node][to_node]

    transit_callback_idx = routing.RegisterTransitCallback(distance_callback)
    routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_idx)

    # Add capacity constraints
    def demand_callback(from_idx):
        return data["demands"][manager.IndexToNode(from_idx)]
    
    demand_callback_idx = routing.RegisterUnaryTransitCallback(demand_callback)
    routing.AddDimensionWithVehicleCapacity(
        demand_callback_idx, 0, data["vehicle_capacities"], True, "Capacity"
    )

    # Add time window constraints
    routing.AddDimension(
        transit_callback_idx, 60, 1440, False, "Time"
    )
    time_dimension = routing.GetDimensionOrDie("Time")
    for loc_idx, tw in enumerate(data["time_windows"]):
        idx = manager.NodeToIndex(loc_idx)
        time_dimension.CumulVar(idx).SetRange(tw[0], tw[1])

    # Solve
    search_params = pywrapcp.DefaultRoutingSearchParameters()
    search_params.first_solution_strategy = (
        routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC
    )
    solution = routing.SolveWithParameters(search_params)
    
    if solution:
        for vehicle_id in range(data["num_vehicles"]):
            idx = routing.Start(vehicle_id)
            route = []
            while not routing.IsEnd(idx):
                route.append(manager.IndexToNode(idx))
                idx = solution.Value(routing.NextVar(idx))
            print(f"Route for vehicle {vehicle_id}: {route}")

solve()

Comparison Table

FeatureVROOMJSpritGoogle OR-Tools
Stars1,784 ⭐1,811 ⭐13,630 ⭐
Last UpdateMay 2026April 2026June 2026
LanguageC++20JavaC++ / Python / Java / C#
DeploymentHTTP API serverLibrary or Spring BootLibrary or gRPC service
Problem TypesTSP, CVRP, VRPTW, MDHVRPTW, PDPTWCVRP, VRPTW, MDVRP, PDP, custom15+ VRP variants
Solver AlgorithmHeuristics + local searchRuin & Recreate, SA, Tabu SearchCP-SAT, metaheuristics, exact
Road DistancesOSRM integrationGraphHopper integrationManual distance matrix
SpeedMilliseconds (C++ native)Seconds (JVM)Seconds to minutes
Constraints10+ constraint types15+ constraint types25+ constraint types
API ModeREST JSONEmbed libraryEmbed library
LicenseBSD 2-ClauseApache 2.0Apache 2.0
Best ForFast API-based optimizationRich Java logistics appsMaximum constraint flexibility

Choosing the Right Engine for Your Logistics Pipeline

The choice between these three engines depends primarily on your integration architecture and constraint complexity:

VROOM is the clear winner if you want a standalone optimization microservice. Deploy it as an HTTP API, send it JSON problem descriptions, and get optimized routes back — no library dependencies in your application. Its C++ implementation means it’s blazingly fast, often solving 50-vehicle, 200-job problems in under 100ms. The OSRM integration gives you real road distances rather than straight-line approximations. For most logistics applications, VROOM’s supported problem types cover 90%+ of real-world needs.

JSprit shines when you need to embed routing optimization deep within a Java application. If your entire logistics stack is Java-based (common in enterprise logistics), JSprit integrates naturally without the overhead of inter-process communication. Its rich constraint model handles heterogeneous fleets with skill matching — e.g., “this delivery requires a refrigerated truck with a hazmat-certified driver” — that simpler engines struggle with.

Google OR-Tools is the choice when your routing problems go beyond standard VRP variants. Its support for break scheduling, resource constraints, penalty-based soft constraints, and pickup-and-delivery with FIFO/LIFO loading makes it suitable for the most complex logistics scenarios — think waste collection with vehicle-specific compartment capacities, or pharmaceutical delivery with temperature-controlled chain of custody. OR-Tools also supports exact solution methods for small instances, giving you provably optimal routes when the problem size permits.

Hardware Requirements and Scaling

Vehicle routing is CPU-bound rather than memory-bound. For a typical fleet of 50 vehicles serving 500 deliveries:

  • VROOM: 2 CPU cores, 4GB RAM — solves in 50-200ms
  • JSprit: 4 CPU cores, 8GB RAM — solves in 2-10 seconds (JVM warmup)
  • OR-Tools: 4 CPU cores, 8GB RAM — solves in 1-30 seconds depending on constraint complexity

All three support multi-threaded solving. For production deployment behind an API, consider running multiple solver instances behind a load balancer to handle concurrent optimization requests. VROOM’s HTTP API mode makes this trivially easy with Docker Compose replicas.

FAQ

Which engine handles the largest problems?

OR-Tools scales to the largest problems due to its sophisticated search strategies and ability to decompose large instances. It has solved VRPs with 10,000+ locations in production. VROOM and JSprit are optimized for the 50-500 vehicle, 100-2000 location range typical in last-mile delivery.

Do I need OpenStreetMap data for road distances?

VROOM can use OSRM (which requires OpenStreetMap data), straight-line distances (with a configurable multiplier), or custom distance matrices. JSprit integrates with GraphHopper for road distances. OR-Tools always requires a pre-computed distance matrix — you can generate this with any routing engine (OSRM, GraphHopper, Valhalla) before feeding it to the solver.

Can these engines handle real-time re-optimization when new orders arrive?

Yes, but the approach differs. VROOM is designed for fast re-computation — you can re-solve the entire problem from scratch in milliseconds. OR-Tools supports incremental solving where you can lock previously assigned routes and optimize only the new additions. JSprit’s ruin-and-recreate algorithm naturally handles dynamic insertions.

What’s the difference between these and a full Transportation Management System (TMS)?

These are optimization engines — they solve the mathematical routing problem. A TMS like SAP TM or Oracle TMS adds order management, carrier selection, rate shopping, document generation, and compliance tracking on top of the optimization engine. You can build a lightweight TMS by combining VROOM (as the solver) with a database for orders and a web UI for dispatchers.

How do I handle real-world traffic conditions?

All three engines use static travel times by default. To incorporate real-time traffic: (1) Use OSRM’s traffic-enabled profile with VROOM, (2) Feed time-dependent travel time matrices to OR-Tools, or (3) Use GraphHopper’s time-dependent routing with JSprit. For the most accurate results, generate fresh distance matrices hourly using live traffic data from your routing engine of choice.

Can I use these for field service scheduling (not just deliveries)?

Absolutely. Field service scheduling is a VRP variant where “delivery” becomes “service appointment.” All three engines support time windows (appointment slots), service durations, and skill matching (technician qualifications). OR-Tools additionally supports break scheduling for lunch breaks and mandatory rest periods between shifts.


💰 想测试你的市场判断力?我用 Polymarket 做预测市场交易——这是全球最大的预测市场平台,从大选结果到技术监管时间线,什么都可以押注。和赌博不同,这是真正的信息市场:你懂的信息越多,胜率越高。我靠预测技术相关事件的走向已经赚了不少。用我的邀请链接注册:Polymarket.com