Self-hosted Nominatim
The question
Both of these run on your own hardware, keep queries off the network, and cost infrastructure rather than per request. So the residency argument does not separate them, and neither does the licensing one. What separates them is what happens to your string after it arrives.
What Nominatim is
Nominatim is the search engine behind OpenStreetMapOpenStreetMap (OSM). A community-curated global map database (ODbL-licensed) with addr:* tagged features and place hierarchies. A secondary corpus source and a source of street names.'s own place search. Its documentation, read on 2026-08-04 at version 5.3.2, defines it as:
"Nominatim (from the Latin, 'by name') is a tool to search OSMOpenStreetMap (OSM). A community-curated global map database (ODbL-licensed) with addr:* tagged features and place hierarchies. A secondary corpus source and a source of street names. data by name and address and to generate synthetic addresses of OSMOpenStreetMap (OSM). A community-curated global map database (ODbL-licensed) with addr:* tagged features and place hierarchies. A secondary corpus source and a source of street names. points (reverse 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.)."
It offers search, reverse 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., address lookup, details and status endpoints, and the manual notes a "limited capability to search featuresfeatureAn input signal a model conditions on. Beyond the raw tokens, Mailwoman feeds soft features — gazetteer-membership channels and the postcode anchor — that inform predictions without overriding them. by their type (pubs, hotels, churches, etc)."
Its published install requirements, read the same day:
"A minimum of 2GB of RAM is required or installation will fail. For a full planet import 128GB of RAM or more are strongly recommended." … "For a full planet install you will need at least 1TB of hard disk space."
Read that as what it is: a planet-scale recommendation for smooth operation under load, published by a project that would rather you provision correctly than discover the ceiling in production. 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.-scale import is a different and much smaller thing, and the same page is where you would find that out.
What each one is built to do
Nominatim indexes every OSMOpenStreetMap (OSM). A community-curated global map database (ODbL-licensed) with addr:* tagged features and place hierarchies. A secondary corpus source and a source of street names. place as a searchable record and ranks your whole string against the index. Mailwoman labelscomponent tagOne of the 25 labels in Mailwoman's address schema — street, locality, region, postcode, house_number, unit, po_box, country, venue, intersection, and others. Each parsed span carries exactly one component tag. the spansspanA contiguous range of characters or tokens in the input string, tagged with an address component type (street, locality, postcode, etc.). Parsed addresses are represented as collections of spans, possibly nested in a tree. of your string first and then runs one constrained lookup per spanspanA contiguous range of characters or tokens in the input string, tagged with an address component type (street, locality, postcode, etc.). Parsed addresses are represented as collections of spans, possibly nested in a tree.. That single difference produces the rest of this table.
| Nominatim | Mailwoman | |
|---|---|---|
| Design | Search over an index of every place | Labelcomponent tagOne of the 25 labels in Mailwoman's address schema — street, locality, region, postcode, house_number, unit, po_box, country, venue, intersection, and others. Each parsed span carries exactly one component tag. the string, then look up each spanspanA contiguous range of characters or tokens in the input string, tagged with an address component type (street, locality, postcode, etc.). Parsed addresses are represented as collections of spans, possibly nested in a tree. |
| Store | PostgreSQL with spatial extensions | Sealed SQLite files, read from disk |
| Reference data | OpenStreetMapOpenStreetMap (OSM). A community-curated global map database (ODbL-licensed) with addr:* tagged features and place hierarchies. A secondary corpus source and a source of street names. | Who's On FirstWOF (Who's On First). An open-source gazetteer of places maintained by Mapzen/whosonfirst. Mailwoman builds a custom SQLite database from WOF GeoJSON repos, extended with postcode data, importance scores, and coincident-role relations., plus national registersinput modeThe Decision-A register switch: 'fragmented' (human-typed fragments — feeds the evidence channels) vs 'formatted' (complete records — runs the trained absence identity). Explicit on CLI/API; per-endpoint defaults (batch→formatted, autocomplete→fragmented); kind-derived otherwise. 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. |
| Ambiguity | Surfaced as a ranked result list | Resolved to one reading, with alternatives attached |
| Partial or fuzzy input | A strength — scoring is continuous | A weakness — a failed parseaddress parsingThe process of decomposing a free-text postal address string into structured components — house number, street name, locality, region, postcode, and country — so a geocoder can resolve them to coordinates. has nothing to look up |
| Non-address queries | Answers them; place types are searchable | Not the design |
| What arrives | A matched record with an address breakdown | Labeled spansspanA contiguous range of characters or tokens in the input string, tagged with an address component type (street, locality, postcode, etc.). Parsed addresses are represented as collections of spans, possibly nested in a tree. with offsets, plus a coordinate and a tier |
| Setup | An import and an index build | A package install and a download |
Where Nominatim is stronger, without qualification. It answers queries that are not addresses. It degrades gracefully — a misspelled or half-remembered string still returns a ranked list, where a parser that mislabelscomponent tagOne of the 25 labels in Mailwoman's address schema — street, locality, region, postcode, house_number, unit, po_box, country, venue, intersection, and others. Each parsed span carries exactly one component tag. a spanspanA contiguous range of characters or tokens in the input string, tagged with an address component type (street, locality, postcode, etc.). Parsed addresses are represented as collections of spans, possibly nested in a tree. looks up the wrong index and returns nothing at all. Its data is OpenStreetMapOpenStreetMap (OSM). A community-curated global map database (ODbL-licensed) with addr:* tagged features and place hierarchies. A secondary corpus source and a source of street names., so a place that exists in OSMOpenStreetMap (OSM). A community-curated global map database (ODbL-licensed) with addr:* tagged features and place hierarchies. A secondary corpus source and a source of street names. is reachable the day it is mapped, with no localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. tier to wait for. And a ranked list is the right shape for a search box, which is what it was built to serve.
Where the designs diverge on output. Nominatim returns the record that matched. Mailwoman returns which characters of your input were the streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels. and which were the town, with offsets. If your next step is deduplicationrecord matchingThe process of determining whether two database records refer to the same real-world entity. Mailwoman's matcher uses a geocode-first approach (match the resolved place, not the address string) with Fellegi-Sunter probabilistic scoring., validation or record matchingrecord matchingThe process of determining whether two database records refer to the same real-world entity. Mailwoman's matcher uses a geocode-first approach (match the resolved place, not the address string) with Fellegi-Sunter probabilistic scoring., that decomposition is the product and a matched record is a step short of it.
When to choose Nominatim
- Your queries are exploratory. Search boxes, partial strings, landmarks, place types. This is its home ground, and a parser is the wrong instrument because there is frequently nothing to parseaddress parsingThe process of decomposing a free-text postal address string into structured components — house number, street name, locality, region, postcode, and country — so a geocoder can resolve them to coordinates..
- You want OpenStreetMapOpenStreetMap (OSM). A community-curated global map database (ODbL-licensed) with addr:* tagged features and place hierarchies. A secondary corpus source and a source of street names. specifically. If your workflow depends on OSMOpenStreetMap (OSM). A community-curated global map database (ODbL-licensed) with addr:* tagged features and place hierarchies. A secondary corpus source and a source of street names. identifiers, OSMOpenStreetMap (OSM). A community-curated global map database (ODbL-licensed) with addr:* tagged features and place hierarchies. A secondary corpus source and a source of street names. tags, or contributing corrections upstream and seeing them in your own results, that loop is worth more than any property of a different engine.
- You are already operating PostgreSQL well. The database is the operational burden, and a team that runs Postgres competently has already paid most of it.
- 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. OSMOpenStreetMap (OSM). A community-curated global map database (ODbL-licensed) with addr:* tagged features and place hierarchies. A secondary corpus source and a source of street names. 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 a property of the map, not of a localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. tier. Where our 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 unverified, What ships today says so, and an engine with global OSMOpenStreetMap (OSM). A community-curated global map database (ODbL-licensed) with addr:* tagged features and place hierarchies. A secondary corpus source and a source of street names. 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 the more predictable choice.
- Your workload is reverse 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. over dense OSMOpenStreetMap (OSM). A community-curated global map database (ODbL-licensed) with addr:* tagged features and place hierarchies. A secondary corpus source and a source of street names. featuresfeatureAn input signal a model conditions on. Beyond the raw tokens, Mailwoman feeds soft features — gazetteer-membership channels and the postcode anchor — that inform predictions without overriding them.. Coordinate to nearest mapped featurefeatureAn input signal a model conditions on. Beyond the raw tokens, Mailwoman feeds soft features — gazetteer-membership channels and the postcode anchor — that inform predictions without overriding them., across every featurefeatureAn input signal a model conditions on. Beyond the raw tokens, Mailwoman feeds soft features — gazetteer-membership channels and the postcode anchor — that inform predictions without overriding them. class, is what the index is arranged for.
When to choose Mailwoman
- Your input is postal. Rows from a form, a CRM export, a delivery manifest — strings that are addresses, where the parseaddress parsingThe process of decomposing a free-text postal address string into structured components — house number, street name, locality, region, postcode, and country — so a geocoder can resolve them to coordinates. is the useful part.
- You need the decomposition. SpansspanA contiguous range of characters or tokens in the input string, tagged with an address component type (street, locality, postcode, etc.). Parsed addresses are represented as collections of spans, possibly nested in a tree. with offsets, not a matched record you post-process into fields.
- You want a smaller resident footprint. The 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. is read from disk rather than held in memory, which is what the constrained-probe design buys.
- You want to scope the data to what you serve. 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 a set of downloads, so a France-only deployment carries France-sized artifacts.
- You have Nominatim clients already written.
@mailwoman/nominatimserves/search,/reverseand/statuson a compatible surface, so the swap does not touch calling code for/searchand/status—/reversereturns an empty result until you build a full WOFWOF (Who's On First). An open-source gazetteer of places maintained by Mapzen/whosonfirst. Mailwoman builds a custom SQLite database from WOF GeoJSON repos, extended with postcode data, importance scores, and coincident-role relations. distribution and mount it — Swap in for Nominatim walks it.
The two compose
A 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. can labelcomponent tagOne of the 25 labels in Mailwoman's address schema — street, locality, region, postcode, house_number, unit, po_box, country, venue, intersection, and others. Each parsed span carries exactly one component tag. first, take the constrained lookup when it succeeds, and fall back to a ranked search over the raw string when the labeling produces nothing usable. That inherits both sets of costs and is a real design — it is the shape to reach for when your input is mostly postal with a tail that is not.
Run it yourself
The comparison that decides this is not ours to run for you: take a thousand rows of your own input, send them through both, and look at how each one fails rather than at how each one scores. Our own published panels and their scripts:
curl -fsSLO https://mailwoman.sister.software/benchmarks/fr-ban-panel.mjs
curl -fsSLO https://mailwoman.sister.software/benchmarks/fr-ban-sample.json
mailwoman data pull candidate fr
node fr-ban-panel.mjs --data-root <DATA_ROOT>
Benchmarks carries the method and the results, including the rows that missed.
Related
- The two architectures — the design split this page is a case of, with the hardware figures for four engines.
- Swap in for Nominatim — the compatible endpoint, end to end.
- Drop-in replacements — what the compatible surfaces cover.
- Footprints — our measured install and download sizes.