CRS Governance and Reprojection Standards

Coordinate reference systems are the one dimension of a spatial product that cannot be renegotiated after the fact: get the CRS wrong and every distance, intersection, and join computed downstream is quietly incorrect while every schema field still validates. This reference sits inside Geospatial Data Mesh Fundamentals and defines how a federated estate governs CRS across many independently owned domains — declaring a canonical storage CRS, reprojecting only at domain boundaries, and delivering per output port in the projection each consumer expects. It builds directly on Spatial Domain Boundary Design, because the boundary is exactly where reprojection is allowed to happen, and on Metadata Cataloging for Raster/Vector, which records the declared crs_epsg that this governance enforces. The recurring failures it prevents are mundane and expensive: axis-order inversion, precision loss from repeated round-trips, and mercator-metre math applied to EPSG:4326 degrees.

Figure — Sources in mixed CRSs are reprojected to a canonical EPSG:4326 store at ingest, then reprojected again only at delivery into the projection each output port serves.

CRS reprojection flow from mixed sources through a canonical store to per-port delivery Three sources on the left in EPSG:4326, EPSG:32633 UTM 33N, and EPSG:3857 web mercator all flow into a single reproject step at the ingest boundary that converts them to EPSG:4326. The normalized data lands in a canonical store holding EPSG:4326 in lon/lat order as the single source of truth. From the store, delivery reprojects at the output boundary into two ports: EPSG:3857 vector tiles for web maps, and EPSG:4326 features for the OGC API. A note states that EPSG:4326 is stored and delivered lon/lat, with axis order asserted at every boundary. → 3857 → 4326 EPSG:4326 native source EPSG:32633 UTM 33N source EPSG:3857 web mercator src Reproject ingest boundary → EPSG:4326 Canonical store EPSG:4326 lon/lat single source of truth EPSG:3857 tiles web mercator MVT EPSG:4326 features OGC API Features Axis order: EPSG:4326 is stored and delivered lon/lat order asserted explicitly at every reprojection boundary

Architectural Boundaries & Design Rationale

CRS governance rests on one principle: there is exactly one canonical storage CRS for the mesh, and every product is reprojected into it at the moment it crosses an ingest boundary. This site standardizes on EPSG:4326 for canonical storage — the concrete rollout is documented in Standardizing on EPSG:4326 Across Domains — while delivery ports may serve any approved projection the consumer needs. Reprojection is confined to the two boundaries, ingest and delivery, and is forbidden in the interior. That confinement is not stylistic; it directly eliminates the failure modes that a federated estate accumulates when every domain reprojects wherever it likes.

Four concrete failures motivate the standard:

  • Axis-order inversion. EPSG:4326 is officially latitude-then-longitude, but most tooling and every GeoJSON payload use longitude-then-latitude. A domain that follows the authority order where its neighbours follow the tooling order produces geometry that lands in the wrong hemisphere. The contract must assert lon_lat explicitly, exactly as Data Contracts for Spatial Products records it.
  • Repeated round-trip precision loss. Reprojecting 4326 → 3857 → 4326 across successive interior hops accumulates floating-point drift and can shift vertices by centimetres to metres. Reprojecting only at boundaries caps the number of transforms a coordinate ever undergoes.
  • Mercator-metre math on degrees. A consumer that runs a buffer or distance query assuming metres against EPSG:4326 degrees computes a nonsense result that no schema check catches.
  • Silent cross-domain CRS mismatch. Two domains joined on a shared extent but stored in different CRSs produce empty or shifted joins. A single canonical store makes every interior geometry comparable by construction.

The delivery side is where governance meets consumer reality. A tile port serves EPSG:3857 because web map clients demand web mercator; a features port serves EPSG:4326 for OGC API Features. Both reproject from the canonical store at the output boundary, so the store never holds more than one projection and the ports never leak a non-canonical CRS back into storage.

Specification & Contract Reference

CRS governance is expressed as a small set of enforceable parameters attached to every domain and output port. These are validated at registration and at the boundary gate.

