tutorial

Monitoring Nominatim with Vigilmon

Nominatim is a self-hosted OpenStreetMap geocoding API built on C++ and PostgreSQL. Learn how to monitor API availability, geocoding response times, reverse geocoding health, and OSM data import jobs with Vigilmon.

Nominatim is the geocoding engine behind OpenStreetMap — a self-hosted API that converts addresses to coordinates and coordinates back to addresses, backed by a massive PostgreSQL database of global OSM data. When you run it yourself, you get unlimited lookups, full data control, and no per-request pricing. But you also own the reliability: if the API server goes down, geocoding calls in your application stack fail silently; if an OSM import job corrupts the search index, lookup accuracy degrades without any error response. Vigilmon gives you continuous visibility into your Nominatim deployment's availability, performance, and data freshness.

What You'll Set Up

  • HTTP uptime monitor for the Nominatim API server
  • Geocoding endpoint response time monitoring
  • Reverse geocoding endpoint health check
  • PostgreSQL database connectivity heartbeat
  • OSM data import job status heartbeat
  • Address lookup API synthetic health check
  • Search result accuracy check via known-good query

Prerequisites

  • Nominatim installed and running (C++/PHP or Python frontend, port 8080 by default or behind a reverse proxy)
  • PostgreSQL database with OSM data imported
  • A free Vigilmon account

Step 1: Monitor the Nominatim API Server

Nominatim exposes its geocoding interface via HTTP. Start with a basic availability check.

  1. Log in to vigilmon.online and click Add Monitor.
  2. Set Type to HTTP / HTTPS.
  3. Enter your Nominatim base URL: https://nominatim.yourdomain.com or http://YOUR_SERVER_IP:8080.
  4. Set Check interval to 1 minute.
  5. Set Expected HTTP status to 200.
  6. Under Keyword match, enter Nominatim to confirm the status page is rendering.
  7. Click Save.

Nominatim's root endpoint typically returns its version and status page. This confirms the web server (Apache/nginx + PHP/Python) is operational.


Step 2: Monitor the Geocoding Endpoint

The forward geocoding endpoint (/search) converts place names or addresses to coordinates. Monitor it with a known, stable query.

  1. Add MonitorHTTP / HTTPS.
  2. URL:
    https://nominatim.yourdomain.com/search?q=Berlin&format=json&limit=1
    
  3. Expected HTTP status: 200.
  4. Keyword match: "lat" — confirms the response contains a coordinate, not just an empty array.
  5. Check interval: 2 minutes.

"Berlin" is a stable, unambiguous query that will always return results as long as you have European OSM data imported. Use a location appropriate to your imported dataset if you're running a regional Nominatim instance.

This monitor also acts as a response time check — Vigilmon records response times for every probe, so you'll see latency trends in the dashboard. Set a Response time threshold alert (e.g., 5000ms) to catch slow queries caused by database bloat or index fragmentation.


Step 3: Monitor the Reverse Geocoding Endpoint

Reverse geocoding (/reverse) converts latitude/longitude pairs to human-readable addresses. It uses different code paths and indexes than forward geocoding, so monitor it independently.

  1. Add MonitorHTTP / HTTPS.
  2. URL:
    https://nominatim.yourdomain.com/reverse?lat=52.5200&lon=13.4050&format=json
    
    (These coordinates are central Berlin — adjust to a point in your imported area.)
  3. Expected HTTP status: 200.
  4. Keyword match: "display_name" — confirms the response contains a resolved address string.
  5. Check interval: 2 minutes.

Step 4: PostgreSQL Database Connectivity Heartbeat

Nominatim's entire dataset lives in PostgreSQL. A database failure takes down all geocoding operations. Monitor connectivity with a lightweight heartbeat script:

#!/bin/bash
RESULT=$(psql -U nominatim -h 127.0.0.1 -d nominatim \
  -c "SELECT count(*) FROM placex LIMIT 1;" 2>/dev/null | grep -E "^\s+[0-9]")

if [ -n "$RESULT" ]; then
  curl -s https://vigilmon.online/heartbeat/POSTGRES_HEARTBEAT_ID
fi

This queries the placex table — Nominatim's primary geocoding table — to confirm both connectivity and table availability. Save it to /usr/local/bin/check-nominatim-db.sh, make it executable, and schedule it every minute:

* * * * * /usr/local/bin/check-nominatim-db.sh

In Vigilmon:

  1. Add MonitorCron Heartbeat.
  2. Expected ping interval: 2 minutes.

Also add a TCP port monitor for the database:

  1. Add MonitorTCP Port.
  2. Host: your PostgreSQL server IP.
  3. Port: 5432.
  4. Check interval: 1 minute.

Step 5: OSM Data Import Job Heartbeat

Nominatim's data stays current through periodic OSM updates, typically run via osm2pgsql and Nominatim's update scripts. If the update job fails, your geocoding data grows stale — addresses for new streets or renamed roads return incorrect results without any error indicator.

Wrap your update script with a heartbeat:

