The zero-server model
When you open Off The Pace, your browser downloads data and runs queries itself. There is no compute server waiting for your requests. The entire runtime is:Cross-origin isolation (COOP / COEP)
DuckDB-Wasm requires aSharedArrayBuffer for its multi-threaded worker. Browsers only expose SharedArrayBuffer in a cross-origin-isolated context, which requires two HTTP response headers on every page:
Cross-Origin-Resource-Policy: cross-origin, which the bucket’s CORS policy provides. Removing or weakening either header causes the DuckDB worker to silently fall back to a single-threaded mode where queries still work but run several times slower.
The runtime manifest
The app never hard-codes data file paths. Instead, a lightweight manifest JSON file is fetched at startup:Cache busting
GCS edge caches have a default TTL of one hour. Parquet files are served with an appended?v=<build_hash> query string baked into the manifest. When a new build is published, the manifest points to new ?v= URLs; the CDN serves fresh files even if the previous version is still cached under the old URL. The manifest itself is served with Cache-Control: no-cache so it is always re-fetched.
Data shape
The Parquet files on the CDN are the gold-mart tables produced by the dbt pipeline, exported verbatim from the warehouse. The tables the app reads at runtime include:
DuckDB-Wasm registers each Parquet file as a virtual table, so every SQL query in the app runs against the same schema as the warehouse no translation layer.
ONNX inference
The XGBoost models (quantile regressors, cliff classifier, stint-life regressor) are exported to ONNX and bundled alongside the app. At warmup, ONNX Runtime Web loads the model into a WebAssembly session. Subsequent calls score a feature vector and return quantile predictions, cliff probability, and stint-life estimates in a single synchronous call no fetch, no server. The Degradation Simulator’s interactive sliders update predictions in under 5 ms on a mid-range device.Source code and deployment
The app is a React + Vite single-page application hosted on Firebase Hosting. Code changes are deployed by CI; data changes (new Parquet builds) are published separately viascripts/publish_cdn.sh and take effect on next page load without a code deploy. The two cycles are deliberately decoupled so a broken data build does not require a code rollback and a new code deploy does not require a data rebuild.