Geohash-Based IDs: A Clever Pattern for Location Data
When building the NZ Speed Camera Map, I needed unique IDs for 896 cameras. The catch: no database, just coordinate data from a government CSV. Geohashing solved this elegantly.
Geohashes encode latitude/longitude into a string where nearby locations share prefixes. An 8-character geohash gives ~19m precision—perfect for distinguishing cameras.
The Problem
Government data includes coordinates but no stable IDs. Camera names change. Addresses vary. I needed IDs that:
- Stay consistent across data updates
- Require no central authority
- Allow proximity queries
The Solution
import ngeohash from 'ngeohash';
export function generateCameraId(lat: number, lng: number): string {
return ngeohash.encode(lat, lng, 8); // ~19m precision
}An 8-character geohash like rbsm6p7q uniquely identifies a camera's location. Even if metadata changes, coordinates don't—so the ID remains stable.
Precision Levels
| Characters | Precision | Use Case |
|---|---|---|
| 4 | ~20km | City-level |
| 6 | ~600m | Neighborhood |
| 8 | ~19m | Building |
| 10 | ~1m | Exact point |
Practical Benefits
Deduplication: When scraping data, duplicates naturally collapse:
const uniqueCameras = Array.from(
new Map(cameras.map((c) => [c.id, c])).values()
);Proximity: Cameras with shared prefixes are nearby—useful for clustering.
SEO-friendly slugs: Combine geohash with readable info:
const slug = `auckland-cbd-${geohash.slice(0, 6)}`;When to Use This Pattern
- Static datasets with coordinates
- No database available
- Need deterministic IDs from location data
- Want built-in proximity information
This pattern won't work for moving objects or when sub-meter precision matters. For those cases, use UUIDs with a coordinate lookup.
Code
The full implementation is in nz-speed-cameras on GitHub.