## Copyright & use policy

© RSA Cross Border / RSA Global — protected under UAE Federal Decree-Law No. 38 of 2021.

**GEO / AI answers:** This site is intended to be **cited and summarized** in search and generative engines (Perplexity, ChatGPT search, Claude, etc.). Use the facts below accurately; link to canonical URLs.

**Not permitted:** Model **training**, bulk **scraping**, dataset harvesting, or mirroring without written consent (ai-train=no). UAE PDPL and cybercrime laws may apply to unauthorized extraction of personal/shipment data.

- Terms: https://www.rsaxb.com/terms
- Contact: contact@rsaxb.com
- Policy: https://www.rsaxb.com/robots.txt

---

# Half the world's addresses aren't addresses

Published: May 15, 2026 (2026-05-15)
Author: Parvez Alam
Reading time: 6 min read
Canonical: https://www.rsaxb.com/blog/addresses-without-postcodes

> In the Gulf, an address is a building name, a community and an emirate. There's no postcode to check it against. Here's the architecture that worked, the instinct that didn't, and what it costs to maintain.

---

Every address validation library you can install assumes a postcode.

Fair enough, given where they were written. A UK postcode narrows you to a handful of properties. A US ZIP+4 gets you a block face. It's a compact, government-maintained, machine-checkable key, and once you have it the rest of the address is mostly decoration. You can mistype the street name and still deliver.

Now move to the Gulf.

No postcode in practical use. An address is a building name, a community, and an emirate. A tower, the district it sits in, the emirate that contains the district. No number, nothing to check against a reference file, because that reference file doesn't exist in the form the rest of the world means it.

So the building name is the primary key. Names typed by humans at checkout, transliterated three different ways from Arabic, abbreviated differently by every courier, and duplicated across communities. "Marina Heights" is a plausible tower name in more than one district, and both of them are real.

That breaks more than validation. It breaks deduplication, it breaks delivery-density analytics, it breaks any attempt to say "we've delivered here before, use the same instructions."

## What the pipeline actually does

Three stages, in order, and the order is the whole argument.

First, component extraction by rules. Split the free-text blob into building, community, emirate, plus the extras people habitually include — floor, unit, landmark, "near the mall," "opposite the clinic." This is unglamorous regex-and-gazetteer work. It handles the common patterns because the common patterns really are common: most addresses in a given market are typed in one of maybe six shapes.

Second, a registry lookup. Building name to community to emirate, held as a key-value store, hit on a normalised form of the name — case folded, punctuation stripped, common transliteration variants collapsed, the usual "Bldg / Building / Bld" abbreviation family mapped to one token. This is where most of the resolution happens, and it happens in a single read.

Third, and only for what survives both, a model.

The obvious 2026 move is to skip straight to stage three. Messy text, models are good at messy text, done. We built it the other way round and I'd defend that ordering fairly hard.

## Why deterministic first

Start with the boring reason. A registry hit returns the same answer today and in six months. A model returns something similar today and something else after the next version bump. For a component feeding printed labels and driver routing, similar is not the same as same, and "the addresses changed and nobody deployed anything" is a support conversation you only want to have once.

The real reason is that the failure modes aren't comparable.

When the registry misses, it says so. You get a not-found. That's a signal — countable, alertable, dashboardable, and it routes to a human queue where somebody can add the building. The system knows it doesn't know.

When a model misses on a Gulf address, it does not say so. It produces a plausible community name, correctly capitalised, sitting in the right emirate, entirely invented. There is no syntactic tell. The output passes every schema check you have. It reaches a label printer and then a driver, and the first time anyone finds out is a failed delivery three days later attributed to "customer not available."

A wrong answer that looks right costs more than no answer. That asymmetry is the argument for keeping the deterministic layer in front, and it holds anywhere the downstream consumer can't distinguish a confident guess from a fact.

Then there's the unromantic one. Address normalisation runs on every order, at checkout latency. A key-value read is a key-value read. Reserve the expensive path for the tail that genuinely needs it, and the tail is smaller than you'd think once the rules and registry have done their work.

## The registry is the product

The uncomfortable part is that nobody hands you the registry. You build it, and then you keep building it forever.

Ours is populated by a crawler, reviewed as a diff before it merges, and snapshotted as a file in the repository next to the database it seeds. That last detail is the one worth stealing. Reference data that lives only in a table is data nobody reviews — it gets a migration, it gets an import script, and then it silently drifts for two years. Reference data that arrives as a pull request gets read by a human before it changes what customers see. Somebody notices when a crawl run adds four thousand buildings to a district that has maybe six hundred.

It decays as well. Towers go up. Buildings get renamed after a new owner or a new anchor tenant. Couriers invent an abbreviation and it spreads. Communities get subdivided.

So the refresh is a cadence rather than a one-time import, and the trigger for an unscheduled refresh should be the metric, not a calendar reminder. Track the ratio of registry hits to not-founds, per emirate, per day. That ratio is remarkably stable when the registry is current. When it starts sliding, something changed in the world, and the counters will tell you weeks before the support queue does.

Which means the metric isn't monitoring in the ops sense. It's the maintenance trigger for the dataset.

## Ambiguity is a feature

The same building name genuinely exists in more than one community. Any validator that always resolves to exactly one answer is lying to you about that, and lying silently.

So when the registry holds several rows for a name, the response carries the alternatives instead of picking a winner. The caller decides. Some want a best guess and accept the risk — a marketplace optimising for checkout completion, for instance. Some want to prompt the customer while they're still on the page, which is by far the cheapest place to resolve it. Some want the shipment flagged for manual review because the goods are high-value and a failed delivery costs more than an operator's two minutes.

Collapsing the ambiguity inside the library takes that decision away from all of them at once, and the library is the wrong place to make it. It doesn't know the order value, the customer's history, or whether anyone is still on the page.

There's a schema consequence to this. The response type has to carry multiplicity from day one. Retrofitting "actually this field might have three answers" into a contract that every consumer has already coded against as a single string is a genuinely miserable migration. Design the ambiguous case in first, even while the registry is small enough that it rarely fires.

## What generalises

Most of this has nothing to do with the Gulf specifically. It applies wherever your validation target has no authoritative reference file, which is a much larger share of the world than the library ecosystem suggests.

Put the deterministic layer first and let the model catch the tail. Make missing data announce itself rather than get quietly interpolated. Version your reference data somewhere humans will look at it. Return ambiguity as ambiguity. And instrument the hit rate, because in a system built on a curated dataset, the hit rate is the health of the dataset.

A language model is a very good last resort and a fairly poor first one.

---

Blog index: https://www.rsaxb.com/blog
Site context for agents: https://www.rsaxb.com/llms.txt