#!/bin/bash
LOG_FILE="/var/log/nominatim-update.log"

# Run Nominatim's OSM update
nominatim replication --project-dir /srv/nominatim/project >> "$LOG_FILE" 2>&1

if [ $? -eq 0 ]; then
  curl -s https://vigilmon.online/heartbeat/OSM_UPDATE_HEARTBEAT_ID
else
  # Log failure but don't ping — alert fires when heartbeat stops arriving
  echo "$(date): Nominatim update failed" >> "$LOG_FILE"
fi

Set the Vigilmon heartbeat interval to match your update frequency:

  • Minutely updates (replication mode): 5 minutes
  • Hourly updates: 90 minutes
  • Daily updates: 1500 minutes (25 hours, to account for schedule drift)

Step 6: Address Lookup API Synthetic Health Check

Nominatim's /lookup endpoint resolves specific OSM node IDs to address details. This endpoint exercises a different query path than /search and /reverse.

  1. Add MonitorHTTP / HTTPS.
  2. URL:
    https://nominatim.yourdomain.com/lookup?osm_ids=R62422&format=json
    
    (R62422 is the OSM relation ID for Germany — a stable, well-indexed object.)
  3. Expected HTTP status: 200.
  4. Keyword match: "osm_id" — confirms the lookup returned a valid result.
  5. Check interval: 5 minutes.

Step 7: Search Result Accuracy via Synthetic Query

Response time and status code alone don't catch data quality issues. If your OSM import partially failed, the API returns 200 with empty or wrong results. Add an accuracy check using a query with a known, expected result.

Create a script that validates the geocoding result, not just the HTTP status:

#!/bin/bash
# Query for a known location and verify the response contains expected data
RESPONSE=$(curl -s \
  "https://nominatim.yourdomain.com/search?q=Brandenburg+Gate+Berlin&format=json&limit=1")

# Check that the response contains coordinates in the expected range for Berlin
LAT=$(echo "$RESPONSE" | python3 -c \
  "import sys,json; d=json.load(sys.stdin); print(d[0]['lat'])" 2>/dev/null)

# Brandenburg Gate is at ~52.5163°N — verify we're within 0.1 degrees
VALID=$(python3 -c "lat=float('$LAT'); print('ok' if 52.4 < lat < 52.6 else 'fail')" 2>/dev/null)

if [ "$VALID" = "ok" ]; then
  curl -s https://vigilmon.online/heartbeat/ACCURACY_HEARTBEAT_ID
fi

Adapt the reference location to a well-known landmark in your imported region. Run every 10 minutes via cron and set the Vigilmon heartbeat interval to 15 minutes.


Step 8: Monitor Nominatim's Status Endpoint

Nominatim includes a built-in /status endpoint that reports whether the service is operational and the data age:

  1. Add MonitorHTTP / HTTPS.
  2. URL: https://nominatim.yourdomain.com/status.php (or /status depending on your Nominatim version).
  3. Expected HTTP status: 200.
  4. Keyword match: OK or "status":0 — Nominatim returns {"status":0,"message":"OK"} when healthy.
  5. Check interval: 1 minute.

This is Nominatim's own self-reported health check and is the fastest way to confirm the service considers itself operational.


Step 9: Configure Alert Channels

  1. Go to Alert Channels in Vigilmon and add your preferred channel (Slack, email, PagerDuty, or webhook for integration with your application stack).
  2. Set Consecutive failures before alert to 2 for geocoding endpoint monitors to filter transient network blips.
  3. Set Response time threshold alerts on the /search and /reverse monitors — degraded response times (above 3–5 seconds for most queries) indicate index problems before they cause timeouts.
  4. Set the OSM update heartbeat to 1 consecutive failure — stale data is a data quality issue that should alert immediately.
  5. Use Maintenance windows during OSM full re-imports, which can take hours and will spike response times.

Summary

| Monitor | Target | What It Catches | |---|---|---| | API server | https://nominatim.yourdomain.com | Web server/PHP down | | Status endpoint | /status.php | Self-reported Nominatim failure | | Geocoding endpoint | /search?q=Berlin | Forward geocoding failure, slow index | | Reverse geocoding | /reverse?lat=...&lon=... | Reverse lookup failure | | Lookup API | /lookup?osm_ids=R62422 | Node lookup failure | | PostgreSQL TCP | :5432 | Database server unreachable | | PostgreSQL heartbeat | placex query script | DB disconnect, table corruption | | OSM update heartbeat | Post-update ping | Import job failure, stale data | | Accuracy heartbeat | Coordinate validation script | Data quality degradation |

Nominatim gives you a private, unlimited, cost-effective geocoding API — but its reliability is entirely in your hands. With Vigilmon watching every endpoint, validating result accuracy, and alerting on stale OSM updates, your geocoding infrastructure stays trustworthy for every application that depends on it.

Monitor your app with Vigilmon

Free plan — 5 monitors, no credit card required. Up and running in 60 seconds.

Start free →