Parameter Scope Constraint / Convention Rationale
canonical_crs Mesh EPSG:4326 Single interior projection; never overridden per domain
canonical_axis_order Mesh lon_lat Explicit to defeat authority/tooling ambiguity
source_crs_allowlist Ingest [4326, 3857, 4269, 32610, 32611, 32633] Only approved projections may be reprojected in
reproject_boundaries Topology ingest, delivery Interior reprojection is prohibited
delivery_crs Output port 3857 (tiles) | 4326 (features) Per-port projection served to consumers
min_precision_decimals Quality 6 (~0.11 m) Guards against round-trip precision loss
transform_pipeline Governance Named PROJ pipeline or EPSG code Pinned so a transform is reproducible and auditable
datum_shift_grid Governance e.g. null | NAD83→WGS84 Declared when a datum shift is required, not implicit

The distinction between a bare CRS change and a datum shift matters: reprojecting EPSG:32633 to EPSG:4326 is a coordinate operation within the WGS 84 datum, whereas moving from EPSG:4269 (NAD83) involves a datum transformation whose grid must be declared and pinned. Leaving the datum shift implicit is how “correct” reprojections drift by a metre.

Production Implementation

Reprojection at a boundary must be idempotent and reproducible: the same input and the same pinned transform always yield byte-comparable geometry, and re-running the step never compounds error. Below, ogr2ogr normalizes an incoming vector source to the canonical EPSG:4326 at the ingest boundary, and a PostGIS ST_Transform produces the EPSG:3857 delivery view — followed by a validation query that proves the transform did not silently corrupt the extent. Zero-trust applies here too: the boundary trusts only the declared source CRS after verifying it against the allowlist, never a guessed projection.

bash
#!/usr/bin/env bash
set -euo pipefail

SRC="${1:?source dataset}"          # e.g. parcels_utm33.gpkg (EPSG:32633)
SRC_EPSG="${2:?declared source EPSG}"

# Zero-trust: refuse any source CRS outside the enterprise allowlist.
case "$SRC_EPSG" in
  4326|3857|4269|32610|32611|32633) ;;
  *) echo "FATAL: EPSG:${SRC_EPSG} not in source allowlist"; exit 1 ;;
esac

# Reproject to canonical EPSG:4326 at the ingest boundary.
# -s_srs is set explicitly (never trust the file's embedded CRS blindly);
# lon/lat axis order is forced so authority ordering cannot leak in.
ogr2ogr -f GPKG parcels_4326.gpkg "$SRC" \
  -s_srs "EPSG:${SRC_EPSG}" -t_srs EPSG:4326 \
  -lco GEOMETRY_NAME=geom --config OGR_CT_FORCE_TRADITIONAL_GIS_ORDER YES
echo "normalized ${SRC} (EPSG:${SRC_EPSG}) -> EPSG:4326"

What has to be pinned for a reprojection to be reproducible on another machineA reprojection is reproducible only when four things are fixed: the source CRS as declared by the producer, the transformation pipeline chosen explicitly rather than by the library, the grid package shipped as a versioned image dependency, and the PROJ version itself. All four flow into the warp, which produces the EPSG:4326 artifact. Each of the first three drops onto a rail leading to the same outcome — coordinates that differ silently between workers — because PROJ selects a best-available transformation from whatever grids happen to be installed on the host.Declared source CRSfrom the producerPinned pipelineexplicit, not chosenGrid packageversioned in the imageEPSG:4326 artifactreproducible++warpassumed → systematic offsetauto-selected → host-dependenthost-installed → not reproducibleSilent metre-scale driftvalid geometry, wrong place

sql
-- Canonical storage holds EPSG:4326; delivery views reproject at the output port.
-- ST_Transform is deterministic for a pinned source/target pair.
CREATE MATERIALIZED VIEW parcels_tiles_3857 AS
SELECT parcel_id,
       ST_Transform(geom, 3857) AS geom          -- delivery boundary → web mercator
FROM   parcels_4326;                             -- interior stays EPSG:4326

-- Validation: the reprojected extent must round-trip back within tolerance,
-- proving no axis flip or datum drift crept in at the boundary.
SELECT parcel_id
FROM   parcels_tiles_3857 t
JOIN   parcels_4326 c USING (parcel_id)
WHERE  NOT ST_Equals(
         ST_SnapToGrid(ST_Transform(t.geom, 4326), 0.000001),
         ST_SnapToGrid(c.geom, 0.000001)
       );
-- Zero rows returned == reprojection is lossless within 1e-6 degrees.

