Python Machine Learning Prophet Docker FastAPI OpenAPI

Flow Forecast

Work in Progress GitHub →

Time-series forecasting API for river flow rates using Facebook Prophet, integrated with GaugeWatcher

Flow Forecast - River flow prediction API visualization

Flow Forecast

A time-series forecasting API that predicts river flow rates using historical gauge data. Built as an experimental feature for GaugeWatcher, this service helps paddlers anticipate river conditions days in advance.

The Problem

River flow rates are notoriously difficult to predict. They depend on snowpack, precipitation, dam releases, and seasonal patterns that vary by watershed. Paddlers often check gauge readings the morning of a trip, but by then it may be too late to adjust plans if conditions aren’t ideal.

What if you could see a forecast for river levels the same way you check a weather forecast?

Technical Approach

Why Prophet?

Facebook Prophet is designed for time-series forecasting with strong seasonal patterns—exactly what river flow data exhibits. Key advantages:

  • Handles seasonality well — river flows follow annual snowmelt cycles and weekly dam release patterns
  • Robust to missing data — gauge stations occasionally go offline; Prophet handles gaps gracefully
  • Fast enough for real-time — forecasts generate in seconds, suitable for API responses

Architecture

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│  GaugeWatcher   │────▶│  Flow Forecast  │────▶│     Prophet     │
│   iOS/macOS     │     │    FastAPI      │     │     Model       │
└─────────────────┘     └─────────────────┘     └─────────────────┘


                        ┌─────────────────┐
                        │   USGS API      │
                        │  (Historical)   │
                        └─────────────────┘

The API:

  1. Receives a gauge station ID and forecast horizon from the client
  2. Fetches historical data from USGS (typically 2+ years for seasonality)
  3. Fits a Prophet model to the historical data
  4. Returns forecasted values with confidence intervals

API Design

@app.get("/forecast/{gauge_id}")
async def get_forecast(
    gauge_id: str,
    days: int = 7,
    include_history: bool = False
) -> ForecastResponse:
    """Generate flow forecast for a USGS gauge station."""

The API is documented with OpenAPI spec, enabling automatic client generation. The GaugeWatcher Swift client is generated from this spec using openapi-generator.

Current Status

FeatureStatus
USGS gauge forecastingComplete
Dockerized deploymentComplete
OpenAPI documentationComplete
Swift client generationComplete
Colorado DWR supportPlanned
Canadian gauge supportPlanned

Learnings

  • Data quality matters more than model complexity — Prophet works well out of the box, but garbage in = garbage out. Cleaning historical data (removing sensor errors, handling unit changes) had more impact than tuning model parameters.
  • Forecasting is humbling — rivers are chaotic systems. The model provides useful directional guidance but shouldn’t be treated as ground truth. Confidence intervals are essential.
  • API-first design pays off — generating the Swift client from OpenAPI eliminated an entire class of integration bugs between the Python backend and iOS app.