OSRM: six routing services over one C++ engine, and two preprocessing pipelines
Open Source Routing Machine - C++ backend
At a glance
- What is it?
- A routing engine written in C++ that runs on OpenStreetMap data and exposes nearest, route, table, match, trip and tile over three surfaces. Getting it running is a preprocessing step you wait for, and the argument you pass it is a base path rather than a file. The Node and Python bindings are pinned more narrowly than the engine is.
- Who is it for?
- It suits a team that wants predictable high speed routing from its own OpenStreetMap extract, with the matrix and matching services available over plain HTTP, and that is prepared to run a preprocessing pipeline before it serves a request. It does not suit someone who wants a hosted routing service or a map-matching product with an interface attached.
- Can I use it commercially?
- Yes. BSD-2-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 13, 2026, and from our analysis. They are not legal advice.
Star history
- Project-OSRM/osrm-backend8,216 ★ · +119
| Repository | 2026-09-22 | 2026-11-13 |
|---|---|---|
| Project-OSRM/osrm-backend | 8.1k | 8.2k |
119 Stars in the last 52 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Six services, three ways to reach them
The engine exposes a small set of services and is reachable three ways, which tells you what it is: a library with servers built on top. Nearest snaps a coordinate onto the street network and returns the closest matches. Route finds the fastest route between two coordinates. Table computes the duration or the distance of the fastest route between every pair of coordinates you supply. Match snaps a noisy GPS trace to the road network in the most plausible way. Trip solves the travelling salesman problem, and the readme is candid that it does so with a greedy heuristic rather than an exact solver. Tile generates vector tiles carrying routing metadata internally. All six are available over an HTTP API, through the C++ library interface, and through a Node wrapper, so the same engine can sit inside a service or inside your process.
Preprocessing is two pipelines and the choice is not cosmetic
Before the server answers anything, the extract has to be turned into a routing graph, and there are two ways to do it. Contraction hierarchies is one. Multi-level Dijkstra is the other, and it is the recommendation by default, with the stated exception of very large distance matrices, where contraction hierarchies remains the better fit for the time being. Switching is not a configuration flag on one tool, it is a different set of steps. For the recommended pipeline you run the partitioning step and then the customisation step; for the other you replace both with a single contraction step and pass a different algorithm option to the server.
docker run -t -i -p 5000:5000 -v "${PWD}:/data" ghcr.io/project-osrm/osrm-backend osrm-routed --algorithm mld /data/berlin-latest.osrmThe practical consequence is that your pipeline choice is baked into how your infrastructure is scripted, and changing it later means rewriting those steps.
The .osrm argument is a base path, not a file
One detail in the quick start is more of a trap than it looks. There is no file called berlin-latest.osrm. The server is passed that name, and what exists on disk is a set of files whose names begin with it, which is why the readme insists that the argument is a base path referring to several files rather than a path to one. There is also relief available: the suffix can be left off entirely, so the same step works with a shorter argument. If you have ever lost time wondering whether the preprocessing failed, or copied the wrong single file into a container, this is the explanation, and it is also why a mounted volume has to contain the whole set rather than one artefact.
Extraction is the slow step and the readme warns you
The preprocessing commands print very little while they work, and the readme calls that out with a concrete figure rather than a vague warning: a Mexican OpenStreetMap file of 550.7 megabytes took around half an hour to finish extraction and to generate the edge-expanded graph representation. That number is the one to plan against. It also explains the shape of the commands, which print a message on failure through `|| echo` rather than aborting a script.
wget http://download.geofabrik.de/europe/germany/berlin-latest.osm.pbfThe mount flag is explained in the same paragraph, and the explanation is worth keeping in mind: the container path refers to a file inside the container, and the host directory is the current working directory you mounted at that path. Once the graph exists, a first request looks like an ordinary HTTP call against the routing endpoint.
Five image tags, two of which exist to be debugged
The container registry table is short and the differences are the whole point. The default tag is the development branch compiled with the release flag, which is not what the phrase release tag usually implies elsewhere. There is a tag built from the development branch with the release flag but with assertions enabled and debug symbols kept, and another built with the debug flag. Then a specific tag gives you that tag compiled with the release flag, with a matching debug variant. So the axis is not version alone, it is version times build configuration. The assertions build is the interesting one for an operator, because assertions turn a silent arithmetic overflow into a crash rather than a wrong answer, and it is worth running that way when a route result looks wrong and you cannot tell whether the bug is in the graph or in your own code.
Building from source is a package manager, a compiler standard and a manifest
Dependencies are managed with vcpkg in manifest mode, which means the dependency list lives in the repository rather than on your machine. The stated Linux tooling is deliberately minimal: a C++20 compiler, CMake at 3.29 or newer, Ninja, and a handful of autotools packages that some ports need in order to bootstrap themselves.
sudo apt install build-essential git cmake ninja-build pkg-config \
autoconf automake libtool curl zip unzip tarYou bootstrap vcpkg once anywhere on the machine and point an environment variable at it. The tree carries the manifest, a configuration file and an overlay ports directory, and that last one is the interesting escape hatch: an overlay lets you patch or replace a single dependency locally without forking the project. The build is driven by CMake with a presets file, and the test layout separates integration tests, unit tests and a fuzzing directory.
The bindings are version-pinned more tightly than the engine
The engine releases monthly, with tags following the calendar, and the last three releases in the repository are all within a couple of months. The bindings are narrower. The Node package declares its supported runtimes as two ranges with a gap in the middle, installs through a prebuilt binary fetcher with a shell fallback when no binary exists, and runs its tests through a shell script that drives a matrix, plus a separate path that builds a native binding and pipes results through a reporter. The Python side requires 3.10 or newer, builds through the scikit build backend with nanobind, and configures its wheels for cp312, with wheel.py-api = "cp312" and build = "cp312-*". It also skips musllinux entirely, and its manylinux container images are pulled from a personal account rather than the project's, with a comment asking whether that should move into the project organisation.
Three sibling repositories carry the parts you would otherwise build
The backend on its own does not draw a map or speak to a person, and the project says so by pointing at three sibling repositories. One is the user-facing frontend with a map, which is what the public demo server runs on top of this engine, so the demo is a fair picture of the whole stack rather than of the backend alone. The second turns a route response into text instructions, which is the part that turns a polyline into something a driver can follow. The third is where the ready-to-use container images live, with older backend versions kept on Docker Hub. Documentation is split the same way, with a hosted site for the general material and the routing daemon's HTTP API reference kept inside this repository. Two reading suggestions are offered for anyone new: the OpenStreetMap wiki page on routing for how the road network is represented, and a mapping guide for navigation that is linked through a web archive snapshot, which is a small hint that the second of those has not moved in a while. Support is community funded, through patches, issue triage, reviews, and two donation routes.
Editorial conclusion
It suits a team that wants predictable high speed routing from its own OpenStreetMap extract, with the matrix and matching services available over plain HTTP, and that is prepared to run a preprocessing pipeline before it serves a request. It does not suit someone who wants a hosted routing service or a map-matching product with an interface attached. Check four things before you commit: which pipeline you need, because the contraction hierarchy is the better fit only for very large distance matrices, how long preprocessing takes against your extract size, whether your Python is a version the published wheel targets, since the wheel is configured for cp312 and requires-python is >=3.10, and whether you want the release image or an assertions build, because the default image is built from the development branch.
Frequently asked questions
What does OSRM do?
OSRM is a high performance routing engine written in C++ designed to run on OpenStreetMap data. It exposes six services: snapping coordinates to the network, finding the fastest route, computing a duration or distance matrix, matching noisy traces, solving the travelling salesman problem with a greedy heuristic, and generating vector tiles with routing metadata.
Is OSRM an API?
It is an engine with three surfaces rather than a single API. The same six services are reachable over an HTTP API served by the routing daemon, through the C++ library interface, and through a Node wrapper, and the HTTP API documentation for the daemon is kept in the repository alongside the hosted documentation.
How do I set up OSRM?
The readme calls the provided Docker images the quickest route. Download an OpenStreetMap extract, run the extraction step with a profile, then the partitioning and customisation steps for the recommended pipeline, or a single contraction step if you use the other, then start the routing daemon and optionally the frontend on its own port.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/project-osrm-osrm-backend)Star history chart for your README
[](https://hysenlabs.com/projects/project-osrm-osrm-backend)Was this useful?