iOS background execution is opportunistic. The system decides when work runs and how long it receives. A reliable design treats background delivery as acceleration, not the only path to correctness.
Observer queries can notify the app that HealthKit changed. The handler should start bounded incremental work and call completion promptly. Long historical work belongs in resumable windows.
Background tasks can schedule refresh, but they may be delayed or skipped. Every foreground launch should check durable sync state and catch up from the last committed anchor or cursor.
Keep stages independent:
HealthKit changes → local normalized store → remote upload → derived refresh
Failure in remote upload should not force another expensive HealthKit read. Local persistence provides the handoff.
Protect concurrent triggers with one coordinator so foreground refresh, observer delivery, and scheduled work do not race. Coalescing is usually better than starting three syncs.
Use expiration handlers to cancel work and persist safe progress. Never mark a stage complete before its durable result exists.
Measure last successful local import and remote upload separately. “Background sync ran” is less useful than knowing which stage is stale.
The operating system offers opportunities, not schedules. Idempotency and foreground recovery provide the guarantee users experience.