Back to Roadmap

Workout Syncing Infrastructure

Production-ready sync API. Proper error handling and validation, rate limiting, connection resilience, sync conflict resolution beyond last-write-wins. Batch processing improvements for large workout histories.

Updated for SYNTHESIS schema

Multi-source sync state

  • sync_states table is per-athlete per-source (not per-user single-row)
  • Each source (apple_health, garmin, strava, etc.) has its own anchor and sync status
  • Supports last_sync_status: 'success', 'partial', 'failed'

Same-source deduplication

  • UNIQUE(athlete_id, source, external_id) constraint prevents duplicate imports from the same provider
  • Upsert on conflict: update existing record if provider data has changed

Cross-source deduplication

  • Match on (athlete_id, start_date ±2min, activity_type, duration ±10%) to detect same activity from different sources
  • Open question: storage for duplicate links — duplicate_of FK vs junction table vs shared duplicate_group UUID (SYNTHESIS §13)
  • GPS overlap as a stronger signal when available

Priority-based conflict resolution (Open Wearables pattern)

  • source_priorities table: athlete-configurable provider priority (e.g., Apple Health > Garmin > Strava)
  • Device type priority within a provider: Watch > Band > Ring > Phone > Other
  • Higher-priority source becomes "primary" record
  • Never auto-delete: flag duplicates, let users resolve
  • Keep the richer record: when priorities equal, prefer source with more populated fields

Unit normalization at ingest

  • All distances → meters, durations → seconds, calories → kcal, speed → m/s, coordinates → decimal degrees (SYNTHESIS §9)
  • Provider-specific conversions: Whoop kJ → kcal, Fitbit ms → seconds, etc.

Depends on

  • #31 Implement SYNTHESIS Schema

Reference

See docs/api-research/SYNTHESIS.md §9 (Unit Conventions), §11 (Deduplication & Conflict Resolution).

Status
Done
Priority
Top
Platform
API
Date
1 month ago
Workout Syncing Infrastructure - Roadmap - Trainstack