Clarification on HealthKit Observer Delivery Frequency and BGTaskScheduler Behavior

Hi Team,

We are implementing HealthKit data sync using HKObserverQuery along with enableBackgroundDelivery and BGTaskScheduler for fallback processing.

However, we are observing inconsistent behavior and would like clarification on expected system behavior:

  1. For HKObserverQuery:
    • When using enableBackgroundDelivery with frequency .immediate, we sometimes receive updates promptly, but other times we do not receive any trigger at all.
    • Similarly, when using .hourly, our expectation was that updates would be delivered approximately once per hour, but in practice, triggers are delayed, batched, or skipped.
  2. For BGTaskScheduler:
    • We are scheduling BGAppRefreshTask with earliestBeginDate set (e.g., 1 hour), but tasks are sometimes delayed by several hours or not triggered predictably.
    • In some cases, tasks are not executed even after extended periods.

We would like to understand:

  • Are HKObserverQuery delivery frequencies (.immediate, .hourly, .daily) strictly best-effort hints rather than guaranteed intervals?
  • Under what conditions can observer updates be skipped or significantly delayed?
  • Is there any recommended approach to ensure more reliable periodic syncing of HealthKit data?
  • For BGTaskScheduler, what factors most strongly influence scheduling delays or missed executions?

Our goal is to design a reliable sync mechanism, but the lack of deterministic behavior is making it difficult to define expected system behavior.

Any clarification or recommended best practices would be greatly appreciated.

Thanks in advance!

How background tasks and HealthKit work on watchOS was somehow discussed here and here. You can check if they help.

iOS has a similar background execution time budget, but isn't as strict as watchOS. In a normal situation (meaning that your app has background execution time budget, the device's battery level is high, and no many apps are competing the background execution time), I'd expect that the system wakes your app and runs the updateHandler of your observer query (HKObserverQuery) whenever a process saves or deletes samples of the specified type.

The update frequency (HKUpdateFrequency) for sample types is another factor to consider. For example, stepCount samples have an hourly maximum frequency in iOS, and so the updateHandler will be triggered at most once per hour, even you use enableBackgroundDelivery + .immediate. This is documented in the Discussion section here.

Now to your questions:

Are HKObserverQuery delivery frequencies (.immediate, .hourly, .daily) strictly best-effort hints rather than guaranteed intervals? Under what conditions can observer updates be skipped or significantly delayed? Is there any recommended approach to ensure more reliable periodic syncing of HealthKit data?

No, the delivery frequency is not guaranteed. The system tries to honor the specified frequency, but may not achieve that due to the app's background execution time budget and other undocumented factors, and there is no API to change the behavior.

Having said that, if you see that the delivery frequency is not honored in a normal situation, please share the detailed steps you use to observe the behavior, and I'll be intersted in taking a closer look.

For BGTaskScheduler, what factors most strongly influence scheduling delays or missed executions?

I discussed BGTaskScheduler a bit in this post. The detailed mechanism the system uses to schedule background tasks is undocumented.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Clarification on HealthKit Observer Delivery Frequency and BGTaskScheduler Behavior
 
 
Q