Skip to main content

Runtime flags

Scope

Two things configure a running Mailwoman: environment variables, and the defaults on the mechanisms inside the 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.. This page covers both, restricted to what a consumer of the published packages can act on.

The boundary matters, because the repository's own environment schema is wider than this page. That schema splits its variables by whether they are safe to log rather than by whether a consumer should set them, so it also declares the release-publishing settings, the 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. dev-linking overrides, the 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. fetch knobs, and the switches the evaluationevalRunning the model against a held-out golden dataset and computing per-component F1, exact-match, calibration, and resolved-coordinate error. scripts read. None of those does anything in an installed package, and several are declared but read nowhere. If a variable is not on this page, setting it changes nothing you can observe.

Behavior defaults are listed after the variables. They are not environment variables — each is an option on createRuntimePipeline, geocodeAddress, or 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., and the table states where.

Environment variables

Every variable below is read by shipped runtime code. Each has no default unless the table says so.

VariableDefaultEffectSet it when
MAILWOMAN_DATA_ROOTa built-in pathThe root directory for every downloaded artifact: gazetteersgazetteerA 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., shardsshardA partial output file of the corpus build, written in Parquet format. The training pipeline streams shards row by row., POIpoint of interest (POI). A named place that is not strictly an address — landmark, transit stop, venue, amenity, or franchise. Mailwoman tags these as venue and resolves them through the gazetteer. layerlayerOne transformer block — attention plus a feed-forward network, with normalization and residual connections — applied to every position. Stacking layers lets the model build up richer representations; Mailwoman's encoder has 6.Your data lives anywhere but the default. Run mailwoman doctor to see the resolved value
MAILWOMAN_CANDIDATE_DB<data root>/wof/candidate.dbPath to candidate.db, overriding the convention path. none pins the FTS backend insteadYour copy lives outside the data root, or you want the FTS backend
MAILWOMAN_WOF_DBunsetPath to a full 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. SQLite distribution, used by the search backendYou resolve against a full distribution rather than candidate.db
MAILWOMAN_WOF_ADMIN_DBunsetPath to the 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 for mailwoman reverseYou reverse geocode
MAILWOMAN_WOF_POLYGONS_DBunsetPath to the polygon sidecar. Without it every reverse result is approximateYou need polygon-exact containment
MAILWOMAN_POSTAL_CITY_ALIAS_DBunsetPath to the postal-citylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy. alias database, which adds an alias-aware scoring passYou geocode United States mailing addresses at volume
MAILWOMAN_FST_BINunsetPath to 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. index mailwoman autocomplete readsYou run autocomplete against an index outside a 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
MAILWOMAN_MODEL_CARDthe package's cardPath to a model cardmodel cardA JSON metadata file (model-card.json) shipped with each weights bundle. It declares the model version, lineage, label set, required inference channels (anchor, gazetteer), calibration data, and training provenance., read by the server's /health reportYou serve 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.' whose card is not beside it
MAILWOMAN_COARSE_PLACER_DIRthe bundled placerDirectory holding the coarse 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. placerYou replace the bundled placer
MAILWOMAN_BATCH_MAX1000The row cap on POST /v1/batch under mailwoman serveYou 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. more than 1000 rows per request

MAILWOMAN_CANDIDATE_DB is the variable most installs no longer need to set. Since 8.7.0 the candidate 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 the default backend, and it is discovered rather than configured. Every surface that resolves places — parse, geocode, serve, poi, registry, the MCP server, and the nominatim and photon drop-ins — reads an explicit --candidate-db, then this variable, then the convention path <data root>/wof/candidate.db, taking the first that exists on disk. mailwoman data pull candidate writes that path, so a bare pull is the whole setup. (The libpostal drop-in never appears in that list: it parsesaddress 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. and expands, and resolves nothing.)

