Skip to main content

From Pelias to Mailwoman

A short lineage for readers who already know PeliasPeliasAn open-source geocoder, Mailwoman's spiritual predecessor..

Pelias in one paragraph

Pelias is an open-source geocoder. It takes an input string like "350 5th Ave, New York, NY 10118" and returns a structured place. Under the hood, PeliasPeliasAn open-source geocoder, Mailwoman's spiritual predecessor. splits this into two jobs:

  • Parsingaddress 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. — turn the string into labelled parts (house_number=350, street=5th Ave, locality=New York, region=NY, postcode=10118). For this, PeliasPeliasAn open-source geocoder, Mailwoman's spiritual predecessor. uses libpostal, a C library trained on 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. data.
  • Resolving — look up the parsed place in 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. (a large place database, often Who's On First) and return coordinates plus IDs.

The two-job split is important. If we get a great parser but a weak 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., results are still bad. If we get a great 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. but a weak parser, 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. never sees the right query. Both halves have to be strong.

Where Mailwoman came from

Mailwoman v1 was an effort to replace libpostal with a TypeScript-native parser. The motivations were practical:

  • libpostal is a 2 GB binary that's painful to ship in browsers, serverless functions, or edge runtimes.
  • libpostal ships as a black box: its trainingtrainingThe process of adjusting a model's parameters so its predictions match labeled examples, by repeatedly measuring error and nudging the weights to reduce it. Distinct from inference, when the trained model is run on new input. 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., its 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.' is a CRFCRF (Conditional Random Field). A statistical modeling method that predicts structured outputs by modeling dependencies between adjacent labels. Mailwoman uses a linear-chain CRF as the Viterbi decoder at inference time to enforce BIO label consistency — a B-street must be followed by I-street or O, never I-locality. (conditional random fieldCRF (Conditional Random Field). A statistical modeling method that predicts structured outputs by modeling dependencies between adjacent labels. Mailwoman uses a linear-chain CRF as the Viterbi decoder at inference time to enforce BIO label consistency — a B-street must be followed by I-street or O, never I-locality. — see concepts/crf-decoder.md), but there is no easy way to retrain it on your own data.
  • PeliasPeliasAn open-source geocoder, Mailwoman's spiritual predecessor.'s TypeScript ecosystem wanted a parser it could iterate on directly.

Mailwoman v1 used rule classifiers: hand-written code that looks at each tokentokenOne 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. (word) of the input and decides what kind of address component it is. A rule like "if it starts with 5 digits, it is a US 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." is one classifier. There are dozens of them, one per component type. They run in parallel, vote, and a solver picks the best combination. See how-it-used-to-work.md for the full story.

This worked, but it ran into the same limit every rule-based parser hits: the long tail. Real-world addresses have shapes the rules do not know about. "Saint Petersburg, FL" is two words but one citylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighbourhood in the hierarchy.. "Mt Tabor Park" is a venuevenueA named, non-address place — a business, building, park, or stadium. Mailwoman's free-text point-of-interest component, added as a Tier 2 fine label., not a streetstreetThe named linear feature along which house numbers are ordered. Decomposes into a name plus street affixes; one of the Tier 2 fine labels.. Rules can describe these cases, but writing them all out is a never-ending project.

What changed in 2026

Mailwoman v2 — what you are reading docs for — keeps the rule classifiers but adds a neural classifierneural 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.' alongside them. Both run; both produce candidate labelscomponent tagOne of the 33 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 per-component policy decides which one's vote counts more for each address component type. The migration is gradual on purpose: rules stay until the neural classifierneural 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.''s metrics prove it does better.

The neural classifierneural 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.' is a small transformerneural 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.' 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.' (about 29M parametersparameterA single learned number inside a model — one weight or bias. Mailwoman's encoder has roughly 30 million of them; training is the search for good values. in the current weightsparameterA single learned number inside a model — one weight or bias. Mailwoman's encoder has roughly 30 million of them; training is the search for good values. — see concepts/how-mailwoman-parses-an-address.md) trained on a 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. built from many open data sources and rebuilt many times over — see concepts/training-pipeline.md for how it's constructed. It ships in two piecesECE (Expected Calibration Error). A metric that measures how well a model's confidence scores align with its actual accuracy. Lower is better. Mailwoman's held-out ECE drops from 0.067 (raw) to 0.0035 (calibrated).:

  • @mailwoman/neural — the runtime that loads the 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.' and runs inferenceinferenceRunning the trained model on new input to get predictions, as opposed to training, which produces the model. In Mailwoman that means a small transformer encoder reads an address string and classifies every token — house number, street, locality, region, postcode, and the rest. A Who's On First gazetteer can feed soft location hints into the pass, but the model makes the final call on every label. Where a generative model writes text token by token, Mailwoman's output is a retrieval-augmented token classification: one label per input piece. (works in Node.js and the browser).
  • @mailwoman/neural-weights-en-us and @mailwoman/neural-weights-fr-fr — the 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.' files. Two npm packages, but one trained 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.' today: the publish workflow copies the en-us artifacts into the fr-fr package. LocalelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for.-specific weightsparameterA single learned number inside a model — one weight or bias. Mailwoman's encoder has roughly 30 million of them; training is the search for good values. are future work.

The PeliasPeliasAn open-source geocoder, Mailwoman's spiritual predecessor. side of the equation — 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. + resolverresolverThe component that converts parsed address components (locality, region, postcode) into coordinates by looking them up in the gazetteer. The resolver ranks candidates by name match, population, and proximity, and returns the best-matching place with its centroid or polygon. — is also evolving. Mailwoman now ships its own resolverresolverThe component that converts parsed address components (locality, region, postcode) into coordinates by looking them up in the gazetteer. The resolver ranks candidates by name match, population, and proximity, and returns the best-matching place with its centroid or polygon. against 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. as a SQLite database, both server-side and in the browser via WebAssembly. See concepts/resolver-and-wof.md.

What stayed the same

  • The two-job split. 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., then resolve. Same as PeliasPeliasAn open-source geocoder, Mailwoman's spiritual predecessor.. Same as every modern geocoder.
  • The output shape. Mailwoman emits parsed components with confidence scores and offsets, the same surface a PeliasPeliasAn open-source geocoder, Mailwoman's spiritual predecessor. consumer would expect.
  • The CLI ergonomics. mailwoman parse <input> is the entry point.
  • Multi-localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. packaging. Mailwoman ships a separate weightsparameterA single learned number inside a model — one weight or bias. Mailwoman's encoder has roughly 30 million of them; training is the search for good values. package per localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. (en-us, fr-fr) — a packaging boundary for a localelocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. to get its own trained weightsparameterA single learned number inside a model — one weight or bias. Mailwoman's encoder has roughly 30 million of them; training is the search for good values. without a breaking change, even though today both packages carry the same 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.' (see plan/reference/ARCHITECTURE.md).

What we deliberately do differently: no span left behind

One PeliasPeliasAn open-source geocoder, Mailwoman's spiritual predecessor. behavior we do not carry forward. The PeliasPeliasAn open-source geocoder, Mailwoman's spiritual predecessor. parser's solver is lossy by design: 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. that don't fit the winning interpretation are demoted to "accessory" information and punted to the resolverresolverThe component that converts parsed address components (locality, region, postcode) into coordinates by looking them up in the gazetteer. The resolver ranks candidates by name match, population, and proximity, and returns the best-matching place with its centroid or polygon.. If your only goal is "resolve to a point", that's a reasonable economy. But it forecloses the geocoder-adjacent jobs — chiefly record linkagerecord 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., deciding whether two rows in two datasets describe the same entity — because 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. no longer accounts for the whole string.

Mailwoman's parser labelscomponent tagOne of the 33 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. every tokentokenOne 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. (the BIO sequence covers the full input), and the design goal is a lossless, typed decomposition: every character classified or explicitly tagged unknown, 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. carrying a canonical value. Two records match when their canonicalized 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.-sets agree, surface variation and all — something a lossy parser structurally cannot offer. The full argument lives in concepts/synonymy-and-homonymy.md.

Next

  • How it used to work — the rule-only era in detail
  • How it works now — the hybrid
  • What is an address? — the deep dive on the data 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.'