The landscape
The question
You need addresses turned into coordinates. Within an hour of searching you have found a hosted API you could call this afternoon, an open-source engine you could run yourself, a library you could install, and a colleague who insists the whole thing is a hundred lines of Python. Each option suits some situation. This page helps you work out which one suits yours.
The analog
Consider file storage. You can pay someone to store your files, run a file server yourself, or write them to the disk already in the machine. No one of those is right for every case. You choose based on how much data you have, how frequently you access it, who may see it, and what happens when it is unavailable. Address lookup offers the same three options, and similar questions decide between them.
Both cases also have a fourth option that people tend to overlook. For a small, bounded, well-understood set of files, a folder is enough. The geocodinggeocodingThe process of converting an address into geographic coordinates (latitude and longitude). Mailwoman geocodes in a multi-tier cascade: exact address-point match → street interpolation → locality centroid. Each tier is progressively coarser but more widely available. equivalent is the right choice in more cases than people expect, so this page covers it first.
The bounded case: when a regex and a CSV win
If your addresses come from a known, fixed set (a utility's service addresses, a retailer's store list, one citylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy.'s delivery points), you may not need geocodinggeocodingThe process of converting an address into geographic coordinates (latitude and longitude). Mailwoman geocodes in a multi-tier cascade: exact address-point match → street interpolation → locality centroid. Each tier is progressively coarser but more widely available. at all. You need matching, a much easier task.
NormalizenormalizeStage 1 of the runtime pipeline: deterministic input preprocessing (Unicode NFC, punctuation normalization, whitespace collapse). Returns a NormalizedInput with an offsetMap that maps normalized positions back to the raw input. both sides and compare them. Lowercase the text, strip punctuation, expand the standard abbreviations, and drop the tokenstokenOne word or subword in the tokenized input. For the neural classifier, tokens come from SentencePiece (subword units); for the rule classifiers, tokens are whitespace- and punctuation-separated words. your database does not store. Then take the best fuzzy match above a threshold. Against a bounded, curated set this is accurate, fast and easy to debug, and it takes an afternoon to build. The docs here do not argue against it, and a team that ships it and moves on has made a good decision.
Two other simplifications have the same property:
- PostcodepostcodeThe country-specific postcode (US ZIP, French code postal, etc.). Mailwoman handles postcode parsing entirely by rule classifier — a regex problem, not an ML one.-only. ExtractextractA partial output file of the corpus build, written in Parquet format. The training pipeline streams extracts row by row. the postcodepostcodeThe country-specific postcode (US ZIP, French code postal, etc.). Mailwoman handles postcode parsing entirely by rule classifier — a regex problem, not an ML one. with one pattern per countrycountryThe top-level address component (an ISO country). Closed-vocabulary, so it is best handled by a deterministic matcher feeding a proposal rather than a retrained model head., look it up in a postcodepostcodeThe country-specific postcode (US ZIP, French code postal, etc.). Mailwoman handles postcode parsing entirely by rule classifier — a regex problem, not an ML one.-to-coordinate table, and return the center. In countries where a postcodepostcodeThe country-specific postcode (US ZIP, French code postal, etc.). Mailwoman handles postcode parsing entirely by rule classifier — a regex problem, not an ML one. covers a handful of delivery points, the result is close to building-level. In countries where a postcodepostcodeThe country-specific postcode (US ZIP, French code postal, etc.). Mailwoman handles postcode parsing entirely by rule classifier — a regex problem, not an ML one. covers a rural route, it is not, and this approach cannot tell you which case applies.
- LocalitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy.-only. Find the town name, return its center, and ignore the rest. For counting customers by metro area or assigning sales territories, finer detail would not change the answer.
All three approaches have the same limit: they work only on addresses you already know about. For a new customer, a building finished last month, or an address in a format the abbreviation table does not cover, the normalizer returns no match and the postcodepostcodeThe country-specific postcode (US ZIP, French code postal, etc.). Mailwoman handles postcode parsing entirely by rule classifier — a regex problem, not an ML one. pattern extractsextractA partial output file of the corpus build, written in Parquet format. The training pipeline streams extracts row by row. no postcodepostcodeThe country-specific postcode (US ZIP, French code postal, etc.). Mailwoman handles postcode parsing entirely by rule classifier — a regex problem, not an ML one.. There is no partial match to escalate on. The approaches also do not signal which case occurred, so a failure produces no output and no error.
Pick the cheapest approach that meets your actual requirement, and stop there. A geocode accurate to five meters is wasted effort when the application needs only five kilometers.
Hosted APIs
You send a string over HTTPS and receive a result. You do not download data, build an index or keep a gazetteergazetteerA geographical index that maps place names and postcodes to real-world coordinates. Mailwoman uses a custom-built Who's On First (WOF) SQLite database as its gazetteer — the 'atlas' half of the grammar/atlas architecture. current, and you get global coveragecoverageThe fraction of a population or region for which a data source has real, non-placeholder entries — e.g. 47% rooftop coverage on Texas addresses. Distinct from accuracy on the rows that are present. on the first day.
What it is for: prototypes, one-time batchesbatch sizeHow many examples the model processes before each parameter update. Larger batches give smoother gradients but cost more memory; gradient accumulation simulates a big batch on a small GPU., small volumes, and any team that lacks the capacity to source and maintain reference data for the countries it serves. That last point matters, because keeping a national address dataset current is ongoing work that continues after setup.
What you are trading. The result arrives as a set of components in the provider's own vocabularyvocabularyThe fixed set of tokens a tokenizer can produce. Mailwoman's SentencePiece vocabulary is tens of thousands of subword pieces, with byte fallback for anything outside it.. You must translate it into your schema, and the translation loses anything your schema has no field for. You cannot inspect the provider's reasoning. When one address keeps resolving wrongly, there is no stagestageOne of the dataflow stages in the runtime pipeline (normalize, locale check, kind classify, phrase group, token classify, sequence correct, reconcile, resolve). Distinct from tier (model vocabulary) and phase (plan milestone). to examine and no local override to add, so you must correct it downstream in your code. Terms vary on what you may store and for how long. Those terms decide whether geocodinggeocodingThe process of converting an address into geographic coordinates (latitude and longitude). Mailwoman geocodes in a multi-tier cascade: exact address-point match → street interpolation → locality centroid. Each tier is progressively coarser but more widely available. a stable set of addresses is a one-time cost or a recurring one. Every query also leaves your infrastructure. Your compliance team must review that transfer if any of those addresses fall under data-protection rules.
This section makes no claims about any provider's pricing or accuracy. Both change, both depend on your query mix, and the provider's own pages are the right source for both.
Self-hosted engines
You run the geocoder. The data is yours, the queries never leave your network, and you pay for infrastructure instead of per request.
Most well-known open engines use the search-engine-with-a-map architecture: an index over every place, queried as text. That design is strong at fuzzy recallrecallOf the spans whose gold label is a given tag, the fraction the model found. High recall means few misses. Paired with precision to compute F1. over a very large corpuscorpusThe BIO-labeled training data used to train Mailwoman's neural classifier. Assembled from real sources (OpenAddresses, National Address Database) and synthetic extracts (boundary stress, order variants, negative space). Managed by @mailwoman/corpus. and is the right choice for exploratory search. It also needs the index in memory. That requirement explains the published memory recommendations. The two architectures gives those figures with dated citations and explains the reasoning behind them.
What it is for: volume high enough that per-request pricing matters, data-residency requirements, a need to inspect or modify the reference data, and search-box workloads.
What you are trading: a permanent operations burden. You handle index builds, data refreshes, version upgrades, and enough memory to keep the index loaded. For a team with a platform group this is routine. For a team without one, it is a second product to run.
In-process libraries
The geocoder is a dependency. You call a function, it returns a result, and no socket opens.
What it is for: geocodinggeocodingThe process of converting an address into geographic coordinates (latitude and longitude). Mailwoman geocodes in a multi-tier cascade: exact address-point match → street interpolation → locality centroid. Each tier is progressively coarser but more widely available. as one step inside a larger job, such as a batchbatch sizeHow many examples the model processes before each parameter update. Larger batches give smoother gradients but cost more memory; gradient accumulation simulates a big batch on a small GPU. job, an import pipelinestaged pipelineMailwoman's runtime architecture: a sequence of pure-function stages (normalize → query-shape → locale-hint → kind-classifier → phrase-grouper → classifier → decoder) connected by typed handoffs. Each stage is published as its own npm package. or a form validation pass, where a network round trip adds only overhead. It also suits cases where the addresses must not leave the process.
What you are trading: you store the data. The reference files sit on your disk, and you decide when to refresh them, so keeping them current is your responsibility instead of a vendor's. A library also gives you a function instead of a service. If you want an HTTP endpoint, you deploy one.
Where Mailwoman sits
Mailwoman is an in-process library, and you can run it as a self-hosted engine. The parser is an npm install plus a modelneural classifierThe machine learning model at the core of Mailwoman's parser — a transformer encoder (~30M parameters) trained from scratch to do BIO token classification over addresses. It learns the 'grammar' of address formats; the gazetteer supplies the 'atlas.' file, and geocodinggeocodingThe process of converting an address into geographic coordinates (latitude and longitude). Mailwoman geocodes in a multi-tier cascade: exact address-point match → street interpolation → locality centroid. Each tier is progressively coarser but more widely available. adds a gazetteergazetteerA geographical index that maps place names and postcodes to real-world coordinates. Mailwoman uses a custom-built Who's On First (WOF) SQLite database as its gazetteer — the 'atlas' half of the grammar/atlas architecture. that you download once and keep. If you want an endpoint, the API server and the Nominatim-, Photon- and libpostallibpostalAn open-source C address parser used by Pelias. Mailwoman's rule-based v0 and neural classifier supersede it.-compatible drop-ins are servers you run on your own hardware against your own data. What Mailwoman is describes the scope of the project, including what it does not do.
Mailwoman does not fit these cases:
- You need only citylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy.-level or postcodepostcodeThe country-specific postcode (US ZIP, French code postal, etc.). Mailwoman handles postcode parsing entirely by rule classifier — a regex problem, not an ML one.-level answers. The simplifications at the top of this page are cheaper and simpler, and they are equally accurate at that level.
- Your queries are exploratory instead of postal. Landmarks, partial strings, and descriptions like "the place near the bridge" suit the search architecture better.
- You need a countrycountryThe top-level address component (an ISO country). Closed-vocabulary, so it is best handled by a deterministic matcher feeding a proposal rather than a retrained model head. outside the measured tiers. Mailwoman claims coveragecoverageThe fraction of a population or region for which a data source has real, non-placeholder entries — e.g. 47% rooftop coverage on Texas addresses. Distinct from accuracy on the rows that are present. per localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for., and only where a coordinate-graded evaluationevalRunning the model against a held-out golden dataset and computing per-component F1, exact-match, calibration, and resolved-coordinate error. exists. What ships today lists those localeslocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for.. Outside them, the output is unverified. Unverified output is worse than merely less accurate output.
The first decision
Decide your requirements before you pick a tool. Write down your tolerance in meters, and determine whether your set of addresses is bounded or open. Those two facts rule out most of the options on this page. The remaining questions are about operations, and they are easier to answer once the requirement is a number instead of "as accurate as possible".
Related
- The two architectures — the design split underneath the self-hosted engines.
- How close is close enough? — how to arrive at that tolerance number.
- What Mailwoman is — the boundary of this project's claim.
- What ships today — per-localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. coveragecoverageThe fraction of a population or region for which a data source has real, non-placeholder entries — e.g. 47% rooftop coverage on Texas addresses. Distinct from accuracy on the rows that are present. and the gaps.
- Match messy records — the bounded-universe case, done against a real matcher.