# Migrate from a self-hosted Pelias or Photon to geolith

> geolith accepts the same parameters as Pelias: /v1/search, /v1/autocomplete, /v1/reverse, /v1/search/structured and /v1/place with text, size, layers, boundary.country and focus.point.*. Point your Pelias client at https://api.geolith.app and add a key. From Photon, map /api?q= to /v1/search?text=. On the India benchmark (20 Oct 2026) geolith scored 82.5 % on autocomplete against 42.5 % for Photon and 32.5 % for Pelias, from one 543 MB file with no OpenSearch.

## Request mapping

| self-hosted Pelias or Photon | geolith | Note |
| --- | --- | --- |
| `Pelias GET /v1/search?text=…` | `GET /v1/search?text=…` | Same. |
| `Pelias GET /v1/autocomplete?text=…` | `GET /v1/autocomplete?text=…` | Same. |
| `Pelias GET /v1/reverse?point.lat=…&point.lon=…` | `GET /v1/reverse?point.lat=…&point.lon=…` | Same. |
| `Pelias size, layers, boundary.country, focus.point.*` | `Same names` | size up to 40. |
| `Pelias sources=osm,oa,wof` | `Not used` | One source: geolith. |
| `Pelias boundary.rect.* on search` | `Not supported` | Use boundary.country or a focus point. |
| `Photon GET /api?q=…` | `GET /v1/search?text=… or /v1/autocomplete?text=…` |  |
| `Photon lat=…&lon=… (bias)` | `focus.point.lat=…&focus.point.lon=…` |  |
| `Photon limit=…` | `size=…` |  |
| `Photon lang=…` | `lang=…` | Self-hosted server; hosted API planned. |
| `Photon osm_tag=amenity:cafe` | `categories=food or categories=cafe` | Self-hosted server; hosted API planned. |
| `Photon GET /reverse?lat=…&lon=…` | `GET /v1/reverse?point.lat=…&point.lon=…` |  |

## Response mapping

| self-hosted Pelias or Photon | geolith | Note |
| --- | --- | --- |
| `Pelias features[].properties.label` | `features[].properties.label` | Same. |
| `Pelias properties.gid (osm:venue:node/1)` | `properties.gid (geolith:venue:<id>)` | Re-fetch stored gids once. |
| `Pelias properties.confidence, distance` | `properties.confidence, distance` | Same names. |
| `Photon properties.name` | `properties.name` |  |
| `Photon properties.city` | `properties.locality` |  |
| `Photon properties.state` | `properties.region` |  |
| `Photon properties.postcode` | `properties.postalcode` |  |
| `Photon properties.countrycode` | `properties.country_code` |  |
| `Photon properties.extent` | `feature bbox` |  |

## Before and after

Before: self-hosted Pelias:

```js
const url = new URL('http://pelias.internal:4000/v1/autocomplete');
url.searchParams.set('text', 'shaniwar wa');
url.searchParams.set('focus.point.lat', '18.5204');
url.searchParams.set('focus.point.lon', '73.8567');
url.searchParams.set('sources', 'osm,oa');
const { features } = await (await fetch(url)).json();
```

After: geolith:

```js
const url = new URL('https://api.geolith.app/v1/autocomplete');
url.searchParams.set('text', 'shaniwar wa');
url.searchParams.set('focus.point.lat', '18.5204');
url.searchParams.set('focus.point.lon', '73.8567');
url.searchParams.set('api_key', GEOLITH_PUBLISHABLE_KEY);
const { features } = await (await fetch(url)).json();
```

## Hosted or self-hosted

Use the hosted API at api.geolith.app, or keep running it yourself. A self-hosted geolith is one Rust binary and one static .glx file answered by HTTP range reads: no OpenSearch, no libpostal, no placeholder or point-in-polygon services.

- India benchmark, same machine: geolith 543 MB, one file; Pelias 1.0 GB plus supporting services; Photon 810 MB.
- Feature probes: geolith 24 of 25, Photon 19, Pelias 16.
- Errors keep the Pelias shape: an empty FeatureCollection with geocoding.errors.

## Questions

### Will my Pelias client library work?

Usually yes for search, autocomplete, reverse, structured and place: geolith accepts the same parameters as Pelias and returns the same GeoJSON shape. Add the API key and drop sources=.

### Can I keep self-hosting?

Yes. geolith runs from one static .glx file with no database. See the self-hosting cost page and the docs.

Get a free API key (100,000 requests a month): https://console.geolith.app/signup