Run the validation query in CI after every reprojection change. A non-empty result set means the transform pipeline, the source CRS declaration, or the axis order is wrong — and the delivery view must be rebuilt before it is published, never patched in place.

Diagnostic Runbook

When consumers report geometry in the wrong place, empty joins, or distances that make no sense, isolate the CRS fault in order.

  1. Confirm the declared source CRS. Run ogrinfo -so -al source.gpkg | grep -i srs and compare against source_crs_allowlist. A source outside the allowlist should have been rejected at ingest. Remediation: reproject upstream to an allowlisted CRS or add the projection through a governed allowlist change, never silently.
  2. Check axis order. If features are mirrored or in the wrong hemisphere, the boundary likely honored authority lat/lon order. Remediation: force OGR_CT_FORCE_TRADITIONAL_GIS_ORDER YES (or PostGIS ST_FlipCoordinates on the offending set) and re-run.
  3. Detect interior reprojection. Search pipeline code for ST_Transform/-t_srs calls outside the ingest and delivery boundaries. Remediation: remove them; the interior must remain EPSG:4326.
  4. Measure round-trip drift. Run the validation query from the implementation section. Remediation: if rows return, pin the transform_pipeline and, for datum-shifted sources, install and declare the datum_shift_grid.
  5. Verify delivery projection. Confirm the tile port serves EPSG:3857 and the features port serves EPSG:4326 with ST_SRID(geom). Remediation: rebuild the materialized view with the correct target SRID.
  6. Reconcile against the catalog contract. Cross-check the served CRS against the declared crs_epsg recorded in Metadata Cataloging for Raster/Vector. Remediation: if they diverge, the contract or the port is wrong; treat any change to crs_epsg as a breaking version bump.

SLA Targets & Performance Baselines

CRS governance carries measurable guarantees that feed the mesh’s alerting.

Metric Target Alert Threshold Remediation Action
Round-trip reprojection error < 1e-6 degrees any row failing the validation query Pin transform pipeline; install datum grid
Non-canonical interior geometry 0 features any interior SRID ≠ 4326 Remove interior transform; re-normalize at ingest
Axis-order inversions 0 any mirrored feature detected Force lon/lat order; flip and re-publish
Source CRS allowlist violations 0 admitted any out-of-allowlist source registered Reproject upstream; deny at ingest gate
Delivery reprojection latency (p95) < 200 ms > 500 ms for 5 min Materialize view; add spatial index on delivery
Datum-shift declaration coverage 100% of shifted sources any implicit datum change Declare and pin datum_shift_grid

Datum Shifts and the Metre Nobody Sees

The failure that CRS governance exists to prevent is almost never a visible one. A dataset reprojected through the wrong datum transformation does not look wrong: the polygons are valid, the topology is intact, the extent is plausible, and the features land within a few metres of where they belong. Nothing in a rendering pipeline, a topology check, or a schema validator will object. The error surfaces months later, when a utility crew digs where a reprojected asset said the cable was and finds it two metres away.

The mechanism is worth stating precisely because it is routinely conflated with projection. A projection change is mathematical and lossless within its own datum: converting EPSG:4326 to EPSG:3857 is a closed-form transformation of the same underlying positions onto a different plane. A datum change is empirical: it relates two different models of the Earth’s shape and orientation, and the relationship between them is measured, not derived. Going from a national datum to WGS 84 is not a formula; it is a best-fit approximation, and the quality of that approximation depends entirely on which transformation you used.

Transformation method Typical accuracy When it is correct to use
Null / identity (assumed same datum) 0 m, or 100+ m if wrong Only when both CRS genuinely share a datum
3-parameter Helmert (geocentric translation) 3–10 m Coarse regional work where no grid exists
7-parameter Helmert (position vector / coordinate frame) 1–3 m Continental-scale work with published parameters
Grid-based (NTv2, GEOID, .gsb shift files) 0.01–0.2 m Survey-grade work; the only acceptable method for cadastral data

Positional error introduced by each datum transformation methodFive transformation methods and the typical positional error each introduces, measured against a 0.2 metre survey-grade tolerance drawn as a dashed line. Assuming a null transformation when the datums actually differ can be over 100 metres wrong. A 3-parameter Helmert lands around 6 metres, a 7-parameter Helmert around 2. Only grid-based methods — NTv2 shift files — come inside the survey tolerance at about 0.05 metres. The bars make the governance point directly: the transformation, not the target CRS, decides whether a coordinate is defensible.assumed null (wrong)118 minvisible to every check3-parameter Helmert6 m7-parameter Helmert2 mgrid-based (NTv2)0.05 mthe only survey-grade optionprojection only, same datum0.001 mclosed-form, losslesssurvey tolerance

