We're building two apps that rely almost exclusively on HealthKit, so we run a high volume of queries against a single shared HKHealthStore — mostly HKSampleQuery, plus HKStatisticsQuery and HKQuantitySeriesSampleQuery where needed. We also use HKObserverQuery for background processing and widget updates. The data is sleep, body metrics, and workouts.
As our feature set grew, so did data-loading time, to the point of being a noticeable annoyance for users. To speed things up we moved from serial to concurrent queries.
Mechanism: we issue the batch via a ThrowingTaskGroup — each child task calls execute() and awaits the completion handler through a continuation — with up to ~30 queries in flight concurrently against the one shared store.
Symptom: The app doesn't freeze and the queries start fine, but their results sometimes take 30s+ to come back. Most of the times the same data fetch takes only a couple of seconds. There's no clear pattern except that it happens far more often on foregrounding.
Environment: Devices we use for testing are iPhone 17 Pro and iPhone 15 pro both running iOS 26.5. Since the symptoms are hard to catch we're using text file logging to time the data layer responses.
We're considering bounding concurrency to a small N via a capped task group, or reverting to serial — but both feel like either a regression or added complexity we can't justify without understanding the real cause.
Questions:
- When we start ~30 queries at once against a single HKHealthStore, does HealthKit actually run them in parallel, or do they get handled one-at-a-time (or rate-limited) behind the scenes?
- Is there a sensible upper limit on how many queries we should run at once? Should we cap it to a small number, or does that not help because the system serializes them anyway? (Also: is sharing one HKHealthStore across the app the right approach?)
- Why would this happen mainly when the app comes to the foreground? A few possibilities we'd like confirmed or ruled out: the device hasn't been unlocked yet so health data isn't available, the connection to the HealthKit service is being re-established after backgrounding, general contention, or our background HKObserverQuery work blocking the foreground queries.
- Can HKObserverQuery background work get in the way of foreground queries? If so, is there a recommended way to pause or coordinate it when the app becomes active?
Thank you