Skip to main content
Script: scripts/data_migrations/relabel_oura_hrv_sdnn_to_rmssd.py

Problem

Oura reports RMSSD-based HRV, but the ingestion path historically stored those values under the SDNN series type (id=3) instead of RMSSD (id=7). The numeric values are correct — only the metric label (and therefore its unit semantics) was wrong. The ingestion path was fixed separately in backend/app/services/providers/oura/data_247.py, so new Oura HRV samples are now stored as RMSSD. This script corrects pre-existing rows in data_point_series and data_point_series_archive.

What it does

For provider='oura' rows only, it relabels every HRV series from SDNN (id=3) to RMSSD (id=7). The scope is strict — other providers’ genuine SDNN data (e.g. Apple, Ultrahuman) is left untouched. Both data_point_series and data_point_series_archive are updated.

Conflict handling

After the ingestion fix, a re-sync can write a correct RMSSD row at the same key as an old SDNN row, which would collide with the unique constraint on relabel:
  • data_point_series — unique on (data_source_id, series_type_definition_id, recorded_at)
  • data_point_series_archive — unique on (data_source_id, series_type_definition_id, bucket_start_at, aggregation_type)
In that case the stale SDNN duplicate is deleted (the RMSSD row already holds the same Oura value) rather than relabeled.

Idempotency

Once relabeled, rows no longer match the SDNN filter, so re-runs are no-ops. The script is wired into container startup (scripts/start/app.sh) and runs automatically on every deploy until removed.
This script is scheduled for removal after 2026-09-01, once all deployments have migrated.

Usage

# Preview affected rows (recommended first step)
docker compose exec app uv run python scripts/data_migrations/relabel_oura_hrv_sdnn_to_rmssd.py --dry-run

# Apply corrections
docker compose exec app uv run python scripts/data_migrations/relabel_oura_hrv_sdnn_to_rmssd.py

Options

FlagDescription
--dry-runPrint how many rows would be relabeled and how many duplicates would be removed. No changes made.

Dry run output

data_point_series:         Would relabel 1284, remove 0 duplicate(s)
data_point_series_archive: Would relabel 96, remove 0 duplicate(s)

Dry run — no changes made.
  • Commit 3bcf2973 — the ingestion fix (oura/data_247.py) that stores new Oura HRV as RMSSD.
  • Coverage Matrix — Oura HRV is listed under heart_rate_variability_rmssd.