This solution accelerator now has a staged 0 / 1 / 2a / 2b story:
- a small serverless introduction on repo-local coordinate data
- address preprocessing plus Photon geocoding
- CPU routing with OSRM + OR-Tools
- GPU routing with a sparse graph + cuOpt
The main accelerator still starts with local address data, geocodes those addresses to latitude/longitude with Photon, and then routes them with either a CPU or GPU solver.
The default sample is vendored into the repo, so the input data path works without any runtime download from Overture. The only heavyweight setup-time downloads are the Photon index and the Indiana OSRM graph assets.
- AWS
devtarget via theDEFAULTDatabricks CLI profile. - Azure
azuretarget via a caller-supplied Databricks CLI profile, for example:databricks bundle deploy -t azure --profile <your-azure-profile>. - Azure classic-cluster defaults validated in an internal Azure test workspace:
- asset prep / CPU OSRM / CPU optimize:
Standard_D16ds_v5 - geocode + service validation:
Standard_D32ds_v5
- asset prep / CPU OSRM / CPU optimize:
- GPU optimization now runs on serverless GPU with
GPU_1xA10in the bundle. - The serverless GPU notebooks install
cuopt-cu12==25.8.0in-notebook because scheduled serverless GPU jobs do not support bundle-managed dependency lists.
0-introduction/Fast serverless-first learning path that usesutils/shipments.csvplus synthetic haversine travel times to validate CPU and GPU routing without Photon or OSRM.1-preprocessing-geocoding/Builds Photon + OSRM assets, validates executor-local services, then uses a split serverless/classic flow to materializedemos.routing.raw_shipments.2a-cpu-route-optimization/Uses a split serverless/classic CPU flow for clustering and OSRM prep, then Ray + OR-Tools on classic compute to writedemos.routing.optimized_routes.2b-gpu-route-optimization/Uses a split serverless/classic GPU prep flow plus cuOpt on serverless GPU to writedemos.routing.optimized_routes_gpu_10000.data/Contains the vendored Overture-derived address sample and the refresh script used to regenerate it.utils/shipments.csvExplicit coordinates-only fallback for environments that want to skip Photon.routing_app/Dash app for browsing the final route table.databricks.ymlEasy-button Asset Bundle with both the default AWS target and an Azure-orientedazuretarget.
The default AWS-oriented environment is:
- Databricks CLI profile:
DEFAULT - Catalog:
demos - Schema:
routing - Volume:
routing_assets - Region:
indiana
Deploy and run the full workflow on AWS / the default target:
databricks bundle deploy
databricks bundle run routing_intro
databricks bundle run routing_end_to_endDeploy and run the Azure-oriented target with your own Databricks CLI profile:
databricks bundle deploy -t azure --profile <your-azure-profile>
databricks bundle run routing_intro -t azure --profile <your-azure-profile>
databricks bundle run routing_end_to_end -t azure --profile <your-azure-profile>The recommended workflow order is:
routing_introrouting_end_to_end
The hybrid routing_end_to_end job then runs:
1a_load_normalize_addresses1_prepare_assets1_validate_services1b_geocode_addresses1c_build_shipments2a_cluster_shipments2a_resolve_osrm2a_finalize_routing2a_cpu_optimize2b_prepare_sparse_graph2b_resolve_sparse_osrm2b_gpu_optimize
CPU and GPU branches still run in parallel after 1c_build_shipments.
Serverless is used only where it is a good fit in this repo:
0-introduction/- stage 1 address load + normalize
- stage 1 shipment finalization after Photon
- CPU clustering and routing-table finalization
- GPU sparse-graph preparation
- GPU cuOpt optimization
Classic compute is still required for:
1-preprocessing-geocoding/01_prepare_assets.py1-preprocessing-geocoding/02_validate_services.py- the Photon call notebook (
04_geocode_addresses_photon.py) - the CPU and GPU OSRM notebooks
2a-cpu-route-optimization/04_route_optimization.pybecause it still depends on Ray
The bundle job wiring is the source of truth for compute selection. The checked-in
.py notebook source format does not preserve the UI-only notebook environment metadata
the same way Jupyter exports do, so the notebook headers and the mappings below document
the intended pairings for manual runs.
- Serverless CPU environment version 5:
0-introduction/01_cpu_intro.py,1-preprocessing-geocoding/03_load_and_normalize_addresses.py,1-preprocessing-geocoding/05_build_shipments.py,2a-cpu-route-optimization/01_cluster_shipments.py,2a-cpu-route-optimization/03_build_routing_table.py, and2b-gpu-route-optimization/01_prepare_sparse_graph.py - Serverless GPU environment version 4 on A10:
0-introduction/02_gpu_intro.pyand2b-gpu-route-optimization/03_route_optimization.py - Classic clusters:
1-preprocessing-geocoding/01_prepare_assets.pyonasset_prep_cluster,1-preprocessing-geocoding/02_validate_services.pyand1-preprocessing-geocoding/04_geocode_addresses_photon.pyongeocode_cluster,2a-cpu-route-optimization/02_resolve_osrm_distances.pyoncpu_distance_cluster,2a-cpu-route-optimization/04_route_optimization.pyoncpu_optimize_cluster, and2b-gpu-route-optimization/02_resolve_sparse_osrm.pyongpu_distance_cluster
If you want named interactive clusters for manual notebook runs, the repo includes a Databricks Python SDK helper that creates or updates those classic clusters for you.
python3 -m pip install databricks-sdk
python3 setup_classic_clusters.py --profile <your-profile> --asset-prep-only --startRun 1-preprocessing-geocoding/01_prepare_assets.py on asset_prep_cluster, then create
the rest of the classic notebook clusters:
python3 setup_classic_clusters.py --profile <your-profile> --startIf the configured catalog does not exist, 1-preprocessing-geocoding/01_prepare_assets.py
fails immediately with:
Catalog `<catalog>` must already exist before running this notebook.
The first 1-preprocessing-geocoding/01_prepare_assets.py run is the slow path because
the Photon archive is large and must be unpacked locally before it is copied into the
shared volume.
For iterative troubleshooting, use an interactive cluster for stage 1 until the init scripts and geocoding logic are stable. Then switch back to the bundle-managed jobs and rerun:
databricks bundle run routing_intro
databricks bundle run routing_end_to_endSuccessful Azure validation in an internal test workspace produced these approximate stage-level timings on the classic-first version of the workflow:
- asset prep cold path: ~49 min
- service validation: ~6 min
- geocode path combined: ~9 min
- CPU branch combined: ~31 min
- GPU branch combined: ~39 min
The hybrid split introduced here changes the task graph, but these numbers remain a good order-of-magnitude guide for the heavy classic stages.
If you prefer to run notebook-by-notebook:
- Optional but recommended first run:
0-introduction/01_cpu_intro.py, then0-introduction/02_gpu_intro.py. - Run
1-preprocessing-geocoding/03_load_and_normalize_addresses.py. - Run
1-preprocessing-geocoding/01_prepare_assets.py. - Attach the rendered init scripts from
/Volumes/demos/routing/routing_assets/init/to the cluster you will use for geocoding and distance resolution. - Restart that cluster.
- Run
1-preprocessing-geocoding/02_validate_services.py. - Run
1-preprocessing-geocoding/04_geocode_addresses_photon.py. - Run
1-preprocessing-geocoding/05_build_shipments.py. - Run the CPU path in
2a-cpu-route-optimization/. - Run the GPU path in
2b-gpu-route-optimization/.
The older all-in-one notebooks are still in the repo as classic/manual fallbacks:
1-preprocessing-geocoding/legacy_geocode_addresses.py2a-cpu-route-optimization/legacy_distance_calculation.py2b-gpu-route-optimization/legacy_distance_calculation.py
demos.routing.intro_shipmentsRepo-local intro subset used by the serverless-first notebook path.demos.routing.intro_routes_cpuIntro CPU routing output.demos.routing.intro_routes_gpuIntro GPU routing output.demos.routing.source_addressesLocal address input loaded from the vendored CSV.demos.routing.normalized_addressesDeterministic Photon request handoff table produced by the serverless step 3 notebook.demos.routing.geocoded_addressesAudit table with Photon status and matched coordinates.demos.routing.raw_shipmentsRouting-ready shipments withpackage_id,city,latitude,longitude,weight.demos.routing.optimized_routesDefault CPU output used by the Dash app.demos.routing.optimized_routes_gpu_10000Default GPU output.
The vendored sample contains about 55k Indianapolis-metro addresses so both solver paths can read from the same file while keeping their original scale targets:
- CPU defaults to
40000shipments. - GPU defaults to
10000shipments.
Stage 1 synthesizes a deterministic weight column because Overture address records do
not include shipment weights.
If you already have trusted coordinates:
- Skip Photon and point the CPU or GPU notebooks at your own shipments table, or
- Use
1-preprocessing-geocoding/legacy_geocode_addresses.pywithcoordinates_source_tableset to a table that already exposes:package_id,city,latitude,longitude,weight.
If no shipment table exists at all, the staged CPU and GPU notebooks fall back to
utils/shipments.csv.
Change these places first:
- Different catalog / schema / volume:
databricks.ymldefaults and the widget defaults in1-preprocessing-geocoding/01_prepare_assets.py. - Different region:
Stage 1
region,pbf_url,photon_db_url,photon_health_query, andosrm_health_route. - Different input data:
1-preprocessing-geocoding/03_load_and_normalize_addresses.py,1-preprocessing-geocoding/05_build_shipments.py, ordata/refresh_overture_indiana_addresses.py. - Different cluster shapes:
databricks.ymlvariablescpu_node_type_id,geocode_node_type_id, andcpu_spark_version, plus the serverless GPU accelerator inresources.jobs.*.tasks.*.compute.hardware_accelerator. - Different serverless/classic boundaries:
resources.jobs.routing_intro,resources.jobs.routing_end_to_end, andtargets.*.resources.jobs.routing_end_to_end.job_clustersindatabricks.yml. - Different app defaults:
routing_app/config.py,routing_app/app.yaml, androuting_app/README.md.
The vendored address sample is derived from Overture's open address data and filtered to an Indianapolis-metro subset that aligns with the original routing example.
See data/README.md for:
- source release details
- the exact city filter
- refresh instructions
- attribution notes
Start with AGENTS.md. It explains the stage contracts, the safest change order, and the
small set of files that control data source, geography, and deployment defaults.
© 2026 Databricks, Inc. All rights reserved. The source in this accelerator is provided subject to the Databricks License. All included or referenced third party libraries are subject to the licenses set forth below.
| library | description | license | source |
|---|---|---|---|
| OSRM Backend Server | High performance routing engine written in C++ designed to run on OpenStreetMap data | BSD 2-Clause "Simplified" License | https://github.com/Project-OSRM/osrm-backend |
| Photon | Open-source geocoder for OpenStreetMap data used by the address-to-coordinate stage | Apache License 2.0 | https://github.com/komoot/photon |
| ortools | Operations research tools developed at Google for combinatorial optimization | Apache License 2.0 | https://github.com/google/or-tools |
| folium | Visualize data in Python on interactive Leaflet.js maps | MIT License | https://github.com/python-visualization/folium |
| dash | Python framework for building analytical web applications and dashboards | MIT License | https://github.com/plotly/dash |
| branca | Library for generating complex HTML and JavaScript pages in Python; provides shared helpers for folium | MIT License | https://github.com/python-visualization/branca |
| plotly | Open-source Python library for interactive charts and graphs | MIT License | https://github.com/plotly/plotly.py |
| ray | Flexible distributed execution framework for scaling Python workflows | Apache License 2.0 | https://github.com/ray-project/ray |
| Databricks SDK for Python | Python SDK for Databricks workspace APIs used by the dashboard and setup helper | Apache License 2.0 | https://github.com/databricks/databricks-sdk-py |
| DuckDB | In-process analytical database used to refresh the vendored Overture sample | MIT License | https://github.com/duckdb/duckdb |
| cuOpt | GPU-accelerated combinatorial optimization solver from NVIDIA | Apache License 2.0 | https://docs.nvidia.com/cuopt/user-guide/latest/license.html |
The vendored address sample derives from Overture open address data. See data/README.md
for source release details and attribution notes.