Skip to content

About

Rust address resolution with libpostal, Nominatim, ClickHouse, Connect and gRPC

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

OpenGeocoding

Kubernetes-native geocoding: address search, autocomplete and reverse geocoding — on your infrastructure or through a hosted API.

Release License: PolyForm Shield CodSpeed

Turn free-text addresses into coordinates, help users find an address as they type, and resolve coordinates to nearby addresses or administrative regions.

Built in Rust, OpenGeocoding combines libpostal parsing with a read-only index built from Overture Maps, with optional OpenStreetMap, OpenAddresses and GeoNames inputs. The engine serves lookups in-process: no database, external geocoding backend or runtime data downloads.

Try the live demo · Hosted API docs · Self-host · Releases

Source-available under PolyForm Shield 1.0.0, not OSI open source. The engine and index remain experimental; evaluate coverage and accuracy for your use case before production.

What you can build

Capability Use it for
Address search Turn an address or place name into coordinates and structured address fields
Autocomplete Complete places, streets, houses and postcodes, with country filters and location-biased place ranking
Selection retrieval Resolve an autocomplete selection by its opaque ID, without another text search
Reverse geocoding Find nearby houses, with street and locality fallbacks
Region resolution Find administrative regions and ISO 3166-2 codes for a point
Region directory List the regions available in your index

Autocomplete can also include selected landmark categories: airports, stations, attractions, museums, universities, hospitals and stadiums. It is not a general business or POI directory.

Why OpenGeocoding

  • Keep lookups on your infrastructure. Self-host the engine and its data; address resolution does not call a third-party geocoder.
  • Operate one serving process. Parsing, search and reverse lookups share an in-process index. Models and index files are mounted read-only.
  • Search across languages and scripts. Indexed local and alternative place names, Unicode normalization and street-abbreviation handling support multilingual inputs.
  • Distinguish matches from fallbacks. Structured fields and goodMatch let clients identify weaker forward-geocoding answers; it is not a calibrated confidence score.
  • Kubernetes-native by design. The Helm chart manages index-build Jobs and serving Deployments through a leader elected with a Kubernetes Lease, with verified index downloads and rolling updates. Linux amd64/arm64 containers, readiness checks, Prometheus metrics and graceful shutdown are included.

Performance and resources

A world index built in under 20 minutes from already-downloaded sources; deployed forward search measured 1,774–2,675 queries/s per pod with 16 concurrent connections. The build figure is historical; search was measured on release 0.14.0 on 2026-10-19:

Workload Observed result
World index build, including landmarks Under 20 min, excluding downloads, 32.2 GB peak memory, on an 18-core Apple M5 Max with 64 GB RAM
Built world index About 16 GB on disk, excluding libpostal models and build scratch
Forward search, 16 connections to one pod 1,774–2,675 queries/s per pod, 18.4–29.9 ms p95, across three 20,000-request runs
Serving process in the search benchmark About 6.3 GiB process RSS

Search benchmark CPU: Intel Core i5-13500 (14 cores/20 threads) on a shared node. The pod requested 1 CPU with no CPU limit and used an observed 4.1–5.0 CPU cores averaged over each benchmark invocation; this is not a one-CPU throughput claim.

All 60,000 measured requests completed without errors. The client ran on another node and called one pod directly over Connect JSON/HTTP keep-alive, bypassing ingress and the public API edge. The workload repeated 1,000 address samples with the parse cache enabled and warmed. The third run was slower; the table includes all three runs, not only the fastest. These short runs are not a sustained-capacity or hosted API guarantee. Build downloads and model provisioning are additional. See the results and methodology and aggregate measurement record.

Compared with Nominatim

Nominatim 5.3's installation guide strongly recommends 128 GB RAM or more for a planet import, requires at least 1 TB of disk for a planet installation, and describes an import taking around 2.5 days on a well-configured machine (4–5 days on traditional SSDs). OpenGeocoding instead builds a compact read-only serving index and requires no PostgreSQL/PostGIS service.

This is operational context, not a like-for-like speedup claim. The input datasets, indexing work, coverage and hardware differ. Nominatim's import RAM recommendation is not its serving RAM usage. We have not published matched Nominatim queries/s, p95 latency or serving-memory measurements; those comparisons remain unmeasured.

Try the hosted API

For the shortest path to a request, create an API key in the dashboard and set OPENGEOCODING_API_KEY in your environment:

curl --fail-with-body https://api.opengeocoding.com/v1/search \
  -H "x-api-key: ${OPENGEOCODING_API_KEY:?Set your API key first}" \
  -H 'Content-Type: application/json' \
  -d '{"addressString":"Copenhagen, Denmark"}'

