Summit 26 from June 1-4 in San Francisco

Lead your organization in the era of agents and enterprise intelligence.

Snowflake for DevelopersGuidesBuild Routing Solution in Snowflake with Cortex Code
Quickstart

Build Routing Solution in Snowflake with Cortex Code

Cortex LLM
Becky O'Connor, Piotr Paczewski, Oleksii Bielov

🚀 Build. Customize. Optimize. Use natural language to deploy a complete route optimization solution in Snowflake - no code, no external APIs, just results.

Overview

alt text

Build a complete route optimization platform in minutes using just natural language commands.

This solution builds an Open Route Service Native App directly in your Snowflake account using Cortex Code - Snowflake's AI-powered CLI. No complex setup, no external APIs, no data leaving Snowflake.

What You'll Build

🔧 OpenRouteService Native App - A self-contained routing engine running in Snowpark Container Services with SQL-callable functions.

📍 Four Powerful Routing Functions:

  • Directions - Calculate optimal routes between multiple waypoints
  • Optimization - Match delivery jobs to vehicles based on time windows, capacity, and skills
  • Isochrones - Generate catchment polygons showing reachable areas within a given drive time
  • Time-Distance Matrix - Calculate travel time and distance matrices between multiple locations

📐 GeoFunctions — Each routing function also has a _GEO variant (e.g. DIRECTIONS_GEO, ISOCHRONES_GEO, OPTIMIZATION_GEO) that wraps the base function and returns the route/polygon geometry as a native Snowflake GEOGRAPHY column — ready for geospatial analysis with ST_LENGTH, ST_AREA, ST_WITHIN, and more.

🗺️ Any Location - Customize to Paris, London, New York, or anywhere in the world with downloadable OpenStreetMap data.

🧪 Function Tester - An interactive Streamlit app to test the routing functions with sample addresses.

Why This Matters

Traditional ApproachThis Solution
External API dependenciesSelf-contained Native App
Data leaves your environmentEverything stays in Snowflake
Complex integration workDeploy with natural language commands
Pay-per-call API limitsUnlimited calls, you control compute
Hours of setupMinutes to deploy

Prerequisites

This is what you will need:

NOTE: This is enabled by default with the exception of Free Trials where you would need to contact your snowflake representative to activate it.

  • External Access Integration Activated - Required to download map files from provider account

  • Cortex Code CLI installed and configured

    • Installation: See the Cortex Code documentation for setup instructions
    • Add to your PATH: export PATH="$HOME/.local/bin:$PATH" (add to ~/.zshrc or ~/.bashrc)
    • Verify: cortex --version
  • Container Runtime - One of the following:

  • VSCode recommended for running Cortex Code commands

Route Planning And Optimization Architecture

The architecture below shows the solution which uses a native app and container services to power sophisticated routing and optimisation functions.

alt text

This is a self-contained service which is managed by you. There are no API calls outside of Snowflake and no API limitations. This solution uses a small high-memory pool (HIGHMEM_X64_S) which is capable of running unlimited service calls within San Francisco (the default map). If you wish to use a larger map such as Europe or the World, you can increase the size of the compute.

What You'll Learn

  • Build a Snowflake Native App using Cortex Code AI-powered CLI with natural language commands
  • Use Snowpark Container Services to run OpenRouteService as a self-managed routing engine
  • Understand Geospatial data in Snowflake and how it integrates with routing functions
  • Work with 4 routing functions deployed via the Native App:
    • Directions - Simple and multi-waypoint routing based on road network and vehicle profile
    • Optimization - Route optimization matching demands with vehicle availability
    • Isochrones - Catchment area analysis based on travel time
    • Time-Distance Matrix - Calculate travel time and distance matrices between multiple locations
  • Call all routing functions directly via SQL — including concrete query examples you can run immediately
  • Customize map regions and vehicle profiles for your specific use case

Build the Routing Solution

Cortex Code Deployment

Use Cortex Code, Snowflake's AI-powered CLI, to deploy the Native App using natural language commands and automated skills.

