Skip to content

System Architecture

Design Principles

FloodWatch follows a microservices architecture where each component is independently deployable, scalable, and maintainable. The system is fully containerized using Docker Compose, enabling consistent deployment across development, staging, and production environments.

Core design decisions:

  • Separation of concerns — Data ingestion, storage, API, rendering, and presentation are independent services
  • OGC compliance — Map services follow Open Geospatial Consortium standards (WMS, WCS, vector tiles)
  • Spatial-first — PostGIS powers all geospatial queries, with server-side clustering for performance at scale
  • Real-time capable — Automated ingestion pipelines keep forecast data current with minimal latency

High-Level Architecture

graph TB
    subgraph External Sources
        HYDRO[GeoSFM / MIKE / FloodPROOFS<br/>Hydrological Forecasts]
        WRF[WRF Model<br/>Rainfall Predictions]
        SAT[Satellite<br/>Flood Extent]
        FTP[SFTP / FTP<br/>Data Feeds]
    end

    subgraph Ingestion Layer
        JOBS[Scheduled Jobs<br/><i>Python cron tasks</i>]
    end

    subgraph Data Layer
        DB[(PostgreSQL / PostGIS<br/><i>Spatial database</i>)]
        PGBOUNCER[PgBouncer<br/><i>Connection pooling</i>]
    end

    subgraph Application Layer
        CMS[GeoManager CMS<br/><i>Django + Wagtail</i>]
        API[FloodWatch API<br/><i>FastAPI</i>]
    end

    subgraph Map Rendering Layer
        MAPSERVER[MapServer<br/><i>WMS raster tiles</i>]
        MAPCACHE[MapCache<br/><i>Tile caching</i>]
        TILESERV[pg_tileserv<br/><i>Vector tiles</i>]
    end

    subgraph Presentation Layer
        VIEWER[Map Viewer<br/><i>Next.js + MapLibre GL</i>]
    end

    subgraph Gateway
        NGINX[Nginx<br/><i>Reverse proxy</i>]
    end

    HYDRO --> JOBS
    WRF --> JOBS
    FTP --> JOBS
    SAT --> CMS

    JOBS --> DB
    CMS --> DB
    DB --> PGBOUNCER
    PGBOUNCER --> API
    PGBOUNCER --> TILESERV
    DB --> MAPSERVER
    MAPSERVER --> MAPCACHE

    API --> NGINX
    MAPCACHE --> NGINX
    TILESERV --> NGINX
    CMS --> NGINX
    VIEWER --> NGINX

    NGINX --> USERS[End Users<br/><i>Forecasters, Agencies, Public</i>]

Data Flow

1. Ingestion Pipeline

External data sources deliver forecast and observation data via scheduled transfers:

sequenceDiagram
    participant Source as External Source
    participant Jobs as Ingestion Jobs
    participant DB as PostGIS Database
    participant CMS as GeoManager CMS

    Source->>Jobs: Hydrological forecasts (FTP/SFTP)
    Source->>Jobs: WRF rainfall (SFTP)
    Source->>CMS: Satellite imagery (upload)

    Jobs->>DB: Parse, validate, and load forecast data
    Jobs->>DB: Update multimodal_forecast table
    CMS->>DB: Register raster layers (COG format)

    Note over DB: ~5.6M forecast rows<br/>3,199 control points

2. Request Flow

When a user interacts with the map viewer:

sequenceDiagram
    participant User as End User
    participant Nginx as Nginx Gateway
    participant Viewer as Map Viewer
    participant API as FastAPI
    participant Tiles as Map Services
    participant DB as PostGIS

    User->>Nginx: Open FloodWatch
    Nginx->>Viewer: Serve application
    Viewer->>Nginx: Request vector tiles
    Nginx->>Tiles: pg_tileserv query
    Tiles->>DB: Clustered point query
    DB-->>Tiles: GeoJSON features
    Tiles-->>Viewer: Vector tiles (MVT)

    Viewer->>Nginx: Request forecast chart
    Nginx->>API: /api/v1/multimodal/timeseries
    API->>DB: Query forecast data
    DB-->>API: Time series results
    API-->>Viewer: JSON response

Component Overview

Frontend — Map Viewer

The web interface built with Next.js and MapLibre GL JS. Renders an interactive map with vector tiles (control points with clustering), raster overlays (flood extents, rainfall), and analytical widgets (time series charts, impact summaries).

API — FastAPI Service

High-performance REST API serving flood data as JSON and GeoJSON. Provides endpoints for regional summaries, time series forecasts, alert statistics, risk assessments, and expert impact assessments. Auto-generates OpenAPI documentation.

CMS — GeoManager

GeoManager is a Wagtail-based Django application for geospatial data management. Administrators use it to configure map layers, manage raster/vector datasets, set up automated data watchers, and style layer visualizations.

Map Services

Three specialized services handle different tile formats:

  • MapServer — Renders raster data (flood extents, rainfall grids) as WMS tiles
  • MapCache — Caches rendered tiles for performance
  • pg_tileserv — Serves vector tiles directly from PostGIS with server-side clustering

Database — PostgreSQL/PostGIS

Central data store with two primary schemas:

  • gha — Spatial operational data (control points, forecasts, admin boundaries)
  • cms — Application data (CMS pages, layer configurations, user data)

Ingestion — Scheduled Jobs

Python-based cron jobs that synchronize data from external sources:

  • GeoSFM, MIKE, FloodPROOFS discharge forecasts
  • WRF weather model rainfall predictions
  • Google Flood Forecasts
  • Satellite-derived flood extent observations

Alert Classification

The system uses a three-tier alert classification based on river discharge thresholds:

graph LR
    subgraph Discharge Thresholds
        NORMAL[Normal<br/>&lt; 300 m³/s] --> WARNING[Warning<br/>≥ 300 m³/s]
        WARNING --> ALARM[Alarm<br/>≥ 500 m³/s]
        ALARM --> EMERGENCY[Emergency<br/>≥ 750 m³/s]
    end

    style NORMAL fill:#4CAF50,color:#fff
    style WARNING fill:#FF9800,color:#fff
    style ALARM fill:#f44336,color:#fff
    style EMERGENCY fill:#9C27B0,color:#fff

These thresholds are applied consistently across the API, map visualization, and alerting systems.