The hosted service manages authentication, credits and rate limits. This repository contains the self-hosted engine, not the hosted account or billing platform. Hosted routes and available operations are documented in the API reference; they differ from the direct RPC paths below.

Self-host

Your application → trusted network or authenticated proxy → OpenGeocoding
                                                           ├─ libpostal models
                                                           └─ read-only geographic index

You need both libpostal models and a compatible built index. Neither is included in the runtime image. Source downloads and index building happen before serving, not at service startup.

Run with Docker

Follow the Docker setup guide to obtain the image, provision models and build an index. With models at models/libpostal/ and that image's index at out/, start the service:

docker run --rm \
  -p 127.0.0.1:11121:11121 -p 127.0.0.1:8000:8000 \
  -v "$PWD/models/libpostal:/data/libpostal:ro" \
  -v "$PWD/out:/data/index:ro" \
  -e INDEX_DIR=/data/index \
  opengeocoding

In another terminal, make a Connect JSON request (no SDK required):

curl --fail-with-body http://localhost:11121/opengeocoding.OpenGeocoding/SearchAddress \
  -H 'Content-Type: application/json' \
  -H 'Connect-Protocol-Version: 1' \
  -d '{"addressString":"Copenhagen, Denmark"}'

Use a query inside your index's coverage if you built a regional index. Readiness is at http://localhost:11121/healthz; metrics are at http://localhost:8000/metrics.

The engine has no authentication. The command binds ports to loopback. Keep it on a trusted network or behind an authenticated proxy; do not expose the RPC or metrics ports directly to the internet.

Deploy on Kubernetes

The Helm deployment guide covers building and publishing indexes into an existing S3-compatible bucket, verified downloads into serving pods, and rolling upgrades. Each serving pod runs one geocoder instance with its own read-only index. Regional builds are supported.

The chart defaults request 1 CPU and 6 GiB RAM per serving pod, with a 16 GiB memory limit and no CPU limit. A CPU request is not a cap: the benchmark pod had these settings but consumed more than one CPU. The measured throughput is not a one-CPU guarantee. A world build requires substantial memory, scratch disk and initial downloads; review the guide before provisioning.

Geographic evaluation

Coverage depends on the source data and the index you build. Worldwide place coverage does not mean complete house-level coverage: substantial gaps remain in parts of Africa and Asia, and coverage varies elsewhere too. Regional indexes should not be treated as a safe geographic filter; out-of-area queries can still match an indexed namesake.

The repository includes authoritative-source evaluation corpora, held-out cases, regression gates and tools for comparing saved runs. These are diagnostic checks, not a production accuracy percentage. Some evaluation registries also supply index data, so agreement is not independent accuracy evidence.

Connect JSON and Connect Protobuf are the primary interfaces. Direct gRPC interoperability is not signed off: the documented grpcurl search timeout remains a known issue. Autocomplete IDs are valid only for the same index snapshot. See the API guide for matching semantics and operation-specific limits.

Documentation

Start with the documentation index for guides, evaluation workflows, performance evidence and implementation notes.

Area Contents
API Wire contract, request examples, autocomplete, landmarks, reverse geocoding and compatibility
Deployment Docker, Helm, model/index provisioning, configuration and diagnostics
Index building Data inputs, licensing, index construction and limitations
Development Build requirements, tests, reference data and publishing
Performance Measurement scope, resource observations, benchmarks and Nominatim context
Evaluation Corpora, scoring, held-out cases and regression gates
Provider evaluation Offline comparisons, request budgets and provider storage restrictions

The self-hosted wire contract is proto/opengeocoding-v1.proto. Found a bug? Open an issue, without personal addresses, credentials or private endpoints.

License

Project source is licensed under PolyForm Shield 1.0.0. It permits use, modification and redistribution, including commercial use, except providing a product that competes with this software or a product the licensor provides using it. A free product can compete too. Read the license before adopting or offering a service built on it.

This is source-available, not OSI open source, with no later conversion to an open-source license. Versions published before the switch retain FSL-1.1-ALv2, including its Apache-2.0 grant two years after each publication.

Data, models and third-party software have separate terms. Overture's divisions and transportation data and OpenStreetMap carry ODbL obligations; other input licenses vary. Review the index guide, NOTICE, third-party notices and license texts before distributing an index or deployment.

About

Rust address resolution with libpostal, Nominatim, ClickHouse, Connect and gRPC

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages