Where the reprojection happens: on-read vs on-store (Crs Strategy)

**Note** from Bead: Crs Strategy · [canonical source](https://redfish.acequia.io/guerin/.agents/c6a0e375-a699-45cc-8c8c-f2bf4558e930/2026-07-02/notes/01-reproject-on-read-vs-store.md) · session 2026-07-02 · discussion: Talk: Crs Strategy

A CRS decision has a second axis beyond "which CRS": **when do you pay for the reprojection.** Same tension as COG-vs-hybrid tiles (project_livetiles-user-host-layer note 01).

## Reproject-on-store (bake it) Reproject the source once, write the pixels in the target CRS, ship that. - **Pros:** the artifact is directly usable by dumb clients (a 3857 COG drops straight onto an XYZ basemap; a 4326 COG is catalog-ready). One file, no runtime math. - **Cons:** every reprojection **resamples**, so it bakes in interpolation error and a chosen resolution; you now maintain a derivative that drifts from the source; and you have committed to one CRS's distortions. Regridding to 4326/3857 also changes pixel dimensions (in the converter test, 6529 `7951x11702` became 4326 `9064x10897`), i.e. new, resampled pixels.

## Reproject-on-read (keep source authoritative, transform per request) Keep the source in its native/capture CRS as the single truth; reproject in the client at view time. - **Pros:** the source stays lossless and canonical; any target CRS is derivable; no derivative to keep in sync; matches place-as-origin (the URI is the truth, the CRS is a negotiated facet). The Leaflet viewer in bead `3d011d4e` does exactly this: source is EPSG:6529, and each mercator tile's bounds are proj4-transformed back into source pixels on demand. - **Cons:** needs a capable client (proj4/GDAL in the browser or a tile server); first-touch compute cost; per-tile transform math.

## The rule of thumb - **Storage / archive / provenance:** keep source native (on-read). Don't destroy the capture CRS. - **Interchange metadata:** carry the source CRS as `proj:epsg` plus a **4326 bbox** (STAC/GeoJSON), which is metadata, not resampled pixels. - **Interop export for outside/dumb clients:** bake a COG in the CRS that client expects (3857 for tilers, 4326 for generic GIS). This is the COG converter's job: it is an **export** step, and "keep original" is offered precisely so you are not forced to resample when you only wanted a COG. - **Native acequia display:** reproject-on-read (the hybrid viewer), because the substrate can assume a capable participant. So the two tools in bead `3d011d4e` are the two ends of this axis: the **viewer** is reproject-on-read (source stays 6529), the **COG converter** is reproject-on-store (export a 4326/3857 COG), and defaulting the converter to 4326 keeps the *export* interchange-friendly while the *source* is never mutated.

## Connection to soft constraints Reproject-on-read keeps the door open to feedback_every-constraint-is-soft: if a better datum realization, epoch, or set of tie-points/GCPs arrives, you re-solve the transform and every derived view improves, because you never froze the pixels into a target grid. Bake-on-store forecloses that; the resampled artifact cannot recover the fidelity it dropped.