My doctor sees me once a year. This sees every night.
3,778 sessions, 8,590 nights and 75 races since 2012 in one Postgres lake: a decade of falling resting heart rate, a dose-response curve, a winter tax, one honest null result, and a 353-week training streak.
My heart got seven beats slower while I got nine years older
Resting heart rate, yearly average across 3,345 nights: 54.6 → 46.7. Age says it should drift up. Training said otherwise.
Each point is a year's mean overnight resting HR. No app shows you this — Garmin keeps ~2 years, and your doctor gets one reading, in a chair, while you're stressed about being at the doctor.
Every weekly training hour buys resting heartbeats
Group 3,345 nights by how much I trained the seven days before: the curve is monotonic. Quiet weeks: 50.7 bpm. Twelve-plus-hour weeks: 46.7.
r = −0.25 across nine years. This chart needs the training log joined to the sleep log — Strava has one half, the sleep tracker has the other, neither has both. That join is the entire point of the lake.
December runs two beats higher than May
Same body, same training habits — a +2 bpm winter tax, every year, like clockwork.
Less daylight, more indoor sessions, holiday food, colder air. Any one year this would be noise. Averaged over nine winters it's a pattern — and a reason not to panic when a December reading looks "high."
More sleep does not raise my HRV
739 nights of overnight HRV against hours slept: r = 0.02. A flat line — and the error bars say it isn't hiding an effect.
Every wellness app implies more sleep → better recovery scores. For this body, duration doesn't move HRV at all — what moves it is training load and alcohol-free weeks. Generic advice is generic. A personal baseline is the only baseline that means anything.
Why this null is trustworthy: the spread between buckets is 2.1 ms (42.7 at five hours, 44.8 at ten) while the spread within a single bucket is about 5 ms. Every 95% confidence interval overlaps every other one. The four-hour point looks low-ish but carries n=25 and the widest scatter of the set (SD 10.1) — that's noise wearing a trend's clothes.
Publishing the null result on purpose. Data that only ever confirms is data you should distrust.
Where 3,600 hours went
Somewhere in there hides the number I'm proudest of: 353 consecutive weeks with at least one session. No blank week since November 2019 — through lockdowns, a newborn, a company exit.
Hover any year — hours deduped (watch+Edge twin recordings merged). You can read my life in it: the 2020 lockdown bike spike (167 h), the 2022 Ironman-scale year (371 h), the 2025 run pivot that ended in a sub-40 10K (120 h of running, 15 of cycling), and the 2026 triathlon rebuild.
75 start lines since 2012
Latest: two sprint triathlons, seven days apart, August 2026 — top 5% of the field at 45. The gap to the age-group podium closed from 4:34 (2023) to 71 seconds. Every start line, with its percentile, lives in the race ledger. The racing story itself → /race-engineering/
ALL 75 RACES, WITH PERCENTILESWhat I actually take, and when
MORNING · WITH BREAKFAST
- Creatine monohydrate3–4 g
- Vitamin D35,000 IU
- Omega-32 g
- Zinc bisglycinate25 mg
EVENING · BEFORE 22:00
- Magnesium glycinate300 mg
- Omega-32 g
- CoQ10, with dinner fat200 mg
Boring on purpose. Each item earned its slot from bloodwork or a measured need — vitamin D moved 35→53 ng/mL on this dose — and the stack is closed: nothing gets added without a marker that says so. Timing matters more than brands: magnesium at night, D and zinc with food, CoQ10 with the fattiest meal.