Spatial Product Lifecycle Management

The operational discipline that governs how a geospatial asset is provisioned, versioned, promoted, deprecated, and retired as an autonomous product inside a federated mesh.

Enterprise geospatial operations require a disciplined transition from monolithic GIS repositories to federated, domain-aligned data products. Spatial product lifecycle management establishes the operational framework for provisioning, versioning, routing, and retiring geospatial assets so that every tileset, coverage, and feature collection behaves as a versioned, SLA-bound product rather than a static file drop. This page sits inside the Geospatial Data Mesh Fundamentals reference and assumes you have already separated your estate into autonomous domains as described in Spatial Domain Boundary Design and constrained what each product may publish through Scoping Rules for Spatial Products. Where boundary design answers who owns this geometry and scoping answers what may be published, lifecycle management answers how a product moves safely from experiment to production and back out of service without breaking the consumers who depend on it. The intended readers are data architects, platform engineers, GIS data stewards, and enterprise platform teams who must make those transitions deterministic, observable, and reversible.

Figure — The managed lifecycle of a spatial product; each transition is gated by quality checks and deprecation windows.

The managed lifecycle of a spatial product as a gated state machine A spatial product enters at an experimental state and advances left to right through four states — Experimental, Production, Deprecated, Archived — before retiring. Each transition is an explicit gated event: Experimental is promoted to Production after quality gates pass, Production becomes Deprecated when superseded by a successor version, and Deprecated becomes Archived once the deprecation window elapses. promote gates pass superseded by successor window elapsed Experimental pre-production breaking changes ok Production SLA-bound CI/CD writes only Deprecated read-only migration window Archived cold storage routes released

Architectural Boundaries & Design Rationale

A spatial product must be treated as an independent domain boundary with explicit ingress and egress controls. The architectural shift moves away from shared enterprise geodatabases and centralized ETL orchestration toward decentralized ownership with standardized interoperability contracts. Lifecycle management is what keeps that decentralization from degenerating into chaos: without managed state transitions, a federated estate accumulates undocumented overwrites, silent projection changes, and orphaned tilesets that consumers still query. The lifecycle states — Experimental, Production, Deprecated, Archived — exist precisely so that every change to a product is an explicit, gated event rather than an in-place mutation.

The failure modes this pattern prevents are concrete. Silent overwrite occurs when a domain republishes the same version with different geometry, so a consumer that pinned v1.2.0 suddenly receives different features; immutable artifact registries close this by rejecting any write to an existing version tag. CRS drift occurs when a product changes projection between releases, so downstream joins that assumed EPSG:4326 misalign by hundreds of metres after an unannounced move to EPSG:3857; encoding the CRS into the version string and validating it at promotion closes this. Dangling consumption occurs when a product is deleted while live traffic still references it; the Deprecated and Archived states with explicit deprecation windows give consumers a bounded migration period instead of an abrupt failure. Cross-domain leakage occurs when a retired product’s compute plane is reused by another domain without re-scoping, which is why retirement must release routing and policy bindings, not just storage.

Platform engineers enforce these boundaries at the API gateway and service mesh layers, ensuring that vector tile requests, raster processing jobs, and metadata queries are routed exclusively to the owning domain’s compute plane. The routing patterns themselves are owned by the Federated Ownership & Routing Architecture reference and detailed in Cross-Domain Routing Strategies; lifecycle management consumes those routes and is responsible only for binding the correct product version to a route and unbinding it cleanly on retirement. Security boundaries are enforced through zero-trust network policies, attribute-based access control (ABAC), and cryptographic signing of spatial payloads, so a product that has transitioned to Deprecated can have its write path revoked while its read path remains available for the deprecation window. The canonical decoupling patterns this section builds on are codified in Spatial Domain Boundary Design, and the rationale for treating datasets as products at all is established in Product Thinking for GIS Datasets.

Specification & Contract Reference

Every lifecycle transition is governed by a declared contract. A product manifest carries the fields below, and the platform admits a transition only when each field validates against the gate for the target state.

Lifecycle states and gates

State Meaning Entry gate Read access Write access
Experimental Pre-production, breaking changes allowed Schema-valid manifest registered Domain team only Domain team
Production Stable, SLA-bound, consumer-facing Quality gates + topology + CRS validation pass All authorized consumers CI/CD pipeline only
Deprecated Superseded, read-only, migration window open Successor version in Production Existing consumers None (frozen)
Archived Retired, cold storage, routes released Deprecation window elapsed, no live traffic Restore-on-request None

Version string grammar

Versioning adheres to semantic conventions extended for geospatial context. A version tag encodes the projection and resolution so that a CRS or resolution change is impossible to ship without an explicit version bump:

v<major>.<minor>.<patch>-crs:<EPSG>-res:<resolution> — for example v1.2.0-crs:EPSG:4326-res:10m or v2.1.0-crs:EPSG:3857-res:0.5m.

Field Rule Failure if violated
major Increment on breaking schema or CRS change Consumers receive incompatible geometry
minor Increment on additive, backward-compatible change None
patch Increment on metadata or quality fix, geometry unchanged None
crs Must be one of the domain CRS allowlist (EPSG:4326, EPSG:3857, EPSG:32633) Reprojection misalignment downstream
res Must satisfy the resolution limit declared in scoping rules Bandwidth and classification breaches

Routing and policy fields

Field / header Layer Purpose
X-Domain-ID Gateway Pins a request to its owning domain’s compute plane
X-Payload-Signature Gateway Cryptographic signature of the spatial payload, verified per domain key
productId Manifest Stable identifier across all versions of a product
processingProvenance.pipelineId Manifest Upstream lineage anchor for catalog reconciliation
spatialExtent / temporalCadence Manifest Scoping fields; breaking changes require a major bump

Manifest registration itself flows into the federated catalog described in Metadata Cataloging for Raster/Vector, which is the discovery surface consumers use to find a product version and its current lifecycle state.

Production Implementation

Three runnable artifacts cover the lifecycle: a zero-trust routing policy that pins live traffic to the owning domain, an idempotent manifest registration pipeline that feeds the catalog, and a GitOps promotion workflow that swaps product versions atomically.

Zero-trust routing policy (OPA / Rego)

Implementing ABAC at the gateway requires declarative policy-as-code. The following Open Policy Agent (OPA) Rego policy enforces spatial extent validation and CRS compliance before routing requests to downstream tile servers. The default-deny posture is the zero-trust requirement: a request is rejected unless every condition matches.

rego
package spatial.gateway

import rego.v1

# Default deny — zero-trust posture
default allow = false

# Allow only if the request matches the owning domain's contract
allow if {
    input.method == "GET"
    input.path = ["tiles", domain, _, _, _, _]
    domain == input.headers["X-Domain-ID"]
    is_valid_crs(input.query["crs"])
    within_spatial_extent(input.query["bounds"], data.domain_extents[domain])
}

is_valid_crs(crs) if {
    crs in {"EPSG:4326", "EPSG:3857", "EPSG:32633"}
}

within_spatial_extent(bounds, extent) if {
    bbox := split(bounds, ",")
    min_x := to_number(bbox[0])
    min_y := to_number(bbox[1])
    max_x := to_number(bbox[2])
    max_y := to_number(bbox[3])
    min_x >= extent.min_x
    min_y >= extent.min_y
    max_x <= extent.max_x
    max_y <= extent.max_y
}

Idempotent manifest registration

Metadata registration must be idempotent so that a CI/CD retry never creates catalog drift. The pipeline below validates each manifest against the schema, computes a deterministic content hash, and registers the product only when the hash differs from the catalog state — so re-running it is a no-op:

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

MANIFEST_DIR="./spatial-manifests"
SCHEMA_PATH="./schema/spatial-product-manifest.schema.json"

for manifest in "${MANIFEST_DIR}"/*.json; do
  # 1. Schema validation (idempotent)
  python3 -m jsonschema --instance "${manifest}" "${SCHEMA_PATH}"

  # 2. Compute deterministic content hash
  HASH=$(sha256sum "${manifest}" | awk '{print $1}')

  # 3. Register only if the hash differs from catalog state
  PRODUCT_ID=$(jq -r '.productId' "${manifest}")
  EXISTING=$(curl -sf "${CATALOG_API}/products/${PRODUCT_ID}/hash" || echo "")
  if [ "${EXISTING}" != "${HASH}" ]; then
    curl -sf -X POST "${CATALOG_API}/products" \
      -H "Content-Type: application/json" \
      -d @"${manifest}"
    echo "Registered: ${PRODUCT_ID}"
  else
    echo "Skipped (idempotent): ${PRODUCT_ID}"
  fi
done

Atomic promotion and rollback (GitOps)

Promotion pipelines must enforce cryptographic checksums, spatial topology validation, and automated regression testing against baseline extents before a version reaches Production. Immutable artifact registries prevent unauthorized overwrites, while signed releases ensure supply-chain integrity. Leverage Kubernetes-native GitOps controllers to manage spatial tileset promotions so that a version swap is atomic and self-healing:

yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: spatial-product-urban-landcover
spec:
  project: geospatial-mesh
  source:
    repoURL: https://git.enterprise.internal/spatial-products/urban-landcover.git
    targetRevision: v2.1.0-epsg:3857-res:0.5m
    path: deploy/overlays/prod
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true
      - ApplyOutOfSyncOnly=true
  destination:
    server: https://kubernetes.default.svc
    namespace: spatial-prod
Atomic promotion and rollback flow for a spatial product version An experimental candidate version is promoted only after passing four promotion gates — quality regression, topology validation, CRS allowlist, and Cosign signature verification. Passing artifacts are published immutably into an append-only registry that holds the new version and the previous version. A GitOps controller reconciles the production route to the new version with an atomic swap. A dashed rollback path re-points the production route to the previous version, which is still held in the registry. Experimental artifact candidate vN Promotion gates — all must pass Quality regression Topology valid CRS allowlist Cosign verify Immutable registry vN — newly promoted vN-1 — kept (rollback) promote publish vN (append-only) GitOps controller automated sync · self-heal prune · atomic swap Production route serves vN · SLA-bound consumer-facing reconcile to desired vN atomic swap rollback — re-point route to vN-1 (still in registry)

Diagnostic Runbook

When a transition fails, work the following ordered checks; the first matching symptom is usually the root cause.

  1. Verify policy evaluation. Execute opa eval -i input.json -d policy.rego "data.spatial.gateway.allow" to confirm the routing decision is deterministic. A false result with a valid request usually means the X-Domain-ID header was stripped upstream.
  2. Trace mesh propagation. Use istioctl analyze or the equivalent service-mesh CLI to validate that VirtualService and DestinationRule objects restrict cross-domain egress and that the retired version’s route was actually unbound.
  3. Audit cryptographic signatures. Inspect X-Payload-Signature headers against domain-specific public keys; reject requests with expired timestamps or mismatched CRS claims.
  4. Detect schema and catalog drift. Run python3 -m jsonschema --instance manifest.json schema.json to verify backward compatibility, and reject manifests that change spatialExtent or temporalCadence without a major bump. If the catalog returns inconsistent state, compare updated_at timestamps against pipeline execution logs before forcing a re-register.
  5. Validate topology before promotion. Run ogrinfo -so -al tileset.gpkg and verify the Geometry Type and Layer SRS WKT match the declared domain CRS. Mixed geometry types or a projection mismatch must block promotion.
  6. Verify rollback. Execute argocd app rollback spatial-product-urban-landcover --revision <previous-sync-id> and confirm p95 query latency returns to baseline within 90 seconds.
  7. Confirm artifact integrity. Verify Cosign signatures with cosign verify --key domain-public.pem <image-or-artifact>; an unsigned artifact must trigger immediate pipeline termination.

SLA Targets & Performance Baselines

Spatial products instrument standardized telemetry — tile cache hit ratios, raster processing queue depths, and metadata synchronization latency — codified as Prometheus alerting rules and enforced via admission controllers.

Metric Target Alert threshold Remediation
Tile availability 99.95% < 99.8% (5m) Auto-scale tile cache nodes
Metadata sync latency < 15 min > 20 min Trigger catalog reconciliation job
Vector query p95 < 450 ms > 600 ms Optimize spatial indexes, verify CRS alignment
Policy evaluation time < 5 ms > 15 ms Audit Rego complexity, cache compiled policies
Deprecation window honored 100% Any early archival Halt archival job, restore read route

To diagnose an SLA breach, correlate spatial_tile_latency_seconds with opa_evaluation_duration_seconds — high latency in both points to a gateway policy misconfiguration. Confirm the declared manifest schema matches the live tile or vector payload via the contract validation pipeline, then apply automated scaling through a Horizontal Pod Autoscaler with custom metrics. If breaches persist beyond 15 minutes, trigger circuit-breaker routing to a fallback static tileset and notify the domain stewards.

Deprecation That Consumers Can Actually Act On

Deprecation is the lifecycle state that most often exists in name only. A product is marked Deprecated, an announcement goes out, a sunset date is set — and on the sunset date half the consumers are still calling it, because nothing in the process ever told them they were consumers. Making deprecation work is less about policy than about knowing who is affected and giving them something specific to do.

The first requirement is that consumers are identified by telemetry, not by a mailing list. Every request to an output port carries a caller identity from the zero-trust layer, so the set of active consumers of a version is a query, not an estimate. That query is what turns “we announced it” into “these eleven services called this version in the last 30 days, and these three still are”. A deprecation whose consumer list is derived from a wiki page is a deprecation that will overrun.

The second is that the sunset window is a function of the consumer’s release cadence, not the producer’s convenience. A consumer that ships weekly can migrate inside a month; one that ships quarterly under change control cannot, and setting a 30-day window for them guarantees either a breach or an emergency extension that teaches everyone that sunset dates are negotiable. Deriving the window from the slowest affected consumer’s cadence — and publishing that derivation — makes the date credible.

Deprecation element Weak form Form that works
Consumer identification Announcement to a list Query over caller identity in access telemetry
Sunset window Fixed 90 days for everything Two cycles of the slowest affected consumer
Migration target “Use the new version” Named successor version, with a diff
Progress signal Nothing until the date Per-consumer call volume against the deadline
Enforcement Turn it off Escalating: warning header, then throttle, then error
Rollback None Successor stays parallel until the last caller moves

Graduated deprecation, so risk is spread across the window instead of landing on one dateFive stages across a deprecation window. At day zero the successor publishes and both versions run in parallel. From day seven every response to the old version carries a deprecation header, so a consumer reading its own logs finds out without being told. At day thirty the per-consumer call volume is reviewed against the deadline and the window is extended if the slowest consumer cannot make it. From day sixty the old version is deliberately and visibly throttled, which is impossible to ignore and breaks nothing. Only at the sunset date does it return an error, and only once the caller set is empty.Day 0 · successor liveboth versions parallelDay 7 · headerdeprecation on every responseDay 30 · reviewcallers vs deadlineDay 60 · throttlevisible, breaks nothingSunset · erroronly when callers = 0The window is two cycles of the slowest affected consumer, not a fixed 90 days

The third requirement is graduated enforcement, because a hard cutover concentrates all risk into one moment. The sequence that works starts with a deprecation header on every response, so a consumer that reads its own logs finds out without being told; moves to deliberate, well-labelled throttling that makes the deprecation impossible to ignore but does not break anything; and only then returns an error. Each stage is announced and each is reversible, so a consumer who genuinely cannot move has a visible opportunity to say so before the outage rather than during it.

Finally, deprecation must name a successor with a diff. “Migrate to v2” is not actionable; “v2 renames parcel_id to parcel_ref, adds a required survey_date, and changes the storage CRS from EPSG:32633 to EPSG:4326” is a work item a consumer can estimate. Where the successor’s contract has been generated from a structural diff of the two versions, that list already exists — publishing it is the cheapest thing a producer can do to make a deprecation land on time.

One organisational note: deprecation only works when the producing domain is not the only party with an interest in it finishing. Where a successor version exists but consumers have no deadline pressure, migration reliably stalls at eighty percent, and the producer is left maintaining two versions indefinitely. Publishing the per-consumer migration progress somewhere both sides can see it — call volume against the deadline, by caller identity — turns a producer’s request into a shared, visible commitment, which is generally enough without any escalation at all.

Governance & Compliance Notes

Lifecycle transitions are governance events and must leave an audit trail. Every promotion, deprecation, and archival should emit an immutable record capturing the actor, the source and target version strings, the CRS and resolution, and the Cosign signature digest, so a product’s full provenance is reconstructable from the catalog alone. Policy-as-code hooks run at two points: the admission controller blocks any transition whose manifest fails schema or topology validation, and the gateway Rego policy blocks any read that falls outside the product’s declared extent or CRS allowlist. Both hooks reference the same scoping contract, which keeps governance consistent between publication time and query time.

Jurisdictional constraints frequently shape archival and deletion. A product carrying regulated spatial data — cadastral boundaries, critical-infrastructure footprints, or personally locating telemetry — may have a minimum retention period that prevents early archival, or a data-residency rule that forbids restoring an archived artifact into a different region’s compute plane. Encode these as policy fields on the manifest so the lifecycle controller enforces them automatically rather than relying on operator discipline. For authoritative interoperability standards consult the OGC API - Features specification, and for policy-as-code implementation patterns reference the Open Policy Agent Documentation.