Skip to content

GIS Contribution — Foundation Workshop

This page answers the Product & Technology Foundation Workshop agenda for the GIS / geospatial visualization capability. It follows the agenda's own numbering and uses the formats the agenda asks for: lessons as Problem → Root Cause → New Principle, technology decisions as Need → Alternatives → Decision → Rationale backed by lightweight ADRs.

Everything stated here is already built and tested, not proposed on paper: a working reference implementation runs on a Kubernetes cluster, every claim below links to the guide or ADR that proves it, and each guide ships with a rerunnable test suite.

If you read only two pages

Vision — the direction in one page. How it works — the platform explained without jargon.


Part 1 — WHAT: GIS in the product landscape

GIS is a platform-level capability, not a pillar product (§1, §2)

Applying the Four-Pillar Architecture Check: geospatial visualization is needed by any pillar that touches maps, weather, aeronautics or hydrology. It therefore belongs in the Common Platform, below the pillar products:

flowchart TB
    subgraph CP["Common Platform"]
        GIS["GIS services<br/>(OGC APIs: maps, features, processing)"]
        REF["Shared referential<br/>(parameters, units, level types)"]
        STORE["Shared data services<br/>(spatio-temporal DB, object storage)"]
    end
    subgraph PP["Pillar Products"]
        P1["Pillar 1 product"]
        P2["Pillar 2 product"]
        P34["Pillars 3 / 4 (future)"]
    end
    P1 --> GIS
    P2 --> GIS
    P34 -.-> GIS
    GIS --> REF
    GIS --> STORE
Hold "Alt" / "Option" to enable pan & zoom

What the GIS capability provides to every product on top of it:

Capability What products get Standard
Map rendering Styled maps of any published layer, any projection OGC WMS
Tiled maps Fast, cacheable map tiles for web/mobile clients OGC WMTS / TMS
Feature access Raw vector data (stations, observations, zones) as GeoJSON/GML OGC WFS
Geospatial processing Server-side computation (e.g. interpolation of station networks) OGC WPS
Time navigation Every time-aware layer answers TIME= requests WMS dimensions
Vertical navigation Model layers answer ELEVATION= (pressure level / altitude) WMS dimensions
Run selection Model layers distinguish forecast runs (reference time) WMS custom dimension
Styling Palettes and symbolization applied server-side at request time SLD

Because everything is exposed through OGC standards, any client — our future UI, QGIS, a customer's existing tool — consumes the same services. No customer-specific branches at the GIS layer: customer needs are met with configuration (layers, styles, workspaces), not forks.

Target data landscape (§2)

The capability is designed against the real operational inventory, not a toy dataset (details):

  • Observations from the GTS network: SYNOP, METAR — dense surface networks; TEMP, AMDAR — sparse upper-air.
  • Aeronautical area products with validity periods: SIGMET, AIRMET, GAMET, TAF.
  • Imagery: satellite (per satellite/sensor, time series), radar, lightning.
  • NWP models: multi-run, multi-validity, multi-level rasters.
  • Hydrology: stations, discharge/level series, basins, flood-related layers.

Client applications must navigate this data in time and altitude, and apply palettes at request time — both are native WMS mechanisms in the design (dimensions + SLD), not custom code.

What unlocks several pillars first (§3)

The highest-leverage foundation pieces, in build order — this is exactly the sequence the reference implementation followed (guides):

  1. Shared spatio-temporal database (schemas, roles, PostGIS/TimescaleDB) — everything else reads from it.
  2. The parameter/unit referential — one table answering "what is this quantity and in which unit is it stored" (ADR-0003). A measurement without a unit is a bug; K vs °C confusion must be structurally impossible.
  3. The GIS service itself, clustered and configured entirely by code.
  4. Ingestion conventions (file naming, index tables) so any producer can feed the platform without touching the GIS service.

Part 2 — HOW: lessons, principles, stack

§4 Lessons learned (Problem → Root Cause → New Principle)

From previous operational experience with GeoServer platforms, validated again during the reference build:

