Skip to content

Deploying GraphHopper

Introduction

GraphHopper is a fast and memory-efficient open-source routing engine that calculates routes, distances, travel times, and turn-by-turn instructions using OpenStreetMap data. Whether you need point-to-point routing, isochrone calculations, or mobile navigation, GraphHopper provides the foundation for building your own self-hosted mapping and navigation services.

Built in Java for cross-platform compatibility and performance, GraphHopper supports multiple transportation modes including car, bike, foot, and public transit. The engine can be used as a Java library or deployed as a standalone web server with a beautiful web interface.

Key highlights of GraphHopper:

  • Fast Routing: Calculate routes in milliseconds, even for long distances
  • Memory Efficient: Optimized data structures for minimal RAM usage
  • Multiple Profiles: Support for car, bike, foot, motorcycle, and custom profiles
  • Turn-by-Turn Instructions: Detailed navigation instructions for mobile apps
  • Isochrone Calculation: Find areas reachable within a given time
  • Snap to Road: Match GPS traces to the road network
  • GTFS Support: Integrate public transit data
  • Custom Models: Define custom routing behavior and road preferences
  • Web Interface: GraphHopper Maps for visual route planning
  • 100% Open Source: Licensed under Apache 2.0

This guide walks through deploying GraphHopper on Klutch.sh using Docker, importing OpenStreetMap data, and setting up your own routing API.

Why Deploy GraphHopper on Klutch.sh

Deploying GraphHopper on Klutch.sh provides several advantages for routing services:

Simplified Deployment: Klutch.sh automatically detects your Dockerfile and builds GraphHopper without complex orchestration. Push to GitHub and your routing server deploys automatically.

Persistent Storage: Attach persistent volumes for your map data and routing graphs. Pre-processed data survives container restarts.

HTTPS by Default: Klutch.sh provides automatic SSL certificates for secure API access.

GitHub Integration: Connect your configuration repository directly from GitHub. Updates trigger automatic redeployments.

Scalable Resources: Allocate CPU and memory based on your map coverage and expected query volume.

Custom Domains: Assign a custom domain for your routing API.

Always-On Availability: Your routing service remains accessible 24/7.

Prerequisites

Before deploying GraphHopper on Klutch.sh, ensure you have:

  • A Klutch.sh account
  • A GitHub account with a repository for your GraphHopper configuration
  • OpenStreetMap data for your region (PBF format)
  • Basic familiarity with Docker and containerization concepts
  • Understanding of your geographic coverage needs

Understanding GraphHopper Architecture

GraphHopper consists of several components:

Routing Engine: Core Java engine that calculates optimal routes.

Graph Storage: Pre-processed road network stored as a graph structure.

Web Server: Jetty-based HTTP server exposing the routing API.

Web Interface: GraphHopper Maps for visual route planning and testing.

Import Process: Converts OSM data into an optimized routing graph.

Preparing Your Repository

To deploy GraphHopper on Klutch.sh, create a GitHub repository containing your Dockerfile and configuration.

Repository Structure

graphhopper-deploy/
├── Dockerfile
├── config.yml
├── README.md
└── .dockerignore

Creating the Dockerfile

Create a Dockerfile in the root of your repository:

FROM ghcr.io/graphhopper/graphhopper:latest
# Copy configuration file
COPY config.yml /graphhopper/config.yml
# Set working directory
WORKDIR /graphhopper
# Create data directory
RUN mkdir -p /graphhopper/data
# Expose the web interface port
EXPOSE 8989
# Default command
CMD ["java", "-Xmx2g", "-Xms1g", "-jar", "graphhopper.jar", "server", "config.yml"]

Advanced Dockerfile with Custom Memory Settings

For larger map coverage:

