Runtime
- +Go 1.25 · Echo HTTP
- +zap structured logging
- +Distroless image (~10 MB)
// case_study :: miomio_api
Hawaii-specific weather intelligence, built on a Go + PostGIS spine.
miomio-apiis a spatial JSON weather API for the Hawaiian Islands — point-in-time and 25-step hourly forecasts plus real-time observations from ground weather stations, queryable by any lat/lon. Built and operated by Cinder Logic as internal R&D: a working production system we use to sharpen the same platform-engineering practice we ship for clients.
Generic global weather APIs collapse Hawaii's microclimates and trade-wind regimes into a single coarse cell. NOAA publishes a higher-fidelity ~3 km nested grid (NAM Nest-HI), but it ships as raw GRIB2 files that consumer apps can't use directly.
Ground-station observations from the Hawaii Mesonet live in a separate format again. The opportunity: a small, fast, spatial JSON layer over the primary sources — one endpoint that knows both the forecast grid and the live stations, and serves either for any coordinate in the islands.
┌─────────────────────────┐ ┌─────────────────────────┐
│ NOAA NAM Nest-HI │ │ Mesonet stations │
│ GRIB2 (3 km, every 6h)│ │ (live observations) │
└────────────┬────────────┘ └────────────┬────────────┘
│ byte-range fetch │ pull
▼ ▼
┌─────────────────────────┐ ┌─────────────────────────┐
│ noaa-worker │ │ mesonet-worker │
│ cron 0 */2 * * * │ │ long-running daemon │
│ wgrib2 + errgroup │ │ filter inactive sites │
└────────────┬────────────┘ └────────────┬────────────┘
│ │
└───────────────┬───────────────────┘
▼
┌──────────────────────────┐
│ PostgreSQL + PostGIS │ ◀── Redis (cache)
│ GIST index, ST_Distance│
└──────────────┬───────────┘
▼
┌──────────────────────────┐
│ miomio-api (Echo) │
│ stateless · /v1/health │
└──────────────┬───────────┘
▼
api.staging.miomio.dev
One Go binary, four subcommands — api, worker, mesonet, and migrate. Same image deployed three different ways: a stateless API, a cron-driven NOAA ingester, and a long-running Mesonet daemon. One build to test, one binary to roll back, one schema the binary owns end-to-end.
Two-request strategy: pull the .idx, parse byte offsets for the variables we want, then range-fetch only those bytes from NOAA's CDN. Custom UA, exponential backoff on 403/429.
When a query lands more than 1.5 km from the nearest 3 km NAM grid node, fetch the four surrounding nodes and interpolate every scalar field to the exact coordinate. Falls back to nearest-neighbor at coastal edges.
GEOGRAPHY column with a GIST index; ST_Distance ordering for nearest-node selection. Time-step selection is arithmetic on reference_time — no full-table sorts.# postgis earns its keep
Worker fans out 4 GRIB2 fetches via errgroup + a semaphore channel. First error cancels the group and stops in-flight work cleanly.
One Go binary with subcommands (api / worker / mesonet / migrate). Migrations embedded via embed.FS, so a deploy is one image — and Postgres can't drift from the schema the binary expects.
Wind direction is derived from U/V components, then bucketed into a 16-point compass and a boolean trade-wind flag (30°–120° at ≥2 m/s). Useful primitives for downstream consumers.
Raw model output gets turned into actionable labels at query time: precip_summary buckets accumulation into Dry / Light / Moderate / Heavy, and CAPE (J/kg) is surfaced from NAM so consumers can flag convective potential — the afternoon thunderstorm risk that matters in Hawaii but doesn't fit on a temperature dial.# raw numbers → useful answers
Point-in-time forecast — closest valid_time to now
$ curl "https://api.staging.miomio.dev/v1/forecast?lat=21.3069&lon=-157.8583"
{
"reference_time": "2026-05-02T00:00:00Z",
"valid_time": "2026-05-02T04:00:00Z",
"grid_lat": 21.3161,
"grid_lon": -157.864,
"dist_km": 1.2,
"interpolated": false,
"temp_c": 24.2,
"humidity_pct": 77.1,
"wind_u": -4.95,
"wind_v": -3.57,
"wind_speed_ms": 6.1,
"wind_dir_deg": 54.2,
"wind_cardinal": "NE",
"trade_winds": true,
"precip_mm": 0,
"precip_summary": { "label": "Dry", "intensity": "dry" },
"cape_jkg": 679,
"source": "NOAA NAM Nest-HI"
}25-step hourly time series — f00 through f24
$ curl "https://api.staging.miomio.dev/v1/forecast/hourly?lat=21.3069&lon=-157.8583"
[
{
"valid_time": "2026-05-02T05:00:00Z",
"temp_c": 23.9,
"wind_speed_ms": 5.8,
"wind_cardinal": "NE",
"trade_winds": true,
"precip_summary": { "label": "Dry", "intensity": "dry" },
"cape_jkg": 612,
...
},
...
// 25 entries, f00 through f24
]Staging
api.staging.miomio.dev
READY
Production
api.miomio.dev
STANDBY
// start_a_project
Ship a platform you won't have to rebuild.
A 30-minute call to walk your architecture, scope a phase, and decide whether we're a fit.