DEV Community

Daniel Mercer
Daniel Mercer

Posted on

Geocoding 27,854 routes without a paid API

Geocoding 27,854 routes without a paid API

When we set out to build a directory of long-distance moving routes, we faced a simple arithmetic problem. We had tens of thousands of city pairs, and every commercial geocoding API we priced would have charged us per lookup. At our scale, the bill arrived before the product did. So we built the route directory without a paid geocoding API, using public data and a lot of patience. Here is how that worked, and where it broke.

Start with what is already free

The first lesson was that we did not need to geocode everything from scratch. City coordinates are public knowledge, and several open datasets publish them: gazetteers, census place files, and open geographic databases. We started with a single canonical city list, one row per city, with a name, a state, and coordinates from a public source.

That one decision shaped everything else. A route is just two cities, so if you know both endpoints, you know the route. We did not need to look up 27,854 routes. We needed to look up a few thousand cities, once, and then join them.

Normalization is the real work

The hard part was never the coordinates. It was the names. The same city appears as "St. Louis", "Saint Louis", and "St Louis" across different sources. Some datasets use county names, others use place names, and a few use names that changed years ago.

We built a normalization pass: lowercase everything, strip punctuation, expand common abbreviations, and match against our canonical list with a strict rule. Exact matches went through automatically. Near matches went into a review queue, where a human decided. Fuzzy matching without a review queue is how a directory ends up sending movers to the wrong Springfield, and there are a lot of Springfields.

That review queue was small, a few hundred rows, but it mattered more than any other part of the pipeline. Data quality in a directory is not decided by your best rows. It is decided by your worst ones, the ones users actually notice.

Distances without a routing API

With coordinates for both endpoints, straight-line distance is easy. Driving distance is harder, and driving distance is what movers actually care about. Without a paid routing API, we estimated driving distance from straight-line distance using a road factor, calibrated against a sample of known driving routes.

We were honest about the limits of that estimate. A straight-line distance multiplied by a factor is an approximation, and approximations should be labelled as approximations. Our pages present costs as estimates, not quotes, and the calculator on My Fast Movers is explicit about that. A directory that pretends to know your exact moving cost is lying to you, whether it uses a paid API or not.

Where the free approach breaks

Free data breaks in predictable places. Small towns change names or merge. New developments appear faster than public datasets update. Coordinates for rural places are sometimes rounded to a county seat, which is fine for a state-level estimate and wrong for a precise one.

Our answer was to keep the pipeline rerunnable. Every step, from raw download to published page, runs from scripts, so when a dataset updates, we regenerate rather than patch. A directory built on one-off manual work rots. A directory built on a repeatable pipeline stays fixable.

The cost of free is maintenance

People say open data is free, and it is, in the sense that nobody sends you a bill. But it costs maintenance time, review time, and the discipline to keep your pipeline runnable. We traded a monthly API bill for ongoing care, and for a small independent site, that trade was right.

If you are building a geographic directory on a budget, start with a canonical place list, normalize ruthlessly, review the near matches by hand, and be honest about what your numbers are. You can build something genuinely useful without a paid API. You just cannot build it without caring about the data.

Top comments (0)