# komoot/photon: a self-hosted OpenStreetMap geocoder on OpenSearch

> Photon turns OpenStreetMap data into a search-as-you-type geocoder you can run yourself. This review covers the release-binary setup, the GraphHopper dump workflow, and the disk and RAM costs that decide whether it fits.

**komoot/photon** — an open source geocoder for openstreetmap data

- Repository: https://github.com/komoot/photon
- Stars: 3,083 · Forks: 375
- Language: Java
- License: Apache-2.0
- Published: 2026-09-24 · Updated: 2026-09-24 · Language: en
- Canonical page: https://hysenlabs.com/projects/komoot-photon

## What photon solves, and who ends up running it

Nominatim is the reference geocoder for OpenStreetMap, but it is a PostgreSQL and PostGIS workload, and the README describes photon as being built upon Nominatim for its data import rather than as a replacement for its query layer. Photon keeps the OpenStreetMap data but serves queries from OpenSearch, which is the piece that gives it search-as-you-type, typo tolerance and multilingual matching without you writing that logic. The README lists location bias, bounding-box filters and filtering by OSM tag and value as first-class features, and those are the operations an application actually performs: find places near this point, restrict results to this viewport, return only amenities.

The audience is therefore teams that already have a map or a routing product and need a geocoding endpoint they control. The README is explicit that the public demo at photon.komoot.io is not a production service: reasonable request volumes are welcome, but extensive usage will be throttled or banned, availability is not guaranteed, and changes can happen without notice. That sentence is the real adoption trigger. If your traffic is small and unpredictable, the demo is enough. If it is not, photon expects you to run the instance yourself, and the rest of the README is written for that person.

## How photon serves a query: OpenSearch plus a Nominatim-derived import

The architecture is a Java service in front of an OpenSearch index. The README states that photon requires Java 21 or newer, and that OpenSearch 3.x is needed only when you run against an external database instead of the embedded server. That embedded option matters: the release binaries ship with a bundled search server, so the simplest deployment is one JVM process and one data directory, with no separate OpenSearch cluster to operate.

The data path starts with OpenStreetMap, is processed through Nominatim, and lands as a photon database. The repository carries a continuously_update_from_nominatim.sh script at the top level, which is the continuous-update path the feature list refers to. For most users the import step is skipped entirely: GraphHopper publishes weekly dumps of an already-built photon database, and the README points at download1.graphhopper.com/public for both the world-wide dataset and selected country datasets. Those dumps contain names in English, German, French and the local language, which is where the multilingual search behaviour comes from.

The API surface is split across two documents: docs/usage.md for running, importing and updating, and docs/api-v1.md for the request and response format. The README does not inline either, so treat those two files as the contract you are integrating against.

## Installing photon from release binaries and running the first query

This is the path the README calls the easiest way to set up a self-hosted instance. Download a pre-built jar from the GitHub release page, then fetch a database dump. The README recommends pbzip2 over bzip2 for extraction speed and warns against WinRAR, which is documented as having issues with these files. The command below downloads, decompresses and extracts the planet dump in one step. Expect a long transfer and a directory tree containing photon_data once it finishes.

```bash
wget -O - https://download1.graphhopper.com/public/photon-db-planet-1.0-latest.tar.bz2 | pbzip2 -cd | tar x
```

The README stresses one detail here: adapt the directory name to match your photon version. The dump filename carries a version component, and pulling a dump built for a different photon release is the obvious way to get a broken instance.

With the database unpacked, change into the parent directory of photon_data and start the server. The wildcard matches the jar you downloaded, and serve is the subcommand that starts the webserver.

```bash
java -jar photon-*.jar serve
```

The README states the webserver is then available at http://localhost:2322. If the machine does not have enough RAM for the default heap, the README gives java -Xmx8G -jar ... as the way to raise it, with the caveat that enough free RAM must remain that the system does not start swapping. The request and response format for the first query is documented in docs/api-v1.md rather than in the README.