FROM ghcr.io/graphhopper/graphhopper:latest
# Copy configuration
COPY config.yml /graphhopper/config.yml
WORKDIR /graphhopper
# Create data directory
RUN mkdir -p /graphhopper/data
# Set Java options via environment
ENV JAVA_OPTS="-Xmx4g -Xms2g -XX:+UseG1GC"
# Health check
HEALTHCHECK --interval=60s --timeout=10s --start-period=300s --retries=3 \
CMD curl -f http://localhost:8989/health || exit 1
EXPOSE 8989
CMD ["sh", "-c", "java ${JAVA_OPTS} -jar graphhopper.jar server config.yml"]

Creating the config.yml File

Create a GraphHopper configuration file:

graphhopper:
# Data directory for graph storage
graph.location: /graphhopper/data/graph-cache
# OSM file to import
datareader.file: /graphhopper/data/region.osm.pbf
# Profiles for different transportation modes
profiles:
- name: car
vehicle: car
weighting: fastest
turn_costs: true
- name: bike
vehicle: bike
weighting: fastest
- name: foot
vehicle: foot
weighting: shortest
# Enable CH (Contraction Hierarchies) for fast queries
profiles_ch:
- profile: car
# Enable LM (Landmarks) for flexible queries
profiles_lm:
- profile: car
- profile: bike
- profile: foot
# Server configuration
server:
application_connectors:
- type: http
port: 8989
bind_host: 0.0.0.0
admin_connectors:
- type: http
port: 8990
bind_host: localhost
# Import settings
import:
osm:
ignored_highways: footway, cycleway, path, pedestrian, steps

Creating the .dockerignore File

Create a .dockerignore file:

.git
.github
*.md
README.md
LICENSE
.gitignore
*.log
.DS_Store
*.pbf
graph-cache/

Configuration Options Reference

OptionDescription
graph.locationDirectory for the routing graph
datareader.filePath to OSM PBF file
profilesAvailable routing profiles
profiles_chProfiles with Contraction Hierarchies
profiles_lmProfiles with Landmarks
server.portHTTP port for API

Deploying GraphHopper on Klutch.sh

Once your repository is prepared, follow these steps to deploy GraphHopper:

    Download OpenStreetMap Data

    Download OSM data for your region from Geofabrik:

    Terminal window
    # Example: Download data for a small region
    wget https://download.geofabrik.de/europe/monaco-latest.osm.pbf

    Choose a region appropriate for your needs. Larger regions require more memory and storage.

    Push Your Repository to GitHub

    Initialize your repository and push to GitHub:

    Terminal window
    git init
    git add Dockerfile config.yml .dockerignore README.md
    git commit -m "Initial GraphHopper deployment configuration"
    git remote add origin https://github.com/yourusername/graphhopper-deploy.git
    git push -u origin main

    Create a New Project on Klutch.sh

    Navigate to the Klutch.sh dashboard and create a new project. Give it a descriptive name like “graphhopper” or “routing-engine”.

    Create a New App

    Within your project, create a new app. Connect your GitHub account if you haven’t already, then select the repository containing your GraphHopper Dockerfile.

    Configure HTTP Traffic

    GraphHopper serves its API over HTTP. In the deployment settings:

    • Select HTTP as the traffic type
    • Set the internal port to 8989

    Attach Persistent Volumes

    Persistent storage is essential for GraphHopper. Add the following volume:

    Mount PathRecommended SizePurpose
    /graphhopper/data20+ GBOSM data and routing graph cache

    Size depends on your region. Small country: 5-10 GB. Large country: 50+ GB.

    Deploy Your Application

    Click Deploy to start the build process. Klutch.sh will:

    • Detect your Dockerfile automatically
    • Build the container image
    • Attach the persistent volumes
    • Start the GraphHopper container
    • Provision an HTTPS certificate

    Upload OSM Data

    After deployment, upload your OSM PBF file to the persistent volume at /graphhopper/data/region.osm.pbf.

    Import the Data

    GraphHopper will automatically import the data on first startup. This can take from minutes to hours depending on region size. Check logs for progress.

    Access GraphHopper

    Once import completes, access your GraphHopper instance at https://your-app-name.klutch.sh. The GraphHopper Maps interface allows visual route planning.

