Guide

Overpass speed: overpass-rust and Overpass API compared

overpass.ch answers queries on current data with overpass-rust, a reimplementation of the Overpass API in Rust. In a test on the queries of our customers, it was typically 84 times faster than Overpass API 0.7.62.11 on the same hardware for answers under 100 KB, and 14 times faster in total time.

On this page, “C++” means Overpass API, the software of the public Overpass servers, and “Rust” means overpass-rust. Rust gives the same answers as C++, so Overpass Turbo, QGIS, OSMnx and other clients work with it unchanged. History queries run on C++.

The test

The test ran on an AMD Ryzen 9 3900 with 128 GB of RAM and NVMe disks, with Rust and C++ on the same machine and the same planet data, kept current with minutely diffs. It used the queries of our customers. After Rust answered a query, the same query was sent to C++, at most two at a time and within 5 minutes, and the two answers were compared. Only queries with identical answers count. Both sides were timed until the last byte of the answer; for Rust, the time spent waiting for the client is left out.

Queries from 11 November 2026, 05:34, to 12 November, 06:00 UTC:

Median95th percentile99th percentile
C++295 ms6.8 s20.5 s
Rust4 ms0.22 s2.6 s
Compared query by query, C++ took 56 times as long as Rust at the median, 11 times at the 10th percentile and 689 times at the 90th. For answers under 100 KB the median was 84 times. Over all queries C++ needed 14 times the total time, and Rust was faster on 99.96% of them.

C++ was timed on a replay, while the machine had other load. The two servers do not share files, so the replay does not profit from the Rust run. The C++ database also holds 341 GiB of attic data for history queries.

The figures move with the mix of queries. In the night of 12 November, with more heavy area queries, the same method gives a median of 58 times for answers under 100 KB and 9 times in total.

Why Rust is faster

C++ starts a new process for each request, and that process registers with the dispatcher before it reads any data. In the test, the quickest C++ answers took about 50 ms. Rust answers every query inside one server process that reads a memory-mapped LMDB file. Each query gets its own snapshot while a single writer applies the diffs, and the quickest answers took less than 1 ms.

The database is less than half the size. Elements are packed into lz4-compressed chunks of up to 16 KiB, with coordinates stored column by column and a tag dictionary in each chunk, and the indexes are delta-coded. The planet with metadata and areas takes 190 GiB in Rust and 428 GiB in C++, attic data not counted. With 128 GB of RAM, this decides whether the parts of the database in use stay in the page cache or are read from disk.

Data is sorted by spatial cell and then by id, and the tag index points to cell and id, so the elements found through a tag are read in the order they lie on disk. Every way and relation keeps its bounding box. For (bbox), around, poly and areas the box settles most cases without loading node coordinates, and out center and out bb come straight from it.

A planner picks where each statement starts (ids, an input set, the tag index or spatial cells, whichever is cheapest) and begins with the most selective filter. Tags are checked before an element is decoded. An area is turned into ranges of cells, and only those cells are read. Decoding, geometry tests, output and scans of the tag index run on up to 8 threads within one query, where C++ uses one thread per query.

Why the gap grows with the data

DataMeasureRust faster by
Synthetic, 640,000 nodes, one process per query17 queries, total2.5×
Luxembourg, 4.9 million elementsTypical queries1.8× to 17×
Germany, 515 million elements, both in RAM212 queries, total (geometric mean)3.7× (12×)
Planet, customer queriesTotal (median)14× (56×)

On small data, most of the time goes into starting a process and parsing the query, on both sides. On large data it goes into reading indexes and data. On the planet the C++ database for current data is more than three times the size of the RAM, so many C++ queries wait for the disk. The rows use different queries and compare only roughly.

The Germany run used the Geofabrik extract of 1 November 2026 with metadata, on a Xeon E3-1275 v5 with 8 threads, 64 GB of RAM and NVMe. C++ ran as the wiktorn/overpass-api:v0.7.62.11 image, and both servers were queried over HTTP.

C++Rust
Import with metadata90 min17.5 min
Database28 GB9.8 GB
60 minutely planet diffs97 s7.9 s
212 hand-written queries, warm, sum of medians393 s106 s
500 generated multi-statement queries (foreach, for, make, if)775 s49 s
Throughput, 8 clients, queries under 2 s13.7 q/s56.5 q/s

Same answers

The semantics of Rust follow specifications extracted from the C++ sources. Where C++ behaviour shows in the output, as with number formatting, iteration order or area geometry, it is ported. Of 598 test queries over ten datasets, 528 give byte-identical output and 41 are rejected by both with the same error. 12 depend on timing. The other 17 differ on purpose, for example where C++ keeps stale state after a node changes. On the Germany extract, the answers stayed identical through 36 hours of diffs, except where the C++ database itself became inconsistent.

Source code

overpass-rust is open source under the GNU Affero General Public License, on GitHub, with a changelog of the releases. It is based on Overpass API by Roland Olbricht et al.

Switching to overpass.ch

Queries, libraries and tools work unchanged. Only the server URL changes:

https://overpass-api.de/api/interpreter
→ https://api.overpass.ch/v1/YOUR_API_KEY/interpreter

The documentation shows the setting for Overpass Turbo, JOSM, QGIS, Python, R and JavaScript.