Production-grade spatial-temporal analytics platform for government, emergency operations, critical infrastructure, and public safety intelligence workflows.
The engine ingests geolocated events over time, aggregates to H3 cells, computes trend-sensitive risk scores, detects anomalies, and serves operational outputs through REST and vector tiles for a temporal geospatial dashboard.
Traditional incident dashboards frequently fail at:
- combining spatial density with temporal acceleration,
- identifying early-stage risk growth before threshold breaches,
- delivering geospatial outputs in tile-native formats for real-time web operations.
This system addresses those gaps with a time-partitioned PostGIS + Timescale architecture and asynchronous analytics execution.
- Wildfire preparedness: detect sudden ignition cluster growth and prioritize patrol/resource staging.
- Urban safety intelligence: monitor crime activity growth in micro-zones and trigger analyst review.
- Flood/utility resilience: identify outage/flood incident surge zones and support dispatch sequencing.
- Critical asset protection: maintain risk heatmaps for substations, transport corridors, and treatment plants.
flowchart TD
A[Event Sources - CSV/API] --> B[Ingestion Service - FastAPI]
B --> C[PostgreSQL 16 + PostGIS + TimescaleDB]
C --> D[H3 Aggregation Engine - Celery]
D --> E[Risk Scoring Engine]
E --> F[Materialized View mv_daily_risk]
F --> G[Vector Tile API ST_AsMVT]
F --> H[REST Risk/Hotspot APIs]
G --> I[React + MapLibre Dashboard]
H --> I
C <--> J[Redis Tile Cache]
- Python 3.11
- FastAPI
- SQLAlchemy 2.x
- Celery + Redis
- PostgreSQL 16 + PostGIS + TimescaleDB
- h3-py, GeoPandas, Shapely
- Alembic migrations
- React (Vite + TypeScript)
- MapLibre GL JS
- Zustand state store
- PostgreSQL 16 with PostGIS (spatial types, indexes, functions) and TimescaleDB (hypertables, time-based partitioning).
- Extensions enabled at migration:
CREATE EXTENSION postgis,CREATE EXTENSION timescaledb. - All geometry stored in WGS 84 (SRID 4326); tile generation uses Web Mercator (SRID 3857) via
ST_Transform.
| Table | Purpose |
|---|---|
events |
Hypertable partitioned by event_timestamp (1-month chunks). Columns: event_type, event_timestamp, geom (Point, 4326), attributes_json (JSONB). |
h3_cells |
H3 hexagon polygons (GEOMETRY(Polygon, 4326)) keyed by h3_index and resolution. Used for aggregation joins and tile geometry. |
cell_aggregates |
Daily event counts, 7-day rolling average, growth rate per H3 cell and date. |
risk_scores |
Normalized risk score (0–100) and risk_level enum per H3/day. |
anomaly_flags |
Z-score anomaly indicator and flagged boolean per H3/day. |
users |
JWT principals for RBAC (admin, analyst, public). |
idx_events_geom_gistonevents.geom— point-in-polygon and bbox queries.idx_h3_cells_geom_gistonh3_cells.geom— spatial joins and tile clipping.idx_mv_daily_risk_geom_gistonmv_daily_risk.geom— vector tileST_Intersectsfiltering.
- Ingestion:
ST_SetSRID(ST_MakePoint(longitude, latitude), 4326)for event points. - Analytics:
ST_X(geom),ST_Y(geom)for coordinate extraction;ST_GeomFromText(wkt, 4326)for H3 polygon inserts. - Vector tiles:
ST_TileEnvelope(z,x,y)for tile bounds;ST_Transform(geom, 3857)for Web Mercator;ST_Intersectsfor clipping;ST_AsMVTGeomandST_AsMVTfor MVT output.
mv_daily_risk: denormalized materialized view joiningrisk_scores,cell_aggregates,h3_cells, andanomaly_flags, includinggeomfor tile serving. Refreshed after analytics runs.
Pipeline runs in Celery workers:
- H3 Binning
- Event points converted to H3 index at configurable resolution (
7or8).
- Event points converted to H3 index at configurable resolution (
- Daily Aggregation
- Group by day (
date_trunc('day', event_timestamp)) and H3 index.
- Group by day (
- Rolling Mean
- 7-day moving average by H3 partition.
- Growth Rate
(current_day - previous_7_day_avg) / previous_7_day_avg.
- Composite Risk
risk = event_count*0.5 + growth_rate*0.3 + rolling_7d_avg*0.2.
- Normalization
- Min-max normalized to
0..100across run interval.
- Min-max normalized to
- Risk Classification
0-25 low,26-50 medium,51-75 high,76-100 critical.
- Anomaly Detection
- Z-score on daily count sequence per H3 (
flagged = z >= 2.0).
- Z-score on daily count sequence per H3 (
POST /v1/events/upload- bulk event ingestionGET /v1/events- event query with temporal/type filtersPOST /v1/analytics/run- enqueue analytics pipelineGET /v1/risk/{date}- risk outputs for dateGET /v1/tiles/{z}/{x}/{y}.mvt- PostGIS-generated vector tile streamGET /v1/hotspots?start_date=&end_date=- emerging hotspot feedPOST /v1/auth/token- JWT issuanceGET /v1/health/liveandGET /v1/health/readyGET /metrics- Prometheus-compatible metrics endpoint
- JWT authentication with signed access tokens.
- Route-level RBAC using
admin,analyst, andpublicroles. - Rate limiting via
slowapiat API boundary. - JSONB attributes for controlled extensibility without schema churn.
Tiles are generated in-database with:
ST_TileEnvelopeST_AsMVTGeomST_AsMVT
Redis caches recent tile payloads for low-latency dashboard refreshes.
Key optimizations implemented:
- Timescale hypertable partitioning on
events.event_timestamp(1 month chunks). - Spatial index (
GIST) onevents.geomandh3_cells.geom. - Temporal indexes on event and risk buckets.
- H3 and risk-level indexes for hotspot retrieval.
- Materialized view for tile/read path acceleration.
- Cache-first tile response strategy in Redis (5-minute TTL).
Recommended query tuning workflow:
- Run
EXPLAIN (ANALYZE, BUFFERS)on tile and hotspot SQL. - Validate index hit rate and heap fetch behavior.
- Adjust
work_mem, parallel workers, and Timescale chunk interval if workload characteristics shift.
docker compose up --buildServices:
- Backend API:
http://localhost:8000 - Frontend dashboard:
http://localhost:5173 - PostgreSQL:
localhost:5432 - Redis:
localhost:6379
docker compose exec backend alembic upgrade headUse the bootstrap command:
python -m backend.app.utils.bootstrap_admin --username admin --password "CHANGE_ME" --role admin
python -m backend.app.utils.bootstrap_admin --username analyst --password "CHANGE_ME" --role analystThis command is idempotent: if the user exists, password and role are updated.
Load production-like event feeds from CSV (no hardcoded demo data):
python -m backend.app.utils.seed_events --csv /path/to/events.csvExpected CSV headers:
event_typeevent_timestamp(ISO-8601)longitudelatitudeattributes_json(optional JSON object as string)
Call:
POST /v1/analytics/run?resolution=8
Frontend consumes vector tiles and renders temporal risk layers with:
- date slider,
- playback animation,
- risk-level toggles,
- popup metrics (
event_count,growth_rate,risk_score, anomaly flag).
Integration tests are in backend/tests and cover:
- event ingestion + retrieval,
- analytics job enqueue behavior,
- vector tile binary response path.
Run:
pytest backend/tests -qNote: tests require PostgreSQL/PostGIS/Timescale and Redis plus applied migrations.
Operational SQL profiles are under backend/sql/performance:
explain_tile_query.sqlexplain_hotspots_query.sqlREADME.mdwith tuning checklist.
Run:
psql "$DATABASE_URL" -f backend/sql/performance/explain_tile_query.sql
psql "$DATABASE_URL" -f backend/sql/performance/explain_hotspots_query.sqlGitHub Actions workflow at .github/workflows/ci.yml executes:
- backend lint (
ruff), - backend typecheck (
mypy), - migration smoke test (
upgrade -> downgrade -> upgrade), - backend integration tests (
pytest), - frontend production build (
npm ci && npm run build).
risk-intelligence-engine/
├── backend/
│ ├── app/
│ ├── initdb/
│ ├── tests/
│ ├── requirements.txt
│ └── main.py
├── frontend/
├── alembic/
├── docker-compose.yml
├── Dockerfile
└── README.md
- Multi-tenant schema isolation and row-level security.
- Event stream ingestion from Kafka/MQTT.
- pgRouting-based network accessibility risk overlays.
- Probabilistic forecasting (Bayesian/STL/Prophet) per H3 corridor.
- Data quality scoring and lineage metadata.
- SSO (OIDC/SAML), audit trail, and policy-based access control.
- Continuous model drift detection and scoring recalibration.
- Set strong JWT_SECRET_KEY
- Run migrations before first deploy
- Bootstrap admin and analyst users
- Configure rate limits for production load
- Enable HTTPS and secure Redis