Setup Cortex Code

  1. Clone the repository:

    git clone https://github.com/Snowflake-Labs/sfguide-create-a-route-optimisation-and-vehicle-route-plan-simulator
    cd sfguide-create-a-route-optimisation-and-vehicle-route-plan-simulator
    

    Without Git: Download the ZIP from the repository and extract it, then navigate to the folder in VS Code

    After cloning, open the folder in VS Code. You should see the following structure in your Explorer:

    Cloned Repository Structure
  2. Launch Cortex Code CLI in the VS Code terminal:

    cortex
    
  3. Connect to Snowflake - Cortex Code will prompt you to select or create a connection. once a connection has ben created using one of the authentication methods, you will now be able to start cortex code in the terminal by using the cortex command which will give you a similar screen as below.

Cortex Code Logged In

Understanding Cortex Code Skills

Before running any commands, it's helpful to understand what skills are and how they power this solution.

What are Skills?

Skills are structured specifications that instruct Cortex Code how to perform a procedure. Think of them as detailed recipes - they define the exact steps, parameters, and verification checks needed to accomplish a task. Each skill is a markdown file that describes:

  • What the skill does - A clear description of the outcome
  • Step-by-step instructions - The exact sequence of actions to perform
  • Stopping points - Where to pause for user input or verification
  • Success criteria - How to verify the task completed correctly

Benefits of Using Skills

BenefitDescription
ConsistencySkills ensure the same steps are followed every time, reducing human error
ReusabilityOnce created, skills can be shared and reused across projects and teams
TransparencyYou can read the skill file to understand exactly what will happen before running it
CustomizabilitySkills can be modified to fit your specific requirements
AI-Assisted CreationCortex Code can help you create new skills from natural language descriptions

How This Solution Uses Skills

This repository demonstrates how skills can manage the complete lifecycle of an end-to-end Snowflake analytical solution - from installation through customization to uninstallation. There are multiple pre-built skills in the .cortex/skills/skill_name/SKILL.md:

StageSkillsWhat They Do
📦 Buildbuild-routing-solutionDeploy Routing Solution based on Native App and container services
⚙️ Customizecustomize-mainRoute customization requests (location and routing profiles)
customize-main/locationChange the geographic region (sub-skill, do not invoke separately)
customize-main/routing-profilesEnable/disable vehicle routing profiles (sub-skill, do not invoke separately)
customize-main/read-ors-configurationRead current ORS configuration (sub-skill, do not invoke separately)

To run any skill, simply tell Cortex Code:

$<skill-name>

For example:

$build-routing-solution

Cortex Code reads the skill's markdown file and executes each step, asking for input when needed and verifying success before moving on.

TIP: Want to see what a skill does before running it? Open the skill's .md file in the .cortex/skills/skill_name/ folder to review the exact steps.

Verify Prerequisites (Optional)

Run the prerequisites check skill to ensure all dependencies are installed:

$prerequisites-build-routing-solution

Build the Routing Solution

Simply type the following command in Cortex Code:

$build-routing-solution

Cortex Code will automatically:

  • Create the required database, stages, and image repository
  • Upload configuration files
  • Detect your container runtime (Docker or Podman)
  • Build and push all 4 container images
  • Deploy the Native App

The skill will guide you through any required steps, including:

  • Selecting your preferred container runtime if both are available
  • Authenticating with the Snowflake image registry
  • Monitoring the build progress

The skill uses interactive prompting to gather required information:

Interactive Skill Prompting

TIP: Use your keyboard arrow keys to toggle through the options, then press Enter to confirm your selection.

What gets installed:

ComponentNameDescription
DatabaseOPENROUTESERVICE_SETUPSetup database with stages and image repository
StageORS_SPCS_STAGEConfiguration files and map data
StageORS_GRAPHS_SPCS_STAGEGenerated routing graphs
StageORS_ELEVATION_CACHE_SPCS_STAGEElevation data cache
Image RepositoryIMAGE_REPOSITORYContainer images for services
Application PackageOPENROUTESERVICE_NATIVE_APP_PKGNative App package
ApplicationOPENROUTESERVICE_NATIVE_APPDeployed Native App with routing functions

Simply confirm each prompt as the skill progresses. The skill handles all the complex setup automatically - creating databases, uploading files, building containers, and deploying the Native App.

Once complete, you'll see a success message with a direct link to your app:

Route Optimizer Installed Successfully

Activate the App

Once deployment completes, Cortex Code will provide a link to your app. You need to:

  1. Navigate to Data Products > Apps > OPENROUTESERVICE_NATIVE_APP in Snowsight
Navigate to Apps
  1. Click on the OPENROUTESERVICE_NATIVE_APP to open it
App Icon
  1. Grant the required privileges and review external access
Grant Privileges

The app requires these permissions to function:

  • CREATE COMPUTE POOL: Allows the app to create compute pools for running the OpenRouteService containers via Snowpark Container Services
  • External access integration: Required to download OpenStreetMap (OSM) data files from external sources during the initial setup

Click Grant for Step 1. For Step 2, click Review to see the external endpoints, then click Connect to allow the connection.

  1. Once all privileges are granted, click Activate and wait a few minutes for the routing functions to install and the graphs to build

NOTE: The activation time depends on your configuration:

  • Map size: Larger country or state maps take longer than city maps
  • Vehicle profiles: Each enabled profile (driving-car, cycling, walking, etc.) generates its own routing graph
  • Resource scaling: The compute pool size affects build speed

The combination of map size and vehicle options determines the total number of graphs to build. A city map with 2 profiles will complete quickly, while a country map with 5+ profiles will take significantly longer.

Once activated, you'll see a Launch app button appear. Click it to open the Service Manager.

Service Manager

The Launch app button takes you to the Service Manager dashboard, which displays the status of each of the four services running:

Service Manager

The Service Manager shows:

  • Service Status Dashboard - Overview of all running, stopped, and error states
  • Individual Service Management - Start/Stop controls for each service:
    • Data Downloader - Downloads and updates map data
    • Open Route Service - Core routing and directions engine
    • Routing Gateway - API gateway for routing requests
    • VROOM Service - Route optimization engine

Use the Start All / Stop All buttons for bulk operations, or manage services individually. Click Refresh Status to update the dashboard.

TIP: All 4 services should show ✅ RUNNING status before using the routing functions.

ORS Configuration

The Native App is configured via the ors-config.yml file which controls:

Map Source File

ors:
  engine:
    profile_default:
      build:  
        source_file: /home/ors/files/SanFrancisco.osm.pbf

The default deployment uses San Francisco. When you customize the map region, this path is updated automatically.

Routing Profiles

The configuration defines which routing profiles are available for routing:

ProfileDescriptionDefault
driving-carStandard passenger vehicle✅ Enabled
driving-hgvHeavy goods vehicle (trucks)✅ Enabled
cycling-roadRoad bicycle❌ Disabled
cycling-regularRegular bicycle❌ Disabled
cycling-mountainMountain bicycle❌ Disabled
cycling-electricElectric bicycle✅ Enabled
foot-walkingPedestrian walking❌ Disabled
foot-hikingHiking trails❌ Disabled
wheelchairWheelchair accessible❌ Disabled

NOTE: Enabling more profiles increases graph build time and compute resource usage. The default configuration covers most delivery and logistics use cases.

Optimization Limits

The config also controls route optimization capacity:

    matrix:
      maximum_visited_nodes: 100000000
      maximum_routes: 250000

These settings support complex route optimizations with many vehicles and delivery points.

Function Tester

The Native App includes a built-in Function Tester Streamlit application for testing the routing functions interactively.

Function Tester

To access the Function Tester:

  1. Open Data Products > Apps > OPENROUTESERVICE_NATIVE_APP in Snowsight
  2. Navigate to the Function Tester page in the app

The Function Tester allows you to test all four routing functions:

🗺️ DIRECTIONS

  • Select start and end locations from preset addresses
  • Choose a routing profile (car, truck, bicycle)
  • View the calculated route on an interactive map
  • See step-by-step directions and distance/duration

🚚 OPTIMIZATION

  • Configure multiple vehicles with different:
    • Time windows (start/end hours)
    • Capacity limits
    • Skill sets (refrigeration, hazardous goods, etc.)
  • Add delivery jobs with:
    • Locations
    • Time windows
    • Required skills
  • Run the optimization to see assigned routes per vehicle
  • View detailed itinerary for each vehicle

