Localhost will always have port 8080.
For Great Britain (full dataset):
- Allocate at least 16 GB of memory and 2–4 CPUs.
- Setup will take approximately 30 minutes – 1 hour.
For smaller regions:
- Allocate approximately 6–8 GB of memory and 1–2 CPUs.
- Setup should take anywhere between 30 seconds – 5 minutes.
This deployment runs a self-hosted instance of OpenRouteService (v9.9.0) using a local Docker container to provide high-performance spatial routing (distance matrix and travel duration calculations).
- Data Locality: All spatial computing, road graph parsing, and routing queries must happen entirely on-device (local host loops).
- Zero External Dependencies: To comply with standard regulatory network constraints, no external third-party routing APIs (e.g., public OSRM/ORS servers) or remote cloud storage components may be integrated into production code blocks.
- Storage Strictness: Due to virtualization layers on macOS, the runtime directory must execute out of a strictly local, non-cloud-synced volume space (e.g., internal storage subfolders such as
~/Desktopor$HOME). Shared environments synced with iCloud Drive or Google Drive virtual filesystems are structurally prohibited due to file system lock contention and metadata eviction behavior during runtime.
The workspace root folder (RLDatix) must maintain the following file and directory composition:
~/Desktop/RLDatix/
├── docker-compose.yml # Main container configuration specification
├── ors-data/ # Host mounted directory for immutable geodata maps
│ └── great-britain-latest.osm.pbf # Immutable OpenStreetMap road network data file
└── ors-conf/ # Host configuration workspace folder
└── ors-config.yml # Primary YAML configuration file for ORS engine profile parameters
This manifest defines the resource layer and strict storage attachments for the container engine.
services:
openrouteservice:
image: openrouteservice/openrouteservice:latest
container_name: openrouteservice
restart: unless-stopped
ports:
- "8082:8082"
environment:
# Memory allocation tuned for large geographic graphs (e.g., Great Britain)
- JAVA_OPTS=-Xms2g -Xmx8g
# Points the container context explicitly to our mounted YAML properties file
- ORS_CONFIG_LOCATION=/home/ors/config/ors-config.yml
volumes:
# Map our host spatial data directory to the standard interior files lanes
- ./ors-data:/home/ors/files
# Map the host configuration path to the engine runtime environment target
- ./ors-conf:/home/ors/configIn ORS v9+, engine specifications must explicitly declare active routing profiles via a structured YAML profile schema to prevent immediate boot loop abort sequences (No profiles configured. Exiting).
ors:
engine:
# Source file coordinate web path inside the container environment
source_file: /home/ors/files/great-britain-latest.osm.pbf
# Target workspace folder where index tables are written and maintained
graphs_root_path: /home/ors/files/graphs
profiles:
active:
- driving-carTo ensure full compliance with regulatory parameters and lock down your spatial data locality, the Great Britain road network map data must be downloaded cleanly from a verified local source directly into your on-device folder.
Because you are working completely offline/locally on your Desktop, you must explicitly provision this file before launching your container.
Open your terminal and ensure you are working from your strictly local Desktop project folder, and that the target data folder exists:
cd ~/Desktop/RLDatix
mkdir -p ors-dataThe recommended provider for clean, open-source country-level road network data files is Geofabrik.
Option A: Download via Terminal (Recommended)
Run this command from your RLDatix directory. It uses flags (-L to follow redirects, and -C - to automatically resume the download if your connection drops):
curl -L -C - -o ./ors-data/great-britain-latest.osm.pbf https://download.geofabrik.de/europe/great-britain-latest.osm.pbfOption B: Download via Web Browser
- Open your browser and navigate to: https://download.geofabrik.de/europe/great-britain.html
- Click on the link for
great-britain-latest.osm.pbf(usually around 1.5 GB to 2.5 GB). - Once the download completes, open Finder and move the file out of your Downloads folder into:
~/Desktop/RLDatix/ors-data/
CRITICAL: Ensure the file is named exactly
great-britain-latest.osm.pbf. Remove any suffixes like-1or.downloadadded by your browser.
Before spinning up your Docker infrastructure, confirm that the file is sitting in the correct location:
ls -lh ./ors-data/You should see great-britain-latest.osm.pbf listed with a non-zero file size matching the download specifications.
Because compiling the spatial matrix for a dense geographic footprint like Great Britain is a heavy transactional process, the engine must build its index blocks completely without interruption.
To ensure clean state conformity, any partial or corrupt index tables must be systematically purged before initialization:
cd ~/Desktop/RLDatix
docker compose down
# Obliterate any previous graph folders completely
rm -rf ./ors-data/graphs
rm -rf ./ors-graphsVerify that the great-britain-latest.osm.pbf file has been fully downloaded and sits cleanly in your internal host storage location:
ls -la ./ors-data/Execute the container initialization detached from the current terminal thread:
docker compose up -dMonitor the active compilation blocks of the road indexing hierarchy. The processing window requires between 15 to 45 minutes to map out the physical intersections:
docker compose logs -f openrouteserviceThe stack will appear to rest on the line start creating graph from... while indexing millions of intersections. This behavior is normal and represents active compilation cycles. Leave it completely uninterrupted until it outputs the garbage collection tables and announces a successful start.
Once processing terminates, the application manager will announce a successful initialization status block. System operators can track system health from the terminal or a standard web client.
Open a web browser or run a shell query against the container's health route:
curl http://localhost:8082/ors/v2/healthExpected Healthy JSON Response:
{
"status": "ready"
}Note: If the application returns a
404 Page Not Founderror at the root URL (http://localhost:8082/), port mapping is working normally — you must point explicitly to/ors/v2/healthor/ors/health.
Ensure that any downstream components (such as postcode-api.py or your local data connector pipelines) route their HTTP traffic to the following base configurations:
- Target Routing Base URL:
http://127.0.0.1:8082/ors - Default Mode:
driving-car
The following GitHub Actions workflow (build-locroute.yml) automates the full build and validation cycle for the LocRoute-GB engine. It triggers on pushes and pull requests to main/master, and can also be run manually from the GitHub Actions tab.
name: Build and Validate LocRoute-GB Engine
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
workflow_dispatch: # Allows manual execution from the GitHub Actions tab
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository Code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Create Workspace Folder Matrix
run: |
mkdir -p ors-data
mkdir -p ors-graphs
- name: Download Great Britain OSM PBF File
run: |
echo "Starting secure network retrieval of GB extract..."
curl -L -C - -o ./ors-data/great-britain-latest.osm.pbf https://download.geofabrik.de/europe/great-britain-latest.osm.pbf
echo "Verifying local geodata file asset locality:"
ls -lh ./ors-data/great-britain-latest.osm.pbf
- name: Generate Inline Docker Compose Manifest
run: |
cat << 'EOF' > docker-compose.yml
services:
openrouteservice:
image: openrouteservice/openrouteservice:latest
container_name: openrouteservice
ports:
- "8082:8082"
environment:
- JAVA_OPTS=-Xms2g -Xmx4g
- ORS_ENGINE_PROFILES_ACTIVE_0=driving-car
- ORS_ENGINE_SOURCE_FILE=/home/ors/files/great-britain-latest.osm.pbf
- ORS_ENGINE_GRAPHS_ROOT_PATH=/home/ors/graphs
volumes:
- ./ors-data:/home/ors/files
- ./ors-graphs:/home/ors/graphs
EOF
- name: Instantiate Container and Trigger Graph Compilation
run: |
echo "Starting LocRoute-GB Engine Service Layers..."
docker compose up -d
echo "Streaming active network calculations. Monitoring thread allocation..."
# Tail logs for up to 3 minutes to verify successful startup hook or graph initialization
timeout 180 docker compose logs -f openrouteservice || true
- name: Assert Health API Status Compliance
run: |
echo "Querying local routing layer endpoint controls..."
# Due to compilation times for the whole UK, the engine may initially state "loading" or "ready"
# This step verifies the web server port 8082 is actively responding instead of 404/Connection Refused.
RESPONSE=$(curl --silent --fail http://localhost:8082/ors/v2/health || echo "FAIL")
echo "Engine Health Metrics: $RESPONSE"
if [ "$RESPONSE" = "FAIL" ]; then
echo "Error: The LocRoute port endpoint failed to respond cleanly."
exit 1
fiFastAPI service for postcode geocoding and distance calculation with optional Redis caching.
- Geocode endpoint:
GET /geocodeandPOST /geocode - Distance endpoint:
GET /distanceandPOST /distance - Dark-mode Swagger UI:
GET /docs - OpenAPI schema endpoint:
GET /openapi.json - File-based OpenAPI schema:
docs/openapi.json - Optional Redis-backed distance cache (enabled in current
docker-compose.yml)
docker compose up -d --buildAPI will be available at:
http://localhost:8080- Swagger:
http://localhost:8080/docs - OpenAPI JSON:
http://localhost:8080/openapi.json
The app caches known distance responses using a key derived from:
- from postcode + country
- to postcode + country
- mode
- speed (if supplied)
See docs/CACHING.md for details, including how to disable caching.
pytest -qCI also runs this command in .github/workflows/ci.yml.
stress_test_100_requests.py currently generates 100 unique route pairs in one run.
That is useful for coverage, but it does not maximize cache hits.
To observe cache speedups, repeat the same request set (or same routes) after a warm-up run.
The distance API supports Redis caching to speed up repeated lookups for known routes.
Caching is applied inside the distance calculation flow in app/main.py.
- Cache read happens before routing/geocoding work.
- Cache write happens after a successful distance result.
- Cached values are JSON payloads that match the
/distanceresponse structure.
Cache key includes:
- origin postcode and country
- destination postcode and country
- mode
- speed (or
none)
REDIS_URL- Example:
redis://redis:6379/0 - If missing, cache is disabled.
- Example:
REDIS_CACHE_TTL_SECONDS- Default:
86400
- Default:
docker-compose.yml currently enables Redis by default:
postcode-apihasREDIS_URLandREDIS_CACHE_TTL_SECONDSredisservice is included (redis:7-alpine)
To disable cache while keeping the rest of the API working:
- Remove
REDIS_URLfrompostcode-apienvironment indocker-compose.yml. - Recreate service:
docker compose up -d --build postcode-apiOptional full Redis removal:
- Remove
depends_on: redisfrompostcode-api. - Remove the
redisservice block. - Run:
docker compose up -d --build
docker compose down --remove-orphansA single run with only unique routes will not show much cache benefit.
Recommended pattern:
- Flush cache (cold start):
docker compose exec -T redis redis-cli FLUSHDB- Run test set once (cold).
- Run the same test set again (warm).
- Compare average latency between runs.
Expected behavior:
- cold run includes geocoding + routing cost
- warm run returns known routes much faster from Redis