Two things the variable is still for. Point it at a copy that lives outside the data root, or set it to the literal none (equivalently --candidate-db none) to pin the older FTS backend over a full 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. distribution. data pull still prints an export line on success; it is a leftover from when the export was required, and following it changes nothing unless your file is elsewhere.

The change has a real edge: a machine that had candidate.db sitting at the convention path while running on the FTS backend switches backends on upgrade, with no configuration edited. none is the way back.

Setting both MAILWOMAN_CANDIDATE_DB and MAILWOMAN_WOF_DB is not an error, and the candidate backend wins. With a reachable candidate.db, mailwoman parse --resolve and mailwoman geocode need 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. path at all. mailwoman registry run is the exception: it checks for MAILWOMAN_WOF_DB or --resolve-db at startup and refuses to run without one, then ignores the path it insisted on and resolves against the candidate database anyway. Give it any valid path to get past the check.

The 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. cap has two values, and both are correct. @mailwoman/api used as a library defaults to 500; mailwoman serve passes MAILWOMAN_BATCH_MAX, which defaults to 1000.

Precedence

A command-line flag beats an environment variable, which beats the built-in default. The flag names are on CLI; each flag's description names the variable it falls back to.

--resolve-db <path> > $MAILWOMAN_WOF_DB > error, with the fix printed
--candidate-db <path> > $MAILWOMAN_CANDIDATE_DB > <data root>/wof/candidate.db > the search backend
--data-root <path> > $MAILWOMAN_DATA_ROOT > a built-in path

The candidate row has one wrinkle the other two do not. Each position is used only if the file it names is on disk, so a stale $MAILWOMAN_CANDIDATE_DB pointing at a deleted file does not fall through to the convention path — it resolves to nothing and you land on the search backend. And none at either of the first two positions is a pin, not a path: it stops the search there.

A .env file in the working directory is read once at startup and the live environment layerslayerOne transformer block — attention plus a feed-forward network, with normalization and residual connections — applied to every position. Stacking layers lets the model build up richer representations; Mailwoman's encoder has 6. on top of it, so an exported variable beats a .env entry.

Behavior defaults

Every mechanism below is on by default. Each cleared a gate against the shipped 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.' on the first-class localeslocaleThe combination of language and country an address comes from. en-US and fr-FR are the locales Mailwoman ships weights for. before it was promoted, so the defaults are the measured configuration and turning one off is the change that needs a reason. Each is an option, not an environment variable.

MechanismWhereEffectTurn it off when
spanRescoreResolveOptsOn an UNRESOLVED tree only, recovers a localitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy. the subword tokenizertokenizerThe component that converts a raw address string into a sequence of numeric token IDs the model can process. Mailwoman's tokenizer is a SentencePiece unigram model trained specifically on postal addresses. splitYou need output identical to a build without it
postcodeConsistencyResolveOptsA resolved 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. point pulls a same-named localitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy. to the right oneYour postcodespostcodeThe 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. are unreliable
hierarchyCompletionResolveOptsRecovers a localitylocalityThe city / town / settlement component of an address: a populated place sitting between region and neighborhood in the hierarchy. dropped when one name plays two administrative rolesNever, in normal use
parentFallbackResolveOptsRetries once without the parent constraint when a filtered lookup comes back emptyNever, in normal use
adminCoherenceResolveOpts, GeocodeDepsPicks the administratively consistent combination rather than the most populousYou want the older population-first ranking
placeCountryCreateRuntimePipelineOpts, GeocodeDepsA confident whole-string 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. guess biases ranking. It never filtersYou already pin the 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. and want no prior at all
hardPlaceCountryCreateRuntimePipelineOpts, GeocodeDepsPromotes that guess to a filter, inside a 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. safelistYou geocode outside the safelist and want 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 precisionprecisionOf the spans the model labeled as a given tag, the fraction it got right. High precision means few false positives. Paired with recall to compute F1.
normalizeCasepipelinestaged 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., classifier, GeocodeDepsTitle-cases detected all-caps ASCII input before 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.'Your input's casing carries meaning
enforceWordConsistencythe 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.'s classify callArbitrates disagreeing tags inside one wordYou call the classifier directly and want raw per-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. 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.
postcodeRepairthe 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.'s classify callA deterministic 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. repair passYou call the classifier directly. It is off there by default
spanProposerclassifier configSpanspanA 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.-proposal priors from 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). 2.7You need output identical to a build without it
poiQueryKindCreateRuntimePipelineOptsDetects a POIpoint of interest (POI). A named place that is not strictly an address — landmark, transit stop, venue, amenity, or franchise. Mailwoman tags these as venue and resolves them through the gazetteer. query and extracts its intent, without executing itYou only ever 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. addresses and want the earlier kind classification
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. index auto-loadCreateRuntimePipelineOpts.fstLoads the index from the classifier's 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 and biases emissionsYou need output identical to a build without the index

