Geospatial Store
Problem
Standard B-tree indexes cannot efficiently resolve multi-dimensional proximity, boundary-intersection, or distance queries over spatial data. Without spatial indexing, these operations degrade into full-table scans with costly per-row geometry math, inflating latency and compute costs as data volumes grow.
Solution
Use a Database with native Geospatial capabilities (e.g., PostGIS) that uses spatial grid indexing (like H3 or S2) and bounding boxes to optimize spatial query execution.
Cloud Paradigm
- Purpose-Built Persistence (spatial-native storage)
- Spatial Indexing (R-tree and discrete-grid tessellation)
- Coarse-to-Fine Query Pruning (bounding-box filter then exact geometry)
- Coordinate Reference System Normalization
- Precomputed Tile Aggregation for Serving
- Polyglot Persistence
Solution Flow
- The ingestion service receives raw location records—GPS pings, polygon boundaries (GeoJSON/WKT), or address strings—and normalizes them to a consistent SRID (typically WGS 84 / EPSG:4326).
- The geocoder resolves textual addresses into point geometries and, where needed, reprojects to a planar CRS for accurate metric distance work.
- The geospatial database stores each feature in a native
geometry/geographycolumn and builds a spatial index—R-tree/GiST bounding boxes plus a discrete grid (H3 or S2) cell column for cheap coarse filtering. - The query planner answers proximity,
ST_DWithin, andST_Intersectsrequests by first pruning candidates with the bounding-box index, then running exact geometry math only on the surviving rows. - The tile/serving layer aggregates results into H3 hexbins or vector tiles and returns them to mapping clients, routing engines, or analytics dashboards.
- The application consumes ranked-by-distance results, boundary memberships, or heatmap aggregates without ever scanning the full table.
When to Use
- Nearest-neighbor and radius searches ("stores within 5 km") at interactive latency.
- Point-in-polygon tests: which delivery zone, sales territory, or flood plain contains a coordinate.
- Route and isochrone calculations that depend on geometry intersection and length.
- Geofencing and real-time proximity alerts over moving assets.
When NOT to Use
- Purely tabular workloads where location is just a display attribute, never a filter.
- Global-scale telemetry needing sub-millisecond writes better served by an H3-keyed KV store.
- Simple bounding-box-only lookups a standard composite index already handles.
Trade-offs
- Exact spatial correctness vs the CPU cost of geometry math and index maintenance on write.
- Rich operator library (PostGIS) vs operational expertise and tuning of GiST/SP-GiST indexes.
- Grid indexing (H3/S2) speed vs edge-case inaccuracy where cells straddle boundaries.
- Single-database SQL joins with spatial predicates vs harder horizontal scaling of large geometry sets.
Real-World Example
A food-delivery marketplace stores every restaurant as a point and every courier zone as a polygon in PostGIS. When a customer opens the app, the service issues an ST_DWithin query against a GiST-indexed geography column to list restaurants within a 4 km radius, then runs ST_Contains to confirm the address falls inside an active delivery polygon. Dispatch precomputes H3 level-8 cells for couriers so the matcher can shortlist nearby drivers with a fast cell lookup before doing exact distance ranking—turning what would be a full-table distance scan into a millisecond index probe even during peak dinner traffic.
Additional Details
- Projection correctness: Metric operators (
ST_DWithin, length, area) silently return wrong answers if geometries carry mismatched SRIDs or run on a planar CRS far from its valid zone; enforce one storage SRID and reproject explicitly for distance math. - Invalid geometries: Self-intersecting or unclosed polygons from upstream feeds cause predicate exceptions or false negatives—validate on ingest with
ST_IsValid/ST_MakeValidand reject or repair before indexing. - Index maintenance: GiST/SP-GiST indexes bloat under heavy update churn (moving assets); schedule reindex/vacuum, and store fast-moving points separately from static polygons to limit rebuild cost.
- Grid resolution tuning: H3/S2 cell level trades pruning selectivity against candidate-set size—too coarse returns huge shortlists, too fine multiplies rows for large polygons; pick per-layer and precompute cell columns.
- Cost drivers: The bill is dominated by exact geometry CPU on surviving candidates, not the bounding-box probe; watch rows-post-filter and simplify complex polygons (
ST_Simplify) for serving tiles. - Observability: Instrument planner choices (index vs seq scan), candidate-vs-exact row counts per query, and geocoder resolution failure rates to catch silent full-table fallbacks.
- Schema evolution: Changing SRID or geometry type forces full re-indexing and cache invalidation; version tile/hexbin outputs so downstream clients tolerate resolution changes.
Security Controls
- Coordinate PII classification: Treat precise lat/long as personal data and apply the same access controls, masking low-precision coordinates for non-privileged consumers.
- Row-level security: Enforce Postgres RLS so tenants can only query geometries within their own territories or accounts.
- Input geometry validation: Reject malformed or self-intersecting geometries with
ST_IsValidto prevent planner errors and injection via crafted WKT. - Query cost limits: Cap
statement_timeoutand bound radius/polygon size to stop unbounded spatial scans from becoming a denial-of-service vector. - Encryption in transit and at rest: Use TLS to the database and volume/column encryption for stored location histories.
- Audit logging: Log geofence lookups and bulk geometry exports to detect location-tracking abuse.