Twenty Minutes Per Stop Is a Fiction Everyone Agrees To

Ask a planner how long a delivery takes and you will get a number. Twenty minutes. It is a good number. It is also, at almost every individual stop, wrong.

The articulated truck with a tail lift takes longer than the van. The first stop of the day takes no time at all, because the vehicle was loaded overnight and nothing has to be moved. The last stop takes fifteen minutes more than the rest, because that is where the paperwork gets done. A driver who has run this round for six years is faster than one in their second week.

Every planner knows this. What they have not had is a way to tell the optimiser, so they pick a compromise. Use the worst case and the plan wastes capacity all day — fewer stops per route than the fleet can actually do. Use the average and the plan drifts, arriving late at the back end where the buffer has run out. Neither is a modelling problem. It is a missing input.

Durations that know their circumstances

The Route Optimization OptiFlow API now takes conditional rules that adjust a duration according to context. They live in a rules object next to the vehicles and orders, in three lists — tasks, timeSlots and locations.

Every rule has the same two halves. A conditions list says when it applies, and a duration modifier says what it does. The modifier is the same small object throughout: factor, a multiplier defaulting to 1, and extra, a number of seconds defaulting to 0. Either or both may be set, so “half as long” is a factor of 0.5, “ten minutes more” is an extra of 600, and “20% longer plus five minutes” is a factor of 1.2 with an extra of 300.

Where that modifier sits differs by rule type. Task rules carry it as duration, because the thing being adjusted is the work itself. Time-slot and location rules carry it as preparationDuration, because what they adjust is the setup before the work starts.

Three lists, then, and each answers a different question.

Task rules adjust how long the work at a stop takes. Conditions available are taskCategory, vehicleCategory and appointmentPosition, the last taking one of three values — FIRST_OF_ROUTE, LAST_OF_ROUTE or ANY, which is the default. That position condition is what makes preloading modellable: the first depot stop of the route needs zero loading time, because loading already happened. It also handles the mirror case, where the last stop of the day carries end-of-route admin that no other stop does. Combine it with vehicle category and the fleet difference falls out naturally: large trucks need 50% more unloading time than vans at every customer, expressed once rather than duplicated per order.

Time slot rules adjust appointment preparation. Conditions are timeSlotCategory, vehicleCategory and the same appointmentPosition. Docking at a booked depot slot takes ten extra minutes for an articulated vehicle, because reversing onto the dock is a different job from pulling a van up to a door. The booking system already knows the slot type; now the plan can respond to it.

Location rules adjust preparation time at a location, and they are the only ones that look backwards. Conditions are locationCategory, previousLocationCategory and vehicleCategory. That means the cost of arriving somewhere can depend on where the vehicle came from — a secure site entered from a public road needs a check that the same site entered from an adjoining yard does not.

How conditions and rules combine

Two layers of logic are worth separating, because they behave differently.

Inside a rule, the conditions list is an OR and each condition object is an AND. A rule fires when any of its conditions is met, and a condition is met when all the properties in it match. So one condition naming a vehicle category and a first-of-route position fires only where both hold, while two separate conditions in the same rule mean “either of these situations”. A rule can hold up to ten conditions, which is usually enough to express one operational idea without splitting it across rules. Every category property in a condition supports the same “!" negation used elsewhere in the API, so a rule can target everything except a category as easily as the category itself.

Because rules are conditional by nature, a rule whose conditions match nothing in a given day’s data simply does not fire. Nothing is rejected and nothing is flagged — which is convenient when a category is legitimately absent, and quietly unhelpful when the reason it is absent is a typo in a category name. If a rule appears to have no effect, compare the spelling in the condition against the categories actually present on your tasks, time slots and locations before looking anywhere else.

Across rules, the arithmetic is defined rather than first-match. Each rule’s factor is applied to the base duration before any extras are added; where several rules apply, their factors multiply and their extras sum. A vehicle-category rule and a route-position rule both hitting the same task produce both effects together, in that order.

This composes well in practice, because it lets you model each dimension independently. One set of rules describes what the vehicle brings to the job. Another describes what the position in the day adds. You do not have to enumerate the cross-product, which is what makes the approach maintainable as the fleet and the site list change.

It also means it is worth reading your rule set as a whole before trusting it. Two generous factors and an extra can stack into a service time no-one intended. Rules are precise, and precision cuts both ways.

What this recovers

The gain here is capacity, and it comes from removing padding rather than adding speed. A route planned on worst-case service times carries a buffer at every stop. Give the optimiser the real numbers and that buffer is only where it belongs — at the stops that genuinely need it — and the reclaimed hours turn into stops the fleet was always capable of serving.

The second gain is credibility. A plan built on real durations arrives when it says it will. Time windows hold. Customers get an arrival estimate that survives the afternoon. Dispatchers stop treating the plan as a first draft.

For teams building on PTV Developer, the rules also close a gap between two systems that usually know different things. The fleet management system knows which vehicle types need longer. The workforce system knows who is experienced. The site database knows which locations are awkward. Previously that knowledge stayed in those systems and got averaged away before it reached the optimiser. Now it can be passed through as conditions and applied where the plan is made.

The pressure behind it

Service promises have got tighter while stop density has got higher. Same-day and narrow-window delivery is routine, fleets are increasingly mixed as electric and alternative-fuel vehicles come in alongside diesel, and the differences between vehicle types at the kerb are widening rather than narrowing. A single service time per stop was a workable simplification when fleets were uniform and windows were half-days. Neither is true now.

The stop that takes twenty minutes still takes twenty minutes. The point is that the optimiser can finally know which stop that is.

Learn more

Try it and contact us

By Stephan Ruppert

Principal Product Manager for Developer Components at PTV Logistics.