Building address software for places without addresses
Most mapping tools assume a street number and name; much of the world has neither, so a usable address is something you assemble, not something the API hands you.
I dropped a pin on a real building, asked the reverse geocoder where it was, and it told me, with total confidence, “Unnamed Road.” That was the address. For a place where a driver, a customer, and an invoice all needed to agree on a location, the best the API could offer was a polite shrug.
The problem isn’t the geocoder. The problem is the assumption baked into nearly every mapping tool: that a location is a street number plus a street name. That’s a fine model for the cities those tools were built in. For a large share of the world, including most of where I work, there is no street number, often no street name, and the building you actually want has been standing for thirty years with no entry in any database. Hand that reality to a tool that expects “12 Oak Street” and you get “Unnamed Road,” over and over.
Stop trusting any single result
The first instinct is to call the geocoder, take result number one, and render it. That’s where the trouble starts. A single reverse-geocode response is a ranked list, and the top entry is whatever the API scored highest, which in addressed cities is the street and in unaddressed ones is frequently the most useless string in the set.
So I stopped treating the response as an answer and started treating it as raw material. The shift is small to describe and large in practice: don’t read a result, mine the whole list.
- Pool components across every result. A landmark might appear in result three, the neighborhood in result one, the town in result five. None of them alone is the address. Together they are.
- Throw out the noise first. “Unnamed Road,” “Unnamed Road, Unnamed Road,” and every variant of the empty result get filtered out before anything else runs. If I never show that string, I never have to apologize for it.
Assemble the address you wish the API had given you
Once you have a pile of de-noised components, you build the thing yourself. I settled on a two-line shape because that’s what a human reading it actually needs: what is this, and roughly where.
The first line is the most specific real thing I can find: a named landmark, a building people recognize. Not the road, the place. A petrol station, a school, a market everyone in the area uses to give directions anyway. That is how people there already navigate, so the software should speak the same language instead of insisting on a road name nobody uses.
The second line is a breadcrumb for context: neighborhood, then town. Enough to orient someone who doesn’t know the landmark, and no more. And I drop the country entirely. Nobody dispatching a delivery across one city needs “Kenya” stapled to the end of every address; it’s pure noise that pushes the useful part off a small screen.
A usable address in these markets isn’t a field you fetch. It’s a result you compose from the most specific true thing the map knows, plus just enough context to find it.
The honesty of “good enough to find it”
The hard mental shift was giving up on the idea of one canonical, official address. There often isn’t one. What there is, is a description specific enough that a driver can get there and a customer can confirm it’s right. That’s the bar. Not postal-grade, not unique forever, just findable today.
This reframes the whole feature. I’m not querying an address; I’m manufacturing the most useful possible description from incomplete data, and I own every fallback when the data is thin. Landmark missing, fall back to the neighborhood; neighborhood missing, fall back to the town. The chain degrades gracefully instead of collapsing into “Unnamed Road.”
Build for the map you have, not the map the tooling assumes. In the places I build for, the address was never sitting in the API waiting to be read. It was a thing I had to assemble, one honest component at a time, and the moment I accepted that, the feature finally started telling the truth.