Two mechanisms are off by default and worth knowing about:

MechanismWhereEffectTurn it on when
calibrateParseOptsMaps raw 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. confidence through the shipped calibration tableYou threshold on confidence. See Library API
addressPoints, interpolationResolveOptsThe rooftoprooftopGeocoding precision at the building or parcel level — coordinates within a few meters — the highest tier of the geocode cascade. Sourced from address-point and situs data. and interpolationinterpolationA geocoding technique that estimates a coordinate along a street segment based on the house number range. Used as the middle tier of Mailwoman's geocode cascade when exact address-point data is unavailable. coordinate tiersYou have pulled 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. shardsshardA partial output file of the corpus build, written in Parquet format. The training pipeline streams shards row by row. for your regionregionThe first-level administrative subdivision of a country — a US state, a French region, a province. The component between country and locality.

The coordinate tiers are gated on data rather than on a measurement. They stay off because the shardsshardA partial output file of the corpus build, written in Parquet format. The training pipeline streams shards row by row. are a 41.3 GB download for the United States, not because they cost accuracy.

For every boolean option above, false is the disable signal and it is not the same as omitting the option: omitting means "give me the default", while false means "run as though this mechanism did not exist". The three non-boolean options work differently. calibrate takes a calibrator function, and addressPoints and interpolation take lookup objects, so for those three, omitting is the only way to leave the mechanism off.

Errors

ConditionMessage or symptomNext step
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. reachable on a resolving commandA startup error naming $MAILWOMAN_WOF_DB and --resolve-dbRun mailwoman data pull candidate. registry run also wants a --resolve-db it then ignores
candidate.db downloaded but a command still uses the search backend$MAILWOMAN_CANDIDATE_DB is set to a path that is not thereUnset it. A variable naming a missing file does not fall through to the convention path
A reverse geocode reports approximate containmentMAILWOMAN_WOF_POLYGONS_DB is unsetPoint it at the polygon sidecar
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. request answers 413 batch too largeThe request exceeded MAILWOMAN_BATCH_MAXRaise the variable, or chunk the request
A variable you set has no effectIt is outside this page's boundaryCheck the table above. Repository-only variables do nothing installed

mailwoman doctor reports which of these are resolved, and prints the one command that fixes each gap.

Rationale

The 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. 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. commands gate resolution on an environment variable rather than on a file existing at a conventional path, because adopting a database silently would change every result on the machine that downloaded it. A geocoder that answers differently depending on what happens to be on disk is not one you can reason about. The cost is the step this page keeps repeating: download, then export. The two drop-in servers take the opposite trade and read the convention path, because a drop-in that needs a second setup step is not a drop-in.

The behavior defaults are on rather than opt-in because a default nobody turns on is a mechanism that does not exist. Each one shipped on by default only after clearing a gate against the shipped 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 turning one off takes false rather than a rebuild.

The environment schema is broader than this page because its split is about logging safety — a variable is in the non-secret half when printing it cannot leak a credential. That is the right axis for a log line and the wrong axis for a configuration reference, so this page draws the line somewhere else and says where.

See also