Geocoding

Watchman can attach latitude and longitude to list addresses at refresh time. It is optional and off by default (since v0.57.0). Providers: OpenCage, Nominatim, or Google Maps.

Geocoding does not change match scores today. Address similarity still compares parsed text fields (line, city, state, postal code, country). Coordinates are stored on each Address (latitude / longitude), returned in search JSON, and shown in the UI.

Use it when a downstream system wants a map pin, a distance filter you apply yourself, or a stable lat/long on exported records. Skip it if you only need Watchman to score names and IDs.

What happens when it is on

On each list refresh, Watchman walks every loaded entity that has addresses and calls the provider (one goroutine per entity). Hits go through an in-memory LRU (L1) and, if you enable it, a database cache (L2). Failed lookups leave the address unchanged; they do not fail the refresh.

Query-time address= on /v2/search is parsed (libpostal / usaddress / deepparse). Those query addresses are not geocoded. Scoring still compares the parsed fields.

Tradeoffs

Factor What you pay Why it matters
Startup / refresh time One provider call per distinct address, rate-limited (default 1.5 req/s, burst 5) A list with tens of thousands of addresses can take hours on a cold cache. L1/L2 caches make later refreshes cheap.
Money / quota OpenCage and Google are paid APIs. Nominatim is free with a usage policy Default 1.5 req/s is meant to stay polite. Self-host Nominatim if you cannot use a commercial key.
Memory / DB L1 holds up to L1MaxSize entries (default 10,000) for L1TTL (default 24h). L2 writes to MySQL/Postgres L2 needs the Database block. Without it, coordinates are recomputed after restart.
Score No change Similarity does not use lat/long. Turning geocoding on will not move minMatch hits.
Privacy Full street addresses leave your network Prefer a self-hosted Nominatim if addresses must stay inside your network.

Rate-limit and cache YAML: Configuration.

When it would change a score

It would only matter if scoring compared coordinates (for example a distance threshold between two pins). That path is not implemented. Two records at “123 Main St, Springfield” vs “123 Main Street, Springfield, IL” still match on tokens and country folding, with or without geocoding.

If you need distance logic, read latitude / longitude from the search response (or from ingest/export) and apply it in your application.

Providers

Set Watchman.Geocoding.Enabled: true and a provider name. GEOCODING_API_KEY overrides Provider.ApiKey.

OpenCage

OpenCage Geocoding API. Config name: opencage. Paid key required for production volume.

Google

Google Geocoding API. Config name: google. Paid key required.

Nominatim

Nominatim (OpenStreetMap). Config name: nominatim. No API key. Set Provider.BaseURL to a self-hosted instance for production. The public OSM endpoint is for light, policy-compliant use only.

To add a provider, open an issue.