If you build from source instead, the README says photon uses gradle, and the project builds and tests with the following command. The final jar ends up in the target directory.

```bash
./gradlew build
```

## The disk, RAM and update costs nobody mentions in the feature list

A planet-wide photon database needs about 95GB of disk as of 2026, and the README says that figure grows by roughly 10 percent a year. SSDs are strongly recommended, NVMe better still. That is the size of the index alone, before you account for the compressed dump you downloaded and the jar.

The update procedure is where the storage arithmetic gets uncomfortable. The README describes the correct sequence: download and unpack the new version, swap the directories so the new one takes the place of the old, restart photon and check that everything works, then delete the old database. It then states plainly that this means you need twice the space of the database for updates. On a planet-sized instance that is roughly 190GB of fast storage at any moment you refresh, and the refresh cadence suggested by the weekly GraphHopper dumps is a real operational commitment, not a one-off.

There is a documented failure mode attached to this. The README carries a caution that you must never unpack the database in place of the old one, because that leads to corrupted data. The atomic swap is not a style preference; it is the only procedure the project sanctions.

Memory is the other constraint. At least 64GB of RAM is recommended for smooth operation, and more if the server takes significant load. Running with less is possible, and the README offers the heap flag as the adjustment, but it pairs that with the swapping warning. Treat 64GB as the design point rather than a suggestion.

## Where photon is the wrong tool

The clearest boundary is geometry. The README states that the GraphHopper dumps have no support for full geometry output, and links a pull request as the reference. If your application needs the polygon or line geometry of a result, you cannot use the convenient dump path; the README says you need to import your own database from a JSON dump instead. That converts a two-file setup into a Nominatim-backed import pipeline, with the additional Nominatim installation requirements the README links to.

A second boundary is scale of need rather than scale of data. Photon is designed to answer queries against a local index. If your lookup volume is modest, the operational cost of 95GB of SSD, 64GB of RAM and periodic dump swaps is hard to justify against simply calling the demo server within its stated reasonable limits, or against a hosted geocoding API. The README itself makes this argument when it says that users with a larger number of requests should consider a private instance, which implies the converse for everyone else.

Third, photon is not a routing engine and the README does not present it as one. It returns places and addresses. If you need turn-by-turn directions you are looking at a different class of software, even though the same organisation provides the dumps.

Finally, if you need address data outside OpenStreetMap coverage, no amount of tuning helps. The index is only as complete as the underlying OSM data.

## Photon compared with running Nominatim directly

The natural alternative is Nominatim, and the difference is architectural rather than cosmetic. Nominatim is a PostgreSQL and PostGIS application: you install a relational database, load OSM data into it, and queries are SQL against that schema. Photon takes the same OpenStreetMap source, uses Nominatim for the import, and serves from OpenSearch instead. The practical consequences follow from that split.

Search behaviour is the first difference. Photon's feature list includes search-as-you-type, typo tolerance and multilingual search as built-in properties of the search layer. Nominatim's query interface is a different design and the photon README does not attempt a feature-by-feature comparison, so the honest statement is that photon inherits OpenSearch's matching behaviour while Nominatim inherits PostGIS's spatial query behaviour.

Deployment is the second. Photon with the GraphHopper dumps is a jar plus an unpacked directory. Nominatim is a database server you administer. For a team without PostgreSQL and PostGIS experience, photon's release-binary route is the shorter path, which is exactly why the README calls it the easiest way.

The trade-off runs the other way on geometry. Because photon's dump path omits full geometry, a Nominatim deployment that already holds the underlying data can answer questions photon's dumps cannot without a custom import. If geometry matters more than typo tolerance, the comparison flips.

A smaller alternative worth knowing about is the leaflet.photon plugin, which the README lists under related projects for putting a search box in front of a photon server. It is a client, not a geocoder, so it complements photon rather than replacing it.