Using the Routing API

Basic Route Request

Calculate a route between two points:

Terminal window
curl "https://your-app-name.klutch.sh/route?point=52.5170,13.3889&point=52.5205,13.4094&profile=car"

Route Response

The API returns JSON with route details:

{
"paths": [{
"distance": 1234.5,
"time": 180000,
"points": { ... },
"instructions": [
{
"text": "Turn right onto Main Street",
"distance": 100,
"time": 12000
}
]
}]
}

API Endpoints

EndpointDescription
/routeCalculate route between points
/isochroneCalculate reachable area
/matchMatch GPS trace to roads
/matrixCalculate distance matrix
/healthHealth check endpoint

Route Parameters

ParameterDescription
pointCoordinates (lat,lon). Repeat for multiple waypoints
profileRouting profile (car, bike, foot)
localeLanguage for instructions
instructionsInclude turn-by-turn instructions
points_encodedUse polyline encoding
typeResponse format (json, gpx)

Isochrone Request

Calculate areas reachable within a time limit:

Terminal window
curl "https://your-app-name.klutch.sh/isochrone?point=52.5170,13.3889&profile=car&time_limit=600"

Customizing Routing Profiles

Creating Custom Profiles

Define custom routing behavior in config.yml:

profiles:
- name: truck
vehicle: car
weighting: fastest
turn_costs: true
custom_models:
truck:
speed:
- if: road_class == PRIMARY
multiply_by: 0.8
- if: road_class == SECONDARY
multiply_by: 0.7
priority:
- if: max_weight < 7.5
multiply_by: 0

Profile Options

OptionDescription
vehicleBase vehicle type (car, bike, foot)
weightingOptimization target (fastest, shortest)
turn_costsConsider turn restrictions
custom_modelApply custom routing rules

Performance Optimization

Memory Configuration

Adjust Java heap size based on your region:

Region SizeRecommended Heap
City1-2 GB
Small country2-4 GB
Large country4-8 GB
Continent8+ GB

Contraction Hierarchies (CH)

Enable CH for fastest query performance:

profiles_ch:
- profile: car

CH pre-calculates shortcuts, reducing query time from seconds to milliseconds.

Landmarks (LM)

Enable LM for flexible queries with custom models:

profiles_lm:
- profile: car

LM allows runtime customization while maintaining reasonable performance.

Troubleshooting Common Issues

Import Takes Too Long

Symptoms: Data import runs for hours.

Solutions:

  • Use a smaller region for testing
  • Increase Java heap size
  • Verify disk I/O performance
  • Check for sufficient disk space

Out of Memory Errors

Symptoms: Application crashes with OOM errors.

Solutions:

  • Increase Java heap size in Dockerfile
  • Use a smaller region
  • Enable disk-based storage with graph.dataaccess=MMAP

Routing Fails for Some Points

Symptoms: Some coordinates return no route.

Solutions:

  • Verify points are within the imported region
  • Check that roads exist near the coordinates
  • Try snapping to nearest road first
  • Verify the profile supports the road types

Web Interface Not Loading

Symptoms: API works but maps don’t display.

Solutions:

  • Check browser console for errors
  • Verify HTTPS is working
  • Clear browser cache
  • Try a different browser

Additional Resources

Conclusion

Deploying GraphHopper on Klutch.sh gives you a powerful, self-hosted routing engine with full control over your map data. The combination of GraphHopper’s performance and Klutch.sh’s deployment simplicity means you can build navigation services without depending on third-party APIs.

With support for multiple transportation modes, isochrone calculations, and customizable routing profiles, GraphHopper provides the foundation for logistics applications, mobile navigation, and location-based services. Whether you’re building a delivery routing system or adding navigation to your mobile app, GraphHopper on Klutch.sh delivers fast, reliable routing on your infrastructure.