The landscape
The question
You need addresses turned into coordinates. Within an hour of looking you have found a hosted API you could be calling this afternoon, an open-source engine you could run yourself, a library you could install, and a colleague insisting the whole thing is a hundred lines of Python. All four are true statements about somebody's situation. Which one is a true statement about yours?
The analog
Compare it to storing files. You can pay someone to store them, run a file server yourself, or write them to the disk already in the machine. Nobody thinks one of those is the right answer to every question — you pick by how much you have, how frequently you touch it, who is allowed to see it, and what happens when it is unavailable. 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. splits the same three ways and the deciding questions rhyme.
There is a fourth option in both cases, and it is the one people skip past out of embarrassment: for a small, bounded, well-understood set of files, a folder is fine. The equivalent here wins more of the time than the field admits, so it goes first.
The bounded case: when a regex and a CSV win
If your addresses live in a known universe — 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 have a 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. problem at all. You have a matching problem, and it is much easier.
The approach is to 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. Lowercase, strip punctuation, expand the standard abbreviations, 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 carry, then take the best fuzzy match above a threshold. Against a bounded, curated universe this is accurate, fast, trivially debuggable, and takes an afternoon. Nothing in this shelf argues against it, and a team that ships it and moves on has made a good decision.
The same is true of two other reductions:
- PostcodepostcodeThe country-specific postal code (US ZIP, French code postal, etc.). Mailwoman handles postcode parsing entirely by rule classifier — a regex problem, not an ML one.-only. Pull the postcodepostcodeThe country-specific postal code (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 postal code (US ZIP, French code postal, etc.). Mailwoman handles postcode parsing entirely by rule classifier — a regex problem, not an ML one.-to-coordinate table, return the center. In countries where a postcodepostcodeThe country-specific postal code (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 this is nearly building-grain. In countries where it covers a rural route it is not, and the approach has no way to tell you which case you are in.
- 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, ignore the rest. For counting customers by metro area or assigning sales territories, the finer detail was never going to change the answer.
What all three share is a boundary condition, and it is worth naming because it is where they stop: they work on the addresses you already know about. A new customer, a building finished last month, an address in a format the abbreviation table never met — the normalizer returns nothing, the postcodepostcodeThe country-specific postal code (US ZIP, French code postal, etc.). Mailwoman handles postcode parsing entirely by rule classifier — a regex problem, not an ML one. pattern extracts nothing, and there is no gradientgradientThe direction and rate at which the loss would change if each parameter were nudged. Training follows the gradient downhill to reduce error. Huge gradients are tamed by gradient clipping. between a match and no match to escalate on. They also give you no signal about which case you are in, so the failure arrives as silence.
Pick the cheapest approach that clears your actual requirement, and stop there. A geocode accurate to five meters when the application needs five kilometers is engineering you paid for and cannot use.
Hosted APIs
You send a string over HTTPS, you get a result back. No data to download, no index to build, no 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. to keep current, and 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 afternoon.
What it is for: prototypes, one-shot 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 without the capacity to source and maintain reference data for the countries it serves. That last one is not a small consideration — keeping a national address dataset current is a standing job, not a setup step.
What you are trading. The result comes as a component set 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., which you will translate into your schema, and the translation loses whatever your schema has no slot for. The reasoning is not inspectable: when one address consistently resolves wrongly, there is no stagestageOne of the dataflow stages in the runtime pipeline (normalize, locale gate, 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 the correction has to happen downstream in your code. Terms vary on what you may store and for how long, which decides 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. is a one-time cost or a recurring one for a stable set of addresses. And every query leaves your infrastructure, which is a conversation with your compliance function if any of those addresses are protected.
This shelf makes no claims about any provider's pricing or accuracy. Both change, both are specific to your query mix, and both belong on the provider's own pages rather than in someone else's documentation.
Self-hosted engines
You run the geocoder. The data is yours, the queries never leave your network, and the cost is infrastructure rather than per-request.
Most of the well-known open engines are 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 an enormous corpuscorpusThe BIO-labeled training data used to train Mailwoman's neural classifier. Assembled from real sources (OpenAddresses, National Address Database) and synthetic shards (boundary stress, order variants, negative space). Managed by @mailwoman/corpus. and is the right choice for exploratory search. It also wants the index resident, which is where the published memory recommendations come from — The two architectures carries those figures with dated citations, and the reasoning behind them.
What it is for: volume that makes per-request pricing material; data-residency requirements; a need to inspect or modify the reference data; search-box workloads.
What you are trading: an operations burden that does not go away. Index builds, data refreshes, version upgrades, and enough memory to keep the index warm. For a team with a platform function 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: the case where 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. is a step inside something else — 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-gate → kind-classifier → phrase-grouper → classifier → decoder) connected by typed handoffs. Each stage is published as its own npm package., a validation pass on a form — and the round trip is pure overhead. Also the case where the addresses may not leave the process at all.
What you are trading: you carry the data. The reference artifacts sit on your disk and you decide when to refresh them, which means their currency is now your responsibility rather than a vendor's. And a library gives you a function, not a service: if you want an HTTP endpoint, you deploy one.
Where Mailwoman sits
Mailwoman is the third shape, with the second available on top of it. The parser is an npm install and 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; 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. 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, pointed at your own data. What Mailwoman is sets out the boundary of the claim, including what it does not do.
Where it does not fit, stated plainly:
- You need citylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy.-level or postcodepostcodeThe country-specific postal code (US ZIP, French code postal, etc.). Mailwoman handles postcode parsing entirely by rule classifier — a regex problem, not an ML one.-level answers only. The reductions at the top of this page are cheaper and simpler, and they will not be less accurate at that grain.
- Your queries are exploratory rather than postal. Landmarks, partial strings, "the place near the bridge" — that is the search architecture's home ground.
- 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. 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. is claimed 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 draws that boundary, and outside it the output is unverified rather than merely thin.
The one thing worth deciding first
Not which tool. Your tolerance — in meters, written down — and whether your address universe is bounded or open. Those two facts eliminate most of this page. Everything else is a question about operations, and operations questions 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.