## Licence, contribution rules and what to check before you deploy

Photon is licensed under the Apache License, Version 2.0, and the repository carries the LICENSE file at the top level alongside CHANGELOG.md. Apache-2.0 is a permissive licence with an explicit patent grant, which is generally what a commercial deployment wants, but the licence covers the photon code and not the OpenStreetMap data you index, whose attribution requirements come from OpenStreetMap itself and are outside the scope of this README. That is a question for your own legal review, not something the repository answers.

The contribution policy is unusually specific and worth reading even if you never send a patch, because it tells you how the maintainers think about correctness. Pull requests containing AI-generated content, whether in code, in the PR description or in documentation, must mark those sections as such and must include proof that the generated code was run on an actual installation of photon. The README states that adding and executing tests is not sufficient; you have to show the code solves the problem the PR claims to solve. That is a higher evidentiary bar than most projects set.

The release history is regular, with 1.2.0, 1.2.1 and 1.3.0 appearing between June and August 2026, and the last push to the default branch was on 2026-09-23. For upgrade planning, the dump version coupling is the thing to watch: the README ties the database directory to your photon version, so a jar upgrade and a dump refresh are the same maintenance event. Check CHANGELOG.md before either. The README does not document a rollback procedure for a completed database swap, so keep the old directory until the new instance has been verified, which is what the documented sequence already tells you to do.

## Conclusion

Adopt photon if you need address and place lookup over OpenStreetMap data with location bias, tag filters and reverse geocoding, and you can give it SSD storage plus roughly 64GB of RAM for a planet-wide index. Do not adopt it if you only need occasional lookups, because the demo server at photon.komoot.io throttles heavy use and gives no availability guarantee, and do not adopt it if you need full geometry output, which the GraphHopper dumps do not support. Before committing, verify that the dump you download matches your photon version, that you have twice the database size free for atomic updates, and that bzip2 or pbzip2 is installed rather than WinRAR.

## FAQ

### How do I install komoot/photon and start the server?

Download a pre-built jar from the GitHub release page and unpack a database dump from download1.graphhopper.com/public, choosing the dump that matches your photon version. Then run java -jar photon-*.jar serve from the parent directory of photon_data; the webserver listens on http://localhost:2322.

### How do I use komoot/photon once it is running?

The server exposes the Photon API, documented in docs/api-v1.md, which covers search, reverse geocoding of a coordinate to an address, location bias, bounding-box filters and filtering by OSM tag and value. The README points to docs/usage.md for importing and updating a database.

### What are the system requirements for a self-hosted komoot/photon instance?

Photon requires Java 21 or newer, and OpenSearch 3.x if you run against an external database instead of the embedded server. A planet-wide database takes about 95GB of disk, with SSDs strongly recommended, and at least 64GB of RAM is recommended for smooth operation.

### Can I use the photon.komoot.io demo server in production?

The README says the API is welcome to be used as long as request volumes stay reasonable, that extensive usage will be throttled or banned, and that no availability guarantees are given and changes can happen without notice. For larger request volumes the README directs you to run a private instance.

### How do I update the komoot/photon database to a newer dump?

Download and unpack the new version, swap the directories so the new one replaces the old, restart photon and confirm it works, then delete the old database. The README warns that this requires twice the space of the database, and that unpacking in place of the old database will corrupt the data.

### Does komoot/photon return full geometry for a result?

The GraphHopper dumps do not support full geometry output, as the README states. If you need that feature you have to import your own database from a JSON dump, which brings in the additional Nominatim installation requirements.

## Sources

- [Issues](https://github.com/komoot/photon/issues)
- [komoot/photon on GitHub](https://github.com/komoot/photon)
- [License: Apache-2.0](https://github.com/komoot/photon/blob/master/LICENSE)
- [README](https://github.com/komoot/photon/blob/master/README.md)
- [Releases](https://github.com/komoot/photon/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/komoot-photon