Problem Root Cause New Principle
GIS server config drifted between environments; nobody could rebuild it Configuration lived in a UI, applied by hand, stored on a local disk Nobody configures by hand. All configuration is code (a startup plugin + one ConfigMap); the database is the single source of truth (ADR-0006)
Adding/replacing a server instance was a manual, risky operation Instances were "pets": fixed IPs, local state, hand-tuned Cattle, not pets. Instances boot from an empty disk, register via DNS discovery, and are disposable (ADR-0005, ADR-0008)
Failures surfaced days later as wrong maps, not at deploy time Components fell back silently on missing preconditions Fail loud. A missing database, bucket or DNS entry stops startup with an explicit exit code — never a degraded service
Same physical quantity stored in different units by different feeds No shared referential; each decoder chose its own conventions Units are first-class. Canonical unit per parameter, conversion at ingestion, source unit kept (ADR-0003)
Upgrades feared and postponed; versions rotted Environment not reproducible, no way to test an upgrade safely Everything retestable. Pinned artifacts, scripted builds, rerunnable test suites per subsystem — an upgrade is a branch + a test run
Understanding official specs (WMO/ICAO) from text alone led to wrong implementations Figures and tables in the standards carry meaning the text does not repeat Study the source documents, figures included, before modelling data

These are offered as input to the workshop's initial Engineering Principles.

§5 Architecture principles — GIS stance

Position against each relevant workshop principle, with the evidence:

Workshop principle GIS stance Evidence
API-first Everything is an OGC API (WMS/WMTS/WFS/WPS); the UI is just another client All guides test via API only
Standards-based interfaces OGC + SQL + S3 protocol; no proprietary interface anywhere ADR-0009
Cloud-native but on-premise capable Runs on plain Kubernetes (validated on k3s); S3 protocol served by self-hostable storage; no cloud-vendor dependency Guide 3, Guide 4
Containerization Single custom image built on the official GeoServer image, plugins baked in Guide 2
Configuration outside application code One ConfigMap declares layers/styles/mosaics; secrets in K8s Secrets; zero config in the image ADR-0006
Scalability Replica count is a number in a manifest; scaling up/down measured with zero request errors Guide 3
Upgradeability Ephemeral instances + DB as source of truth ⇒ upgrade = new image tag + rollout ADR-0005
Observability by design Honest gap — health probes exist; metrics/tracing/dashboards are the next subsystem to design Risks
Event-driven where appropriate Deliberately not event-driven at the GIS boundary: ingestion writes files + one DB row; the GIS service discovers data through the DB index, no notification bus needed. Simpler, and one less moving part ADR-0010
No customer-specific forks Customer variation = workspaces, layers, styles — configuration, never code §2 above

§6 Technology stack (Need → Alternatives → Decision → Rationale)

Need Alternatives considered Decision Rationale
GIS / visualization server GeoServer 3, GeoServer 2.x, MapServer, thin tile servers (pg_tileserv/martin) GeoServer 3.0.1 Only candidate covering the full need (WMS+WFS+WPS+time/elevation dimensions+SLD+plugin ecosystem); v3 = supported line (Tomcat 11/Spring 6/JDK 21); prior team production experience; thin tile servers cover only a fraction of the need
Relational + geospatial + time-series PostgreSQL+PostGIS, +TimescaleDB, dedicated TSDB (Influx…) PostgreSQL + PostGIS + TimescaleDB (shared, operator-run) One database engine for geospatial and time-series; hypertables for observation volumes; the platform DB is shared — GIS gets its own schemas/roles (Guide 1)
GIS configuration storage File data dir on shared volume (RWX), DB-backed config DB-backed (jdbcconfig/jdbcstore) Shared-filesystem data dirs were the root cause of past drift and locking issues; DB gives one source of truth + instant propagation (measured ~3 s across replicas)
Object / file storage S3-compatible self-hosted (SeaweedFS, MinIO), filesystem S3 protocol; SeaweedFS for the bench Rasters as Cloud-Optimized GeoTIFF read directly from S3; tile cache in S3; MinIO rejected (AGPL licensing risk); final production storage = platform-level decision, anything S3-compatible works (ADR-0009)
Clustering / session sharing Fixed-member config, K8s-native DNS discovery Hazelcast with DNS discovery Replica count becomes a free variable; UI sessions shared across replicas; no fixed IPs anywhere (ADR-0008)
Dense-network interpolation (SYNOP/METAR) IDW, splines IDW as WPS rendering transformation Computed server-side at render time, styled by SLD like any raster (Guide 8)
Sparse-network interpolation (TEMP/AMDAR) IDW, Barnes, RBF, first-guess + corrections First-guess + corrections Comparative study on realistic sparse/clustered stations: RMSE 1.36 K vs 4.40 (IDW), 4.93 (Barnes), 6.77 (RBF) (ADR-0013)
In-house plugin distribution Ad-hoc copies, company artifact repository Company Nexus/Artifactory (to confirm) Community plugins are multi-JAR bundles; in-house plugins are Maven builds — both need a proper artifact channel (ADR-0007)

