Self-hosting Nominatim vs a hosted geocoder

Nominatim is the open-source geocoder for OpenStreetMap data. Its public server allows at most one request a second, and no autocomplete or heavy use, as the OpenStreetMap API guide explains. Running your own server removes those limits: you choose the area, the speed, and how often the data updates. This guide runs it with Docker, from a small test to the whole planet, and covers what that costs compared with a hosted geocoder.

It was tested with Nominatim 5.3 in the mediagis/nominatim Docker image, on a machine with 4 CPU cores and 16 GB of memory.

Try it on a small area

Monaco is small enough to import in about a minute, so it's a good first test. This downloads the area from Geofabrik, imports it, and starts the API on port 8080:

docker run -it --shm-size=1g \
  -e PBF_URL=https://download.geofabrik.de/europe/monaco-latest.osm.pbf \
  -e REPLICATION_URL=https://download.geofabrik.de/europe/monaco-updates/ \
  -e NOMINATIM_PASSWORD=very_secure_password \
  -v nominatim-data:/var/lib/postgresql/16/main \
  -p 8080:8080 \
  --name nominatim \
  mediagis/nominatim:5.3

The nominatim-data volume keeps the database when the container is removed, so a restart doesn't import again. Change the password: it's for the PostgreSQL database inside the container.

Once the log says Application startup complete, search it the same way as the public server:

curl "http://localhost:8080/search?q=Avenue+Pasteur,+Monaco&format=jsonv2&limit=1"
[
  {
    "osm_type": "way",
    "osm_id": 1549110514,
    "lat": "43.7296730",
    "lon": "7.4107761",
    "category": "highway",
    "type": "tertiary",
    "name": "Avenue Pasteur",
    "display_name": "Avenue Pasteur, Jardin Exotique, Monaco, 98020, Monaco"
  }
]

/reverse, /lookup, and /status work too, with the same parameters as the Nominatim API docs.

Import a country

Geofabrik has an extract for every country and many regions, each with its own updates folder. Point PBF_URL and REPLICATION_URL at the area you need. For Germany, they're https://download.geofabrik.de/europe/germany-latest.osm.pbf and https://download.geofabrik.de/europe/germany-updates/.

For larger areas, also:

  • Give PostgreSQL shared memory. Set --shm-size to about half the machine's memory.
  • Use a flatnode file. Mount a volume at /nominatim/flatnode, and the import stores node locations in a file instead of the database. Nominatim recommends it for large imports, such as Europe, North America, or the planet.
  • Import only what you search. IMPORT_STYLE sets how much of the map goes in. address keeps what's needed down to house numbers, and leaves out points of interest. full, the default, keeps them.
  • Improve the ranking. IMPORT_WIKIPEDIA=true adds Wikipedia's importance scores, so well-known places rank above obscure ones with the same name. Without it, a search for Stade Louis II in the Monaco test found the bus stop of that name before the stadium. IMPORT_US_POSTCODES and IMPORT_GB_POSTCODES add postcode data for those countries.

How long an import takes depends on the extract's size and the disk. On the test machine, a 73 MB extract of the Portland area took about 11 minutes to import, and made a 3.2 GB database.

Import the planet

The whole planet is a different scale of job. Nominatim's installation guide asks for:

  • Memory: 128 GB or more is strongly recommended, and 64 GB at the least.
  • Disk: at least 1 TB, on fast NVMe drives.
  • Time: about two and a half days to import on a well-configured machine, or four to five on ordinary SSDs.

The import guide gives rough figures for each import style, measured on the 2020 planet. The planet has grown since, so expect more:

Style Import time Database Without update data
admin 4 hours 215 GB 20 GB
street 22 hours 440 GB 185 GB
address 36 hours 545 GB 260 GB
full 54 hours 640 GB 330 GB

The last column is the size after FREEZE=true, which drops the data used for updates. A frozen database can't be updated, so refreshing it means importing again.

Keep it updated

OpenStreetMap changes every minute. With REPLICATION_URL set, UPDATE_MODE=continuous keeps the database up to date in the background, or run the update by hand:

docker exec -it nominatim sudo -u nominatim nominatim replication --project-dir /nominatim

This keeps applying changes, and checks again every 15 minutes when there are none. Geofabrik's extracts update once a day.

What you still don't get

Running your own server removes the usage policy, not Nominatim's design:

  • No autocomplete. Nominatim matches whole words, so a partial address such as Place du Cas finds nothing until it's typed in full.
  • Only OpenStreetMap's addresses. Where OpenStreetMap is missing house numbers, so is Nominatim. In the US, the optional TIGER data fills in many by estimating a house's position along its street.
  • Your own operations. Backups, monitoring, upgrades, and the server bill are yours.

Self-hosted or hosted

Self-hosting suits you if you need one country, a lot of requests, and someone to run it. For the planet, the server alone is a machine with 128 GB of memory and 1 TB of NVMe, kept running and updated.

A hosted geocoder suits you if you'd rather not run that. Mapricot is one, built on Pelias with OpenStreetMap, OpenAddresses, Overture, and other open data, so it finds more house numbers than OpenStreetMap alone, and it has autocomplete. The first 250,000 requests every 30 days are free, then they cost $0.10 per 1,000, and you can keep the results. Mapricot vs Nominatim compares them side by side.

Questions

What's Nominatim's rate limit? The public server at nominatim.openstreetmap.org allows at most one request a second, from your whole app. Your own server has no limit beyond what its hardware can answer.

How much memory does Nominatim need? At least 2 GB for a small area. For the whole planet, 128 GB or more is recommended.

Can I run Nominatim without Docker? Yes. The installation guide installs it on Ubuntu with PostgreSQL and PostGIS. The Docker image does the same steps for you.

Can I import more than one country? Yes. Merge the extracts into one file with osmium, such as osmium merge france.osm.pbf germany.osm.pbf -o merged.osm.pbf, and import that with PBF_PATH. Updates are simpler from one Geofabrik region that covers them all, such as Europe.