Your Normal Isn't the Population Average
The population average is an average computed without you in it. A personal baseline is a ruler written by your own recent weeks — blunt at first, sharper the longer you use it.
Two people, one number
Two people, one of them usually reads a lot higher, the other a lot lower. One afternoon, both land on exactly the same number.
A population ruler says the second is fine and the first is in trouble. What actually happened that day: the first dropped a long way, the second rose a long way.
When we have no baseline of your own yet, that population ruler is exactly what we fall back on — a center and a width taken from a crowd of strangers. It is a stopgap for the first few days, not what we believe is right. The longer you use it, the clearer its flaw: it measures the distance between you and people you have never met.
People differ from each other more than you differ from yourself
HRV depends on age, sex, resting heart rate, medication, training load and autonomic tone. Across people it can differ several-fold; within one person, day to day, it moves inside a narrow band.
So a population ruler fails in both directions. For someone with a high baseline, the low end of his own normal gets flagged as poor. For someone with a low baseline, his genuinely bad day still sits inside the crowd's normal range, and the ruler stays silent.
There is a quieter problem too: it rewards people who were born with high HRV. Same lifestyle, different starting point, different score. What we want to measure is not where you stand among strangers — it's how far you have moved away from yourself.
How the ruler is built
Make the samples equal first. Some days Apple Watch writes many HRV samples, some days few. Feed them straight into the statistics and the dense hours get more weight — the baseline would move because of sampling rate, not because of your body. So before anything else, HRV samples are grouped into fixed-length time buckets and each bucket keeps only its median. Charts, detail views and live scoring still use the raw samples. Only the ruler uses buckets.
Then pick the window. Up to about a month. If the recent stretch holds enough HRV buckets, enough resting heart rate samples and enough calendar days, we use the full window; otherwise we use whatever real span exists. Why not a shorter window — one bad night is enough to drag the whole thing. Why not a longer one — seasons, training blocks and schedule shifts leak in.
Center on the median. Values outside a plausible band are dropped first, then, when there are enough samples, a small slice is trimmed off both ends, and then we take the median. A stray reading from a loose strap should not lift your center for a week.
Pin the center to this hour. HRV follows a daily rhythm — for most people highest during sleep, lowest in the afternoon, though the shape is individual. A single static center isn't enough. We compute factors from the medians of a few coarse segments over the recent stretch: a segment needs enough samples, and enough segments have to count as reliable. Missing segments are filled by circular interpolation, the factors expand to every hour, one light smoothing pass, then a clamp to a plausible range. The dynamic center at any moment = daily center x that hour's factor.
Why a few coarse segments instead of hourly buckets: watch HRV is sparse and uneven. Most hours hold only one or two samples, so an hourly median mostly draws a curve out of noise. Coarse segments plus interpolation and smoothing land closer to the real rhythm than fine but empty buckets.
The range is not a standard deviation. This is the important step. HRV moves multiplicatively: dropping by the same proportion from a high level and from a low level is the same event, yet one is several times larger in absolute terms. So for every sample we compute its log residual against the dynamic center at that moment.
On a log scale, people with very different baselines line up on the same chart, and transforming back keeps the range positive. Then we take three quantiles of those residuals — one on the lower side, one on the upper side, and one further out:
lower edge of normal = center x exp(quantile on the lower side)
entry to energized = center x exp(quantile on the upper side)
entry to poor = center x exp(the outer quantile)
Choosing this set rather than the usual quartiles is deliberate: normal covers the middle stretch of your own variation and is shifted upward. A low reading gets noticed earlier, while energized requires roughly your own best stretch. A health product shouldn't hand out praise to stay visible.
Three guards on top of that:
Half-widths keep a floor. Very stable users produce razor-thin quantiles, and single-sample noise would flip their state all day.
The upper half-width may not exceed a fixed multiple of the lower one. Otherwise the long right tail of HRV keeps pushing the top of "normal" upward until almost nothing counts as high.
The poor entry is pushed further out: it takes the more distant of the quantile and "center minus several effective lower half-widths". Same reason: keep that line out of the noise.
The residual model has its own entry bar: enough normalized samples, enough calendar days, enough reliable segments. Below that we fall back entirely to robust half-widths — the median absolute deviation versus the interquartile spread, whichever is steadier, with a cap on top. Which means the range you see comes either from your own quantile distribution or from a blunt but stable ruler — never from a quantile scraped together out of too little data.
Bands are measured in half-widths, not sigmas. Scoring asks how many half-widths the value sits from the center (lower half-width below center, upper above), not how many sigmas. That way every band means the same thing for everyone: within one half-width is normal, past that on the low side is energized, further out is strained, and past the poor entry is the last band. What differs between people is how wide a half-width is, not what counts as normal.
Two more rails. Heart rate is a secondary term that only gains weight as HRV moves away from center — the further out, the more weight — and it is scored against your own resting heart rate. The other rail is an absolute floor for critically low HRV, and it ignores your personal baseline entirely. Physiologically low is low; it doesn't need to be excused by being normal for you.
When there isn't enough data yet
For the first few days, the personalized score is blended with the population fallback linearly by day count, and the baseline is marked as cold start: it informs, but it doesn't carry band boundaries. Then comes a learning stretch. After enough days, with a residual model that passes quality checks, it's mature.
Reliability is a separate bar: the less data you have, the more it demands. It decides whether a baseline is allowed to participate in scoring at all; maturity decides its priority in selection and how confident the UI should sound.
And when we evaluate any given day, we only use baselines strictly older than that day. A baseline computed today doesn't get to judge today — otherwise, as HealthKit syncs samples in one at a time, today's verdict would flip back and forth.
Baselines drift too, so we keep a second anchor
A rolling window has a side effect: if someone stays at a low HRV for months, that low level slowly becomes "their normal", and the long-term change disappears.
So we keep the stored baseline snapshots from the recent stretch and pair each current snapshot with one from about a month earlier. Only with enough pairs, and most of them agreeing in direction, do we output sustained low or sustained high. Users see three states: a bit better than last month, a bit worse, or about the same. Not enough pairs and the line stays empty — we don't write "unknown" as "unchanged".
There is also a slow anchor that moves toward the fast baseline by a small step per day, with an even smaller step while drift is sustained. It only ever nudges the score upward, and only slightly, and it never rewrites history. The asymmetry is intentional: a long stretch of low readings deserves to be taken more seriously. A long stretch of high ones doesn't need a reward.
What we haven't solved
Sampling density is isolated on the baseline side by bucketing, but daily summaries still weight every stress point equally, so on high-frequency devices daytime carries more weight than it should. That bias is known and queued for time-bucket averaging; it wasn't changed this round.
Confounders aren't finished either. Caffeine, alcohol, jet lag, menstrual cycle and illness all move HRV. We handle exercise and a short list of the biggest sources explicitly, and that's it.
One more thing, stated plainly: a baseline is not a diagnosis. It's a relative ruler describing your relationship with yourself. It makes no medical claim.
To close with one line — the population average is an average computed without you in it. A personal baseline is a ruler written by your own recent weeks. It starts blunt and only sharpens with use, and there is no way to speed that up.
Keep reading
Try these ideas in Stress HRV
Download on the App StoreThese notes share product thinking for personal wellness. They are not medical advice.