⏰ ISOCHRONES

  • Select a center point location
  • Choose travel time in minutes
  • Generate a catchment polygon showing how far you can travel
  • Useful for delivery zone planning and coverage analysis

🗺️ TIME-DISTANCE MATRIX

  • Calculate travel time and distance matrices between multiple locations

TIP: The Function Tester comes pre-configured with San Francisco addresses and default vehicle profiles (car, HGV, electric bicycle). When you customize the deployment, the Function Tester is automatically updated with region-specific addresses and your enabled vehicle profiles.

SQL Function Reference

All routing functions are deployed as SQL functions inside the Native App and can be called directly from any Snowflake worksheet, notebook, or application. The functions live under OPENROUTESERVICE_NATIVE_APP.CORE.

Function Overview

FunctionSignatureReturnsDescription
DIRECTIONS(method VARCHAR, jstart ARRAY, jend ARRAY)VARIANTPoint-to-point directions
DIRECTIONS(method VARCHAR, locations VARIANT)VARIANTMulti-waypoint directions
ISOCHRONES(method TEXT, lon FLOAT, lat FLOAT, range INT)VARIANTCatchment area polygon
OPTIMIZATION(jobs ARRAY, vehicles ARRAY, matrices ARRAY)VARIANTRoute optimization (tabular)
OPTIMIZATION(challenge VARIANT)VARIANTRoute optimization (raw)
MATRIX(method VARCHAR, locations ARRAY)VARIANTTime-distance matrix (tabular)
MATRIX(method VARCHAR, options VARIANT)VARIANTTime-distance matrix (raw)
ORS_STATUS()VARIANTService health and graph info
DIRECTIONS_GEO(method VARCHAR, jstart ARRAY, jend ARRAY)TABLE(RESPONSE, GEOJSON, DISTANCE, DURATION)Directions with GEOGRAPHY
DIRECTIONS_GEO(method VARCHAR, locations VARIANT)TABLE(RESPONSE, GEOJSON, DISTANCE, DURATION)Multi-waypoint with GEOGRAPHY
ISOCHRONES_GEO(method TEXT, lon FLOAT, lat FLOAT, range INT)TABLE(RESPONSE, GEOJSON)Isochrone with GEOGRAPHY
OPTIMIZATION_GEO(jobs ARRAY, vehicles ARRAY, matrices ARRAY)TABLE(RESPONSE, GEOJSON, VEHICLE, DURATION, STEPS)Optimization with GEOGRAPHY
OPTIMIZATION_GEO(challenge VARIANT)TABLE(RESPONSE, GEOJSON, VEHICLE, DURATION, STEPS)Optimization (raw) with GEOGRAPHY

Base Functions — SQL Examples

Directions: Point-to-Point

Calculate a driving route between two coordinates (longitude, latitude):

SELECT OPENROUTESERVICE_NATIVE_APP.CORE.DIRECTIONS(
    'driving-car',
    [-122.4194, 37.7749],   -- start: [lon, lat]
    [-122.4783, 37.8199]    -- end:   [lon, lat]
) AS route;

Directions: Multi-Waypoint

Route through multiple stops by passing a locations object:

SELECT OPENROUTESERVICE_NATIVE_APP.CORE.DIRECTIONS(
    'driving-car',
    OBJECT_CONSTRUCT('coordinates', 
        ARRAY_CONSTRUCT(
            ARRAY_CONSTRUCT(-122.4194, 37.7749),   -- stop 1
            ARRAY_CONSTRUCT(-122.4078, 37.7941),   -- stop 2
            ARRAY_CONSTRUCT(-122.4783, 37.8199)    -- stop 3
        )
    )
) AS route;

Isochrones

Generate a polygon showing the area reachable within 10 minutes of driving:

SELECT OPENROUTESERVICE_NATIVE_APP.CORE.ISOCHRONES(
    'driving-car',
    -122.4194,   -- longitude
    37.7749,     -- latitude
    10           -- range in minutes
) AS isochrone;

Optimization: Tabular

Match delivery jobs to vehicles using arrays of jobs and vehicles:

