cost, minimizeCosts, and custom objectives are deliberately powerful, but only a minority of plans need them. Before reaching for this page, check whether a standard objective (minimizeDistance, minimizeWorkingDuration, minimizeResources, and so on) already expresses the trade-off you’re after — see How the optimization engine works.
The cost object
A resource’s cost object accumulates several independent contributions into a single currency figure that the minimizeCosts objective then optimizes: using (a flat cost per resource used), workedHours, km, costsByStopTag, costsByCapacity, costPerCapacityPerTravelledKm, and costPerCapacityPerTravelledHour.
These fields reformulate, in a real currency, the same underlying quantities that minimizeDistance, minimizeWorkingDuration, and minimizeResources already count in raw units (km, hours, vehicles). This isn’t a strict one-to-one equivalence — it’s a different objective, built on a monetary version of the same data, not a guaranteed substitute for the raw-unit objectives.
Piecewise-linear cost functions
Every cost field preceding this section except using accepts a CostFloorsAndCoeffs-shaped object: a constantCost base, a costCoeff rate applied past costFloor, and an optional steeper overcostCoeff rate past a second, higher overcostFloor — the same shape as a salary with a base, a free allowance, and an overtime-style rate beyond it. Modeling advanced constraints already has a worked costsByCapacity example using this object, to make capacity overflow economically unattractive rather than infeasible.
Guaranteeing a minimum per-tour revenue via costsByCapacity
Create a capacity that only tracks completed deliveries — for example deliveredUnits, incremented solely on delivery stops rather than tied to any real load — then put a costFloor/constantCost on that capacity so a tour that ends below the threshold keeps paying a flat penalty:
The figures here (200, 50, -4) are illustrative — confirm against the actual subcontractor rate before publishing a real payload. Use generic ids only (subcontractor-van-1), never a real client name, or a real contract amount.
Rebuilding the default objective list with customCost
A CustomObjective (type: "custom") lets you optimize a cost expression built from costsByResourceTag instead of a built-in ObjectivesEnum entry — for example scoping a custom fuel-cost objective to just the resources carrying a given tag:
name must not collide with a built-in ObjectivesEnum value (the schema enforces this). costsByResourceTag maps a Cost-shaped object to a resource tag, so a custom objective can apply to a subset of the fleet rather than every resource.
Modeling revenue or margin per stop
costsByStopTag with negative constantCost values represents a revenue (a negative cost) rather than a charge, combined with minimizeCosts:
If you’d rather reason entirely in positive revenue figures, use a CustomObjective with direction: "maximize" and positive costsByStopTag values instead of negating them under the built-in minimizeCosts — there is no built-in maximizeCosts objective in ObjectivesEnum, only minimizeCosts. The two approaches aren’t interchangeable without also adjusting whatever thresholds you’ve set elsewhere.
Tag a stop with its own stop.id instead of a shared category tag when the rate is unique per stop rather than per category.
See also