A shop catalog needed one thing: "show me what is nearest and how long it takes to get there". It sounds trivial until you count how many external router calls a single drag of the distance slider produces.

Why not a routing API

The first suggestion is always the same: call an external API on every change. That works in a demo with five points and stops working with a hundred users at once. The provider throttles you, the page slows down, and the reader’s location leaves the browser on every move.

That last point matters most. Location is personal data, and sending it to an outside provider just to display "12 minutes" is a cost nobody added up.

What we compute instead

Haversine gives the straight line. Two custom curves turn it into road kilometres and minutes of driving:

  • a curve for how much longer the road is than the straight line — a short trip winds through town, a long one runs on the expressway;
  • an average speed that rises with distance, plus a fixed overhead for setting off and parking.

Both curves are calibrated on 460 real car routes, from 400 metres to 500 kilometres, computed with a real router — from real addresses and from random points across the country.

How wrong it gets

Median time error: 13.6 percent. On routes outside the training set: 13.5 percent. Half of the estimates land within six minutes of a real router.

It is weakest below five kilometres, where a river or a one-way street can double the route. Even there the miss is a minute, not an hour.

What the reader gets

The calculation happens in the browser, so the location goes nowhere. "Nearest to me" sorting and the distance slider work without a single server call. The calibration script sits in the repository, so the result can be recomputed and checked.

The address geocoder and the route router are only needed where they really are — and they have guards of their own: one request at a time, spacing between requests, a cache for repeats (including remembered misses) and a per-IP limit.