SELECT OPENROUTESERVICE_NATIVE_APP.CORE.OPTIMIZATION(
    -- jobs: array of delivery tasks
    [
        {'id': 1, 'location': [-122.4194, 37.7749], 'service': 300},
        {'id': 2, 'location': [-122.4078, 37.7941], 'service': 300},
        {'id': 3, 'location': [-122.4350, 37.7609], 'service': 300}
    ],
    -- vehicles: array of available vehicles
    [
        {'id': 1, 'profile': 'driving-car', 'start': [-122.4177, 37.8080], 'end': [-122.4177, 37.8080], 'capacity': [4], 'time_window': [28800, 43200]},
        {'id': 2, 'profile': 'driving-car', 'start': [-122.3950, 37.7785], 'end': [-122.3950, 37.7785], 'capacity': [4], 'time_window': [28800, 43200]}
    ],
    -- matrices (optional, empty array uses ORS to calculate)
    []
) AS optimized_routes;

Optimization: Raw Variant

Pass a full VROOM-compatible JSON challenge:

SELECT OPENROUTESERVICE_NATIVE_APP.CORE.OPTIMIZATION(
    PARSE_JSON('{
        "jobs": [
            {"id": 1, "location": [-122.4194, 37.7749], "service": 300},
            {"id": 2, "location": [-122.4078, 37.7941], "service": 300}
        ],
        "vehicles": [
            {"id": 1, "profile": "driving-car", "start": [-122.4177, 37.8080], "end": [-122.4177, 37.8080], "capacity": [4]}
        ]
    }')
) AS optimized_routes;

Matrix: Tabular

Calculate the time and distance matrix between multiple locations:

SELECT OPENROUTESERVICE_NATIVE_APP.CORE.MATRIX(
    'driving-car',
    ARRAY_CONSTRUCT(
        ARRAY_CONSTRUCT(-122.4194, 37.7749),
        ARRAY_CONSTRUCT(-122.4078, 37.7941),
        ARRAY_CONSTRUCT(-122.4783, 37.8199)
    )
) AS matrix;

Matrix: Raw Variant

Pass full matrix options for advanced control (sources, destinations, metrics):

SELECT OPENROUTESERVICE_NATIVE_APP.CORE.MATRIX(
    'driving-car',
    PARSE_JSON('{
        "locations": [[-122.4194, 37.7749], [-122.4078, 37.7941], [-122.4783, 37.8199]],
        "metrics": ["distance", "duration"],
        "resolve_locations": true,
        "sources": [0],
        "destinations": [1, 2]
    }')
) AS matrix;

GeoFunctions — Native GEOGRAPHY Output

The _GEO functions are SQL wrappers around the base functions above. All they do is:

  1. Call the base function (e.g. DIRECTIONS)
  2. Use TO_GEOGRAPHY() to parse the GeoJSON geometry from the VARIANT response into a native Snowflake GEOGRAPHY column
  3. Extract key summary fields (distance, duration, vehicle ID, etc.) into their own columns

Why this matters: The base functions return a single VARIANT column where the route geometry is buried inside response:features[0]:geometry. The GeoFunctions extract that geometry into a dedicated GEOJSON GEOGRAPHY column for user convenience.

DIRECTIONS_GEO: Point-to-Point

SELECT * FROM TABLE(OPENROUTESERVICE_NATIVE_APP.CORE.DIRECTIONS_GEO(
    'driving-car',
    [-122.4194, 37.7749],
    [-122.4783, 37.8199]
));
-- Returns: RESPONSE (variant), GEOJSON (geography), DISTANCE (float, meters), DURATION (float, seconds)

DIRECTIONS_GEO: Multi-Waypoint

SELECT * FROM TABLE(OPENROUTESERVICE_NATIVE_APP.CORE.DIRECTIONS_GEO(
    'driving-car',
    OBJECT_CONSTRUCT('coordinates',
        ARRAY_CONSTRUCT(
            ARRAY_CONSTRUCT(-122.4194, 37.7749),
            ARRAY_CONSTRUCT(-122.4078, 37.7941),
            ARRAY_CONSTRUCT(-122.4783, 37.8199)
        )
    )
));
-- Returns: RESPONSE (variant), GEOJSON (geography), DISTANCE (float, meters), DURATION (float, seconds)

ISOCHRONES_GEO