Full decision log: 13 ADRs, all in the lightweight format the agenda proposes.


Part 3 & 4 — Organizing and starting

§8 What GIS needs from the initial toolchain

  • Artifact/container registry — the single hard dependency: the custom GeoServer image and in-house plugin JARs must live somewhere (ties into ADR-0007).
  • CI able to run the existing per-subsystem test suites (plain bash + kubectl against a throwaway cluster).
  • Nothing exotic: the whole reference stack runs on a single-node k3s.

§9 Sprint 0 — the vertical slice already exists

The agenda asks Sprint 0 to demonstrate Source → Ingestion → Messaging/Processing → Storage → API → UI. The reference implementation already covers most of it, end-to-end and tested:

flowchart LR
    SRC["Source<br/>(model runs, sat images,<br/>observations, basemaps)"] --> ING["Ingestion<br/>(convert to COG,<br/>write index row)"]
    ING --> ST["Storage<br/>(S3 + PostGIS/Timescale)"]
    ST --> API["API<br/>(OGC: WMS/WFS/WPS,<br/>time + elevation + runs)"]
    API --> UI["UI<br/>(any OGC client)"]
    style UI stroke-dasharray: 5 5
Hold "Alt" / "Option" to enable pan & zoom

Proven today (each item = a rerunnable test suite): database bootstrap, image build, 3-replica cluster with config propagation and shared sessions, S3 tiles + COG rasters, model/satellite mosaic ingestion with time+elevation+run dimensions, observation tables + views, basemaps, server-side interpolation. The full chain was re-deployed from scratch on a second cluster using only the written runbooks, with zero deviation — the strongest durability evidence we have.

Deliberately not built yet (platform-level decisions the workshop should own):

Gap Why it waits
Messaging/eventing GIS doesn't need it (ADR-0010); if the platform adopts a bus, ingestion plugs into it upstream
Identity / RBAC integration GIS must federate with the platform IdP — the IdP choice comes first
UI / visualization client Any OGC client works today; the common UI framework choice belongs to the workshop
Observability stack Needs the platform-wide monitoring choice; biggest known gap
Data lifecycle / retention Mechanism is ready to build (time-indexed tables), but the retention owner and policy are not defined yet
Real GTS decoders Ingestion conventions are fixed; decoders (SYNOP/METAR/BUFR/GRIB) are the first real product work

§10 30/90-day view (GIS slice)

  • First 30 days: registry + CI in place, reference stack redeployed on the team's environment (the runbooks are written and proven), workspace organization decided against the real inventory (ADR-0002 — deliberately still open), identity integration designed.
  • First 90 days: first real GTS decoders feeding the platform, area products with validity periods (SIGMET/AIRMET/GAMET/TAF) as interval-based time layers, request-time palette mechanism generalized, observability subsystem.

Where to see it

  • Documentation — this site: vision, plain-language explanation, arc42 architecture, 8 runbook guides, 13 ADRs.
  • Live demo — a 3-replica cluster serving the full stack (model layers with time/elevation/run navigation, satellite mosaics, observations, interpolated surfaces, cached tiles) is deployed and can be shown during the workshop.