The governance requirement follows directly: the transformation is part of the contract, not an implementation detail of whoever ran the reprojection. A product that declares EPSG:4326 has said what its coordinates mean only if it also records how it got there from the source datum. Two artifacts of the same parcel, both correctly labelled EPSG:4326, can differ by metres if one went through a 3-parameter Helmert and the other through an NTv2 grid — and a consumer joining them will produce slivers, gaps, and false topology errors that look like data-quality problems in the source.

In practice this means three things a domain must do. Pin the transformation pipeline explicitly rather than letting the library choose: modern PROJ selects a “best available” transformation based on the grids installed on the machine, so the same command on two workers with different grid packages produces different coordinates. Record the pipeline and the PROJ version in the artifact’s metadata, so an unexplained shift can be diagnosed rather than argued about. And ship the grid files as a versioned dependency of the pipeline image, not as an operator’s local installation — a reprojection whose result depends on what happened to be installed on the machine that ran it is not reproducible, whatever the cache key says.

The one case that deserves a hard stop is a source with no declared datum at all. There is a persistent temptation to assume WGS 84, because most modern data is, and because the assumption is right often enough to feel safe. It is the single most expensive assumption in the field: when it is wrong, the error is a systematic offset across the entire dataset, it is invisible to every automated check, and it propagates into every derived product before anyone notices. Fail the ingest, quarantine the artifact, and make the producing domain declare it.

A last governance point concerns vertical position, which is routinely forgotten because most spatial products are treated as two-dimensional. Elevation is measured against a vertical datum — an ellipsoid, a geoid model, or a local tidal datum — and these differ from each other by tens of metres in places. A product carrying z values without declaring its vertical datum has published numbers whose meaning is unknown, and the failure is worse than the horizontal case because there is no visual check at all: a building height, a flood level, and a bathymetric depth all look reasonable regardless of which surface they were measured from. Where a product publishes elevation, the vertical datum belongs in the contract alongside the horizontal CRS, and a transformation between vertical datums requires a geoid model shipped and versioned exactly like a horizontal grid.

Finally, the governance body’s job here is narrow and worth keeping narrow. It sets the canonical storage CRS, maintains the approved transformation registry, and owns the grid package that pipelines depend on. It does not review individual reprojections, and it does not arbitrate which CRS a domain works in internally. A CRS council that reviews changes case by case becomes the bottleneck the mesh was built to remove; one that publishes an approved transformation registry and lets automated checks enforce it scales without becoming a queue.

Audit expectations follow from all of this. Because a reprojection’s result depends on the transformation, the grid package, and the library version, an audit of a positional claim needs all three recorded against the artifact — not merely the source and target CRS. The minimum record that makes a coordinate defensible is the source CRS as declared by the producer, the target CRS, the transformation pipeline actually applied, the grid package version, the PROJ version, and the identity of the run that produced it. Every one of those is available at pipeline runtime and costs nothing to persist; reconstructing any of them afterwards ranges from tedious to impossible. Where positional accuracy carries legal or safety weight — cadastral boundaries, utility networks, flood extents used in planning decisions — that record is the difference between a defensible answer and an argument.

Governance & Compliance Notes

CRS is a compliance surface, not merely a technical one. Only projections on the source_crs_allowlist may enter the mesh, because an unapproved projection silently breaks every cross-domain join and undermines downstream SLAs, and the allowlist is the single enforcement point for that rule. Every reprojection at a boundary emits an audit event recording the source CRS, target CRS, the pinned transform_pipeline, and any datum_shift_grid applied — this trail is what lets an auditor reconstruct exactly how a coordinate reached its delivered position. Because a CRS change is never backward-compatible, it is always governed as a breaking change under Versioning Spatial Data Contracts with SemVer: the crs_epsg in the contract and the projection served at the port must agree, and any divergence forces a major version and a parallel migration rather than an in-place edit. Held to this standard, the mesh keeps one canonical truth, reprojects only where it is accountable to, and delivers each consumer the projection it needs without ever polluting the interior.