Blog

Isochrone geofences, routed by Stadia Maps

A ten-minute drive isn't a circle. How MapSocket turns travel time into a geofence with Valhalla, and why we use Stadia Maps' hosted engine instead of running our own.

2 min read The MapSocket team

A circle around a store is the easiest geofence to draw and usually the wrong one. “Customers within ten minutes” means ten minutes along real roads. A river with one bridge, a motorway on-ramp or a one-way grid stretches that area in some directions and cuts it short in others. The shape you want is an isochrone: everywhere reachable from a point within a travel time.

MapSocket has had isochrone geofences since the start. You give a center (or an address), a time from 1 to 60 minutes and a mode (foot, bike, car, truck or motorbike), and we save the area as an ordinary polygon geofence. From then on it fires the same enter, exit and dwell events as anything you drew by hand.

The routing engine behind it

Computing an isochrone means exploring the road graph outward from a point until the travel time runs out, then wrapping the reached area in a polygon. We use Valhalla, the open-source routing engine built on OpenStreetMap. Its /isochrone action does exactly this, and its /route action gives us travel times for trip ETAs.

We ask Valhalla for a single contour with polygons on, plus a little denoise and generalize so the result is a clean shape rather than thousands of vertices hugging every cul-de-sac. The geometry is computed once, when the geofence is saved. Tracking a user never calls the routing engine: checking a location against an isochrone costs the same as checking it against any other polygon in PostGIS.

Why hosted

Valhalla is easy to run for one city and hard to run for the planet. Routing tiles for the whole world take a lot of disk and memory to build, and they need rebuilding as OpenStreetMap changes. For a feature that’s called when a geofence is saved, not on every track request, a dedicated fleet of routing machines would be poor value.

So production uses Stadia Maps, which runs Valhalla as a hosted API. The request body is Valhalla’s own JSON, so our code doesn’t care which one it’s talking to:

VALHALLA_URL=https://api.stadiamaps.com      # or your own Valhalla
VALHALLA_API_KEY=…                            # sent as Authorization: Stadia-Auth …

When the URL points at Stadia, the API calls /isochrone/v1 and /route/v1; otherwise the plain Valhalla paths. The key goes in a header, never in the URL, so it doesn’t end up in logs. Stadia also has an EU endpoint (api-eu.stadiamaps.com) for traffic that should stay in Europe.

If you self-host MapSocket, point VALHALLA_URL at your own Valhalla and leave the key empty.

When there’s no engine

Routing is optional. Without it, creating an isochrone returns 501 routing_not_configured with a message saying to draw a circle or polygon instead, and trip ETAs fall back to a straight-line estimate at a typical speed for the mode, marked source: "estimate" so you can tell. With routing on, the same ETAs say source: "routing".

Try it

In the dashboard, open Geofences, choose Isochrone, click where travel starts and pick the minutes and mode. Or through the API:

POST /v1/geofences
{
  "type": "isochrone",
  "tag": "store",
  "externalId": "shibuya",
  "center": { "type": "Point", "coordinates": [139.7016, 35.6580] },
  "minutes": 10,
  "mode": "foot"
}

The response is the saved geofence, polygon included, so you can draw it on your own map straight away.