SELECT * FROM TABLE(OPENROUTESERVICE_NATIVE_APP.CORE.ISOCHRONES_GEO(
    'driving-car',
    -122.4194,
    37.7749,
    10
));
-- Returns: RESPONSE (variant), GEOJSON (geography)

OPTIMIZATION_GEO: Tabular

Returns one row per vehicle route with the route geometry as a GEOGRAPHY LineString:

SELECT * FROM TABLE(OPENROUTESERVICE_NATIVE_APP.CORE.OPTIMIZATION_GEO(
    [
        {'id': 1, 'location': [-122.4194, 37.7749], 'service': 300},
        {'id': 2, 'location': [-122.4078, 37.7941], 'service': 300},
        {'id': 3, 'location': [-122.4350, 37.7609], 'service': 300}
    ],
    [
        {'id': 1, 'profile': 'driving-car', 'start': [-122.4177, 37.8080], 'end': [-122.4177, 37.8080], 'capacity': [4], 'time_window': [28800, 43200]},
        {'id': 2, 'profile': 'driving-car', 'start': [-122.3950, 37.7785], 'end': [-122.3950, 37.7785], 'capacity': [4], 'time_window': [28800, 43200]}
    ],
    []
));
-- Returns: RESPONSE (variant), GEOJSON (geography), VEHICLE (int), DURATION (int), STEPS (variant)

OPTIMIZATION_GEO: Raw Variant

SELECT * FROM TABLE(OPENROUTESERVICE_NATIVE_APP.CORE.OPTIMIZATION_GEO(
    PARSE_JSON('{
        "jobs": [
            {"id": 1, "location": [-122.4194, 37.7749], "service": 300},
            {"id": 2, "location": [-122.4078, 37.7941], "service": 300}
        ],
        "vehicles": [
            {"id": 1, "profile": "driving-car", "start": [-122.4177, 37.8080], "end": [-122.4177, 37.8080], "capacity": [4]}
        ]
    }')
));
-- Returns: RESPONSE (variant), GEOJSON (geography), VEHICLE (int), DURATION (int), STEPS (variant)

Geospatial Integration Patterns

Once you have GEOGRAPHY columns from the Geofunctions, you can chain them with Snowflake's built-in geospatial functions:

Route length in kilometers:

SELECT
    ST_LENGTH(GEOJSON) / 1000 AS route_length_km,
    DISTANCE / 1000 AS ors_distance_km,
    DURATION / 60 AS duration_minutes
FROM TABLE(OPENROUTESERVICE_NATIVE_APP.CORE.DIRECTIONS_GEO(
    'driving-car', [-122.4194, 37.7749], [-122.4783, 37.8199]
));

Isochrone area in square kilometers:

SELECT
    ST_AREA(GEOJSON) / 1000000 AS catchment_area_sq_km
FROM TABLE(OPENROUTESERVICE_NATIVE_APP.CORE.ISOCHRONES_GEO(
    'driving-car', -122.4194, 37.7749, 15
));

Check if a point falls within an isochrone:

SELECT
    ST_WITHIN(
        ST_MAKEPOINT(-122.4078, 37.7941),
        GEOJSON
    ) AS is_reachable
FROM TABLE(OPENROUTESERVICE_NATIVE_APP.CORE.ISOCHRONES_GEO(
    'driving-car', -122.4194, 37.7749, 10
));

Customize Your Deployment

The default deployment uses San Francisco with standard routing profiles. You can customize two key areas for the ORS Native App:

CustomizationDefaultExample Custom
🗺️ Map RegionSan FranciscoParis, London, Tokyo, etc.
🚚 Routing ProfilesCar, HGV, Electric BicycleAdd walking, wheelchair, road bicycle

NOTE: This step is optional. If you skip customization, the Native App will use the San Francisco defaults.

ORS Customization Skills

.cortex/skills/customize-main/
├── location.md           ← Customize map
└── routing-profiles.md   ← Customize routing profile
...  

To customize, run:

$customize-main

How the Customization Works

The main $customize-main skill orchestrates the process by asking two questions, then runs only the relevant sub-skills:

  1. "Do you want to customize the LOCATION (map region)?"

    • If YES → Runs $customize-main/location `
    • If NO → Skips map download entirely
  2. "Do you want to customize ROUTING PROFILES (vehicle types)?"

    • If YES → Runs $customize-main/routing-profiles
    • If NO → Keeps default profiles (car, HGV, electric bicycle)

Example: Customizing to Paris

Let's try changing the location to Paris. In Cortex Code, simply type:

$customize-main

then select location: Paris as part of the workflow.

Cortex Code will find the appropriate skill and guide you through the process:

Step 1: Location Change

  • Cortex Code downloads the Paris (or Île-de-France) map from Geofabrik
  • Uploads the OpenStreetMap data to Snowflake
  • Updates ors-config.yml with the new map path

Step 2: Routing Profiles

  • Choose which routing profiles to enable for Paris:
    • driving-car - Standard passenger vehicle ✅
    • driving-hgv - Heavy goods vehicle (trucks) ✅
    • cycling-electric - Electric bicycles ✅
    • foot-walking - Pedestrian (optional)
    • wheelchair - Wheelchair accessible (optional)

Step 3: Function Tester Update

  • Updates Function Tester with Paris addresses
  • Updates available vehicle profiles dropdown to match your configuration

Step 4: Build Graphs

  • Services restart to update routing graphs for Paris
  • Changes are applied directly to your local files

Once the customization completes, Cortex Code shows a summary of everything that was updated:

Location Customization Complete

The summary confirms:

  1. Map downloaded - The Île-de-France map for the Paris region
  2. Config updated - ors-config.yml now points to the new map file
  3. Service spec updated - Volume paths configured for Paris
  4. Services resumed - ORS_SERVICE is rebuilding routing graphs (this takes 15-30 minutes depending on map size)
  5. Streamlit updated - Default location changed to "Eiffel Tower, Paris"

⏳ Wait for Services to Restart

After the map is uploaded (if location was changed) or profiles were modified (if vehicles were changed), the services need to update the routing graphs. You can monitor progress in the Service Manager:

  1. Navigate to Data Products > Apps > OPENROUTESERVICE_NATIVE_APP
  2. Check the Service Manager - all 4 services should show ✅ RUNNING
  3. The Open Route Service will take the longest as it builds the graph files

Once services are running, the Function Tester will show Paris addresses instead of San Francisco!

New Location Complete

You can now test the routing functions with Paris addresses. Here's an example of testing the ISOCHRONES function to calculate a 15-minute driving catchment area from the Eiffel Tower:

Test Isochrones Paris

TIP: If you only want to enable additional vehicle profiles (and keep San Francisco), answer NO to location. This skips map download entirely - making it much faster!

Map Download & Resource Scaling (Location Changes Only)

If you selected YES to location customization, the skill downloads OpenStreetMap data from Geofabrik or BBBike. The bigger the map file, the longer it takes to:

  • Download the OSM data from the source
  • Upload to the Snowflake stage
  • Generate graph files for route calculations
Map SizeExample RegionsDownload TimeGraph Build Time
< 100MBSan Francisco, ZurichMinutes5-15 minutes
100MB - 1GBNew York State, Switzerland10-30 minutes30-60 minutes
1-5GBGermany, France, California30-60 minutes1-3 hours
> 5GBGreat Britain, entire countries1-2 hours3-8+ hours

IMPORTANT: For country-wide or large region maps, graph generation can take several hours. The services will show as "running" while building graphs in the background.

Automatic Compute Scaling

Cortex Code will detect the map size after download and offer to resize the compute pool to speed up graph generation:

Map SizeSuggested ComputeAuto-Suspend Extension
< 1GBCPU_X64_S (default)1 hour
1-5GBHIGHMEM_X64_M8 hours
> 5GBHIGHMEM_X64_M24 hours

When prompted, you can accept the scaling recommendation to ensure graphs are computed as quickly as possible. The extended auto-suspend time prevents the service from shutting down mid-build.

TIP: For quickest results, use the smallest map that covers your use case. A city-level map (e.g., New York) builds much faster than a country map (e.g., USA).

Routing Profile Configuration

The skill presents available routing profiles and lets you enable/disable them:

ProfileCategoryDescription
driving-carDrivingStandard passenger vehicle
driving-hgvDrivingHeavy goods vehicles (trucks)
cycling-regularCyclingStandard bicycles
cycling-roadCyclingRoad bicycles
cycling-mountainCyclingMountain bicycles
cycling-electricCyclingElectric bicycles
foot-walkingFootPedestrian walking
foot-hikingFootHiking trails
wheelchairWheelchairWheelchair accessible routes

NOTE: Enabling more profiles increases graph build time. The default (driving-car, driving-hgv, cycling-electric) covers most logistics use cases.

Function Tester Customization

The skill automatically updates the Function Tester Streamlit with:

Region-specific sample addresses:

  • Start locations (5 landmarks/city centers)
  • End locations (5 different destinations)
  • Waypoints (20 locations across the region)

Vehicle profiles dropdown:

  • Updated to show only your enabled profiles
  • Matches the profiles configured in ors-config.yml

This ensures test addresses are valid for your map region and vehicle options match your configuration.

TIP: Customizations modify your local files directly. If you want to preserve the original San Francisco configuration, make a backup before customizing.

Once your services are running with the new map (or if you skipped customization), you're ready to deploy the demo!

Next Steps

🎉 Congratulations! Your Routing Solution is now installed and configured.

To deploy the Route Optimization demo with real-world POI data and interactive notebooks, continue to the next quickstart: 👉 Deploy Route Optimization Demo

The demo quickstart will:

  • Acquire the Carto Overture Maps Places dataset with 50+ million POIs worldwide
  • Deploy interactive AISQL notebooks to explore routing functions
  • Create the Route Optimization Simulator Streamlit app

All demo content will use your configured map region (San Francisco by default, or your customized region like Paris).

Uninstall the Route Optimizer

Cortex Code makes uninstallation simple with natural language commands.

Uninstall demo

To remove the Snowflake objects installed as part of the demo you can type in Cortex Code CLI:

uninstall all Snowflake objects created as part of skill $build-routing-solution

This will:

  • Remove the Native App (OPENROUTESERVICE_NATIVE_APP)
  • Drop the Application Package (OPENROUTESERVICE_NATIVE_APP_PKG)
  • Delete the setup database (OPENROUTESERVICE_SETUP) including all stages and image repository
  • Optionally remove local container images

Conclusion and Resources

Conclusion

You've just deployed a self-contained routing solution in Snowflake using natural language commands - no complex configuration files, no external API dependencies, and no data leaving your Snowflake environment.

This solution demonstrates the power of combining:

  • Cortex Code - AI-powered CLI that turns natural language into automated workflows
  • Snowpark Container Services - Running OpenRouteService as a self-managed Native App
  • Native App Functions - SQL-callable routing functions for directions, optimization, isochrones, and time-distance matrix

The key advantage of this approach is flexibility without complexity. Want to switch from San Francisco to Paris? Just run the location customization skill. Need to add walking or cycling routes? Enable additional routing profiles. The skill-based approach means you only run the steps you need.

What You Learned

  • Deploy Native Apps with Cortex Code - Use natural language skills to automate complex Snowflake deployments including container services, stages, and compute pools

  • Self-Managed Route Optimization - Run OpenRouteService entirely within Snowflake with no external API calls, giving you unlimited routing requests and complete data privacy

  • Flexible Customization - Use skills to customize location (any city in the world) and vehicle types (car, HGV, bicycle, walking)

  • Four Routing Functions:

    • Directions - Point-to-point and multi-waypoint routing
    • Optimization - Match delivery jobs to vehicles based on time windows, capacity, and skills
    • Isochrones - Generate catchment polygons showing reachable areas
    • Time-Distance Matrix - Calculate travel time and distance matrices between multiple locations
  • GeoFunctions for Geospatial Analysis - Use _GEO variants (DIRECTIONS_GEO, ISOCHRONES_GEO, OPTIMIZATION_GEO) that wrap the base functions and return native GEOGRAPHY columns — no manual JSON parsing needed

Next Steps

Deploy the demo to see the routing functions in action with real-world POI data:

Related Resources

Source code

Related Quickstarts

OpenRouteService Resources

Cortex Code

Map Data Sources

Updated 2026-03-03

This content is provided as is, and is not maintained on an ongoing basis. It may be out of date with current Snowflake instances