← Methods repository
concept

Healthy User Bias

A confounding bias in which initiators of (or adherers to) preventive or chronic therapy are systematically more health-seeking — better diet, exercise, screening, adherence, socioeconomic status, and access — than comparators, so their lower event rates are attributed to the drug rather than to the unmeasured behaviors that travel with treatment.

Bias_Controlbiashealthy-userhealthy-adhererpreventive-therapyconfoundingchannelingadherencenegative-control
Methods reference only. Use primary source citations and local policy before applying this in a study protocol, regulatory submission, payer dossier, or clinical decision.

In plain language

Healthy user bias happens when the people who start or keep taking a preventive medicine — statins, blood-pressure pills, vaccines — are already healthier in ways a dataset can never fully see: they exercise, eat better, go to the doctor regularly, and follow through on every health recommendation, not just the drug. Because those hidden advantages lower their risk of bad outcomes, a study comparing them to non-users or non-adherent patients will make the drug look more protective than it really is. The single clearest proof is that statin adherents also have fewer car accidents — a result no pill can explain, so the advantage belongs to the person, not the medicine.

Healthy user bias

(and its sibling healthy adherer bias) is a specific form of confounding by unmeasured behavior that dominates observational studies of preventive and chronic therapies — statins, antihypertensives, vaccines, bisphosphonates, hormone therapy, antidiabetic drugs. People who initiate and persist with these therapies are not a random sample of the indicated population: they attend preventive visits, get screened, exercise, eat better, are wealthier and more educated, and adhere to everything (including placebo). Because almost none of those behaviors are recorded in claims, the treated arm carries a hidden health advantage that masquerades as drug efficacy. The canonical falsification is Dormuth's: statin adherers had markedly fewer motor-vehicle accidents and fewer unrelated illnesses than non-adherers — an effect no pharmacology can explain, so it must be the adherer, not the statin, who is healthy.

Core conceptual distinction

Healthy user bias is not a single bias but a family separable along two axes. (1) Healthy initiator vs healthy adherer: the first is selection into treatment (who starts), the second is selection among the treated (who keeps taking it) — adherers are even healthier than initiators, which is why per-protocol/as-treated analyses are more biased than intention-to-treat ones for preventive drugs. (2) Healthy user vs confounding by indication / channeling: confounding by indication makes the treated look sicker (they had the indication); healthy user bias makes them look healthier (they are health-seeking). The two can coexist and partially cancel, which is dangerous because a "balanced" Table 1 can hide both. Healthy user bias is also entangled with prevalent-user bias (prevalent users are survivors who tolerated and kept taking the drug — a depletion-of-susceptibles selection that is itself a healthy-survivor effect) and with immortal time bias (defining exposure by future adherence guarantees the exposed survive to accrue it). The estimand matters: the bias inflates the comparative hazard/odds/rate ratio toward apparent benefit, and is worst for absolute and cause-specific effects on outcomes plausibly tied to lifestyle (cardiovascular, all-cause mortality) and milder for biologically specific outcomes the behaviors cannot touch.

Pros, cons, and trade-offs

— Healthy user bias is a problem to control, so the trade-offs are among the mitigation strategies, each named against its alternatives: - Active-comparator new-user design vs new-user-vs-nonuser: the single most effective structural fix. Comparing two drugs for the same indication means both arms cleared the same health-seeking and access thresholds, so most healthy-user imbalance cancels. Cost: it answers a narrower head-to-head question and needs a clinically interchangeable comparator. Prefer it whenever such a comparator exists; a non-user comparator should be a last resort. - High-dimensional propensity score (hdPS) vs hand-picked covariates: proxy measurement is the only lever in claims, and hdPS empirically recovers proxies for health-seeking (screening codes, influenza vaccination, preventive visits) that analysts forget. Cost: it can select instruments or colliders and demands diagnostics. Prefer hdPS over a short investigator list in claims. - Negative-control outcomes / empirical calibration vs trusting a single point estimate: a falsification outcome the drug cannot affect (accidents, screening uptake) directly measures residual healthy-user bias. Cost: a valid negative control sharing the confounding structure is hard to find and the calibration shifts the CI. Always carry at least one. - E-value / quantitative bias analysis vs ignoring the residual: an E-value states how strong the unmeasured health-seeking confounder would have to be to explain the result. Cost: it is a what-if, not a correction. Prefer it as a mandatory reporting element, not a fix.

When to use

— i.e., when to actively design and analyze against healthy user bias: any study of a preventive or long-term chronic therapy where the comparison is exposed vs unexposed or adherent vs non-adherent; any adherence/persistence effectiveness analysis (PDC/MPR as exposure); any vaccine effectiveness study in non-randomized data; any study whose outcome (mortality, CV events, fractures, cancer) is plausibly affected by the same behaviors that drive treatment uptake. In these settings, default to an active-comparator new-user frame, rich proxy adjustment, and at least one negative-control outcome.

When NOT to use — and when it is actively misleading or dangerous

— "Use" here means worrying about / adjusting for healthy user bias; the danger is over- or under-correcting. - Do not condition on post-baseline "healthy" markers. Adjusting for follow-up adherence, on-treatment LDL, or post-index screening is a collider/mediator error that manufactures or amplifies bias. Healthy-user proxies must be measured strictly in the pre-index window. - Do not treat adherence as a clean exposure. Modeling PDC→outcome and "adjusting it away" cannot work: adherence is a marker of the unmeasured health-seeking, so the adherent–nonadherent contrast is biased by definition. The Dormuth accident result is the proof; an as-treated estimate here is actively misleading. - Do not assume an active comparator removes all of it. If one drug is the health-conscious patient's preference (e.g., a newer, marketed, "premium" agent), residual healthy-user channeling persists — diagnose with balance tables and a negative control before trusting the contrast. - It is overkill for a biologically specific acute outcome the behaviors cannot plausibly move (e.g., a within-class active-comparator study of an idiosyncratic drug reaction); forcing elaborate proxy adjustment there adds noise and collider risk without addressing a real bias.

Data-source operational depth

- Claims (FFS vs MA vs commercial): healthy-user proxies are utilization surrogates — counts of age/sex-appropriate screenings (mammography, colonoscopy/FOBT, PSA, bone-density DXA), influenza/pneumococcal vaccination, well/preventive visit E&M codes, distinct preventive drug classes — measured in a fixed pre-index lookback under continuous enrollment. Failure modes: Medicare Advantage person-time lacks fee-for-service claims, so a beneficiary can appear to have zero screenings simply because the encounter was capitated, not because they are not health-seeking — restrict to FFS Parts A/B/D or commercial medical+pharmacy, or the proxy is differential missingness. Influenza vaccines and screenings often migrate to pharmacies/retail clinics or are bundled, so NDC/CPT capture is incomplete and uneven by plan. In the elderly, the sickest patients drop out to hospice/nursing-facility benefits, inducing differential competing risks by exposure that mimic a healthy-user advantage. Immortal time sneaks in when adherence is the exposure or when index is set at diagnosis rather than first fill. - EHR: richer — structured vitals (BMI, blood-pressure control), labs (LDL, HbA1c, lipid panels), smoking status, and notes (exercise, diet via NLP) give objective health-seeking proxies claims cannot. But capture is visit-driven: a health-seeking patient generates more encounters, so "more data = healthier" is itself the confounder, and patients who leave the network are differentially and informatively lost. Residual confounding remains even with vitals. - Registry: strong on disease severity and adjudicated outcomes but typically blind to preventive utilization and lifestyle; link to claims for screening/vaccination history and to a death index so a healthy-survivor pattern is not an artifact of incomplete mortality capture. - Linked claims–EHR–vital records: the best substrate — EHR lifestyle proxies + claims completeness + reliable death — but the linkable subset is itself selected (often more health-engaged), and order/fill/service-date discrepancies must be reconciled before time zero.

Worked claims example (with falsification)

Question: does long-term bisphosphonate use reduce hip fracture in women ≥65 in a Medicare FFS + commercial database? A naive new-user-vs-nonuser cohort risks textbook healthy-user bias (bisphosphonate initiators get DXA scans, attend gynecology/primary care, and exercise). Build it defensibly: (1) require 365 days continuous FFS A/B/D (or commercial medical+pharmacy) enrollment before time zero so absence of prior fills and of screenings is observed, not MA-masked. (2) Time zero = first bisphosphonate `fill_date` (`days_supply` defines exposure episodes); washout = no bisphosphonate fill in the prior 365 days. (3) In the pre-index window only, construct a health-seeking index: count distinct preventive services — screening CPT/HCPCS (mammography 77067, FOBT/colonoscopy, bone-density DXA 77080), influenza vaccine (CPT 90686 / NDC), and well-visit/preventive E&M (99381–99397) — plus distinct preventive drug classes and number of outpatient visits. (4) Enter this index, comorbidity scores, and area-level deprivation (ZIP-linked ADI) into a high-dimensional propensity score; match 1:1 on the logit-PS (caliper 0.2 SD) and confirm standardized differences <0.1. (5) Falsify: run the identical pipeline on a negative-control outcome the drug cannot prevent — e.g., motor-vehicle or fall-unrelated accident hospitalizations, or screening uptake itself. If the "protective" hazard ratio persists for accidents, residual healthy-user bias remains and the fracture estimate is not trustworthy; calibrate the fracture estimate against the negative-control distribution and report an E-value for how strong an unmeasured health-seeking confounder would have to be to nullify it. First-event coding: take the first qualifying fracture in follow-up, applying an acute-event deduplication window so a transfer or readmission is not double-counted.

Interpreting the output

In the statin-adherence cohort (100 adherent, 100 non-adherent initiators), the study reports: hospitalization rate 12% (adherent) vs 22% (non-adherent), crude RD = −10 pp; accidental injury rate 4% vs 11%, crude RD = −7 pp; preventive visits mean 3.2 vs 1.1.

(1) Formal interpretation. The hospitalization RD of −10 pp conflates pharmacological benefit with the healthy-user bias. Adherent patients differ from non-adherent patients not only in statin exposure but in broader health behaviors — the 3.2 versus 1.1 preventive-visit contrast and the disparate accident rate provide the falsification signal. Accidental injury is a negative-control outcome: statins have no plausible causal mechanism for preventing accidents. The 7 pp accident-rate gap therefore represents the portion of the outcome differential attributable to confounding by health-seeking behavior, not to the drug. A confounder strong enough to produce a 7 pp gap in a negative-control outcome may explain a comparable portion of the 10 pp hospitalization estimate.

(2) Practical interpretation. A naive comparison of adherent versus non-adherent patients will systematically overestimate treatment benefit across most drug classes because adherence is a downstream marker of health engagement. The −10 pp hospitalization difference cannot be attributed to statins without accounting for the −7 pp accident difference that statins cannot explain. Negative-control outcomes and falsification tests are the principal tools for detecting and bounding this effect in routine RWE, and should be pre-specified rather than run post hoc when a healthy-user mechanism is plausible.

Worked example

Scenario

Imagine a claims database study asking whether patients who adhere to a cholesterol-lowering statin have fewer hospitalizations than those who do not. The analyst splits 200 statin initiators into two groups based on how consistently they refilled their prescription over one year: 100 who refilled regularly (adherent) and 100 who did not (non-adherent). To test whether any outcome difference is really caused by the drug, the analyst also looks at a placebo-marker: emergency department visits for accidental injury — something a statin cannot prevent.

Dataset

One-year follow-up outcomes for 100 adherent vs 100 non-adherent statin initiators (illustrative counts).

groupn_patientshospitalization_rateaccidental_injury_ratepreventive_visits_past_year
Adherent (high refill rate)10012%4%mean 3.2 visits
Non-adherent (low refill rate)10022%11%mean 1.1 visits

Steps

  • Hospitalizations differ: 12 events in the adherent group versus 22 in the non-adherent group — a 10-percentage-point gap that looks like a drug benefit.

  • But accidental injuries also differ: 4 events versus 11 — a 7-percentage-point gap the statin cannot explain, because a pill does not prevent car crashes.

  • The adherent group also averaged 3.2 preventive doctor visits in the prior year, versus only 1.1 for the non-adherent group — showing the adherent patients were already more health-engaged before any outcome difference could accumulate.

  • Because the same people who refilled their statin also exercised, attended more check-ups, and wore seatbelts, their lower hospitalization rate reflects those clustered healthy behaviors, not just the drug.

  • The accident-rate gap is the tell: it reveals that a hidden health advantage — not the statin — is the main reason the adherent group looks better across all outcomes.

Result

The adherent group had 10 fewer hospitalizations per 100 patients (12% vs 22%), but also 7 fewer accidental injuries per 100 patients (4% vs 11%) — an effect no cholesterol drug can produce. This spurious association shows healthy behaviors are clustering with adherence. The lesson: never trust an adherent-vs-non-adherent comparison as a measure of drug benefit; use an active comparator (another drug for the same condition) so both groups start from a comparable level of health-seeking.

Runnable example

python implementation

Build a pre-index health-seeking proxy index and a propensity-score-ready cohort from claims, then run a negative-control-outcome falsification. Required inputs (cleaned, de-duplicated): rx : person_id, fill_date (datetime), drug_class...

import pandas as pd
import numpy as np

LOOKBACK = 365  # pre-index window for health-seeking proxies and continuous-enrollment check

def health_seeking_cohort(index_df, med, enroll):
    """index_df: person_id, index_date (first study fill). Returns one row/person with proxies."""
    # Require continuous, FFS-observable enrollment across the whole lookback through index.
    e = enroll.merge(index_df[["person_id", "index_date"]], on="person_id")
    e["covers"] = ((e["enroll_start"] <= e["index_date"] - pd.Timedelta(days=LOOKBACK)) &
                   (e["enroll_end"]   >= e["index_date"]) & (~e["ma_only"]))
    eligible = e.loc[e["covers"], "person_id"].unique()
    cohort = index_df[index_df["person_id"].isin(eligible)].copy()

    # Pre-index claims window only: [index_date - LOOKBACK, index_date)
    m = med.merge(cohort[["person_id", "index_date"]], on="person_id")
    pre = m[(m["service_date"] >= m["index_date"] - pd.Timedelta(days=LOOKBACK)) &
            (m["service_date"] <  m["index_date"])]

    def _count(flag):
        c = (pre[pre["code_type"] == flag].groupby("person_id")["code"]
                .nunique().rename(f"n_{flag.lower()}"))
        return cohort["person_id"].map(c).fillna(0).astype(int)

    cohort["n_screen"]    = _count("SCREEN")    # distinct screening procedures (mammo, DXA, FOBT...)
    cohort["n_vaccine"]   = _count("VACCINE")   # influenza/pneumococcal
    cohort["n_wellvisit"] = _count("WELLVISIT") # preventive E&M 99381-99397
    # Composite health-seeking index = sum of distinct preventive touchpoints (a hdPS proxy).
    cohort["health_seeking_index"] = (cohort["n_screen"] + cohort["n_vaccine"] +
                                      cohort["n_wellvisit"])
    return cohort

def negative_control_rate(index_df, med, enroll, fu_days=365, control="ACCIDENT"):
    """First post-index negative-control event (drug cannot cause it) -> residual-bias check."""
    cohort = health_seeking_cohort(index_df, med, enroll)
    nc = med[med["code_type"] == control].merge(
        cohort[["person_id", "index_date"]], on="person_id")
    nc = nc[(nc["service_date"] > nc["index_date"]) &
            (nc["service_date"] <= nc["index_date"] + pd.Timedelta(days=fu_days))]
    first_event = nc.groupby("person_id")["service_date"].min()  # acute-event dedup: first only
    cohort["nc_event"] = cohort["person_id"].isin(first_event.index).astype(int)
    # If exposed (treated) initiators have FEWER accidents than comparators, healthy-user bias remains.
    return cohort
r implementation

Pre-index health-seeking proxy index and negative-control falsification with data.table. Inputs mirror the Python version: index_df : person_id, index_date (Date) # first qualifying study fill from the new-user design med : person_id, service_date (Date),...

library(data.table)
LOOKBACK <- 365L

health_seeking_cohort <- function(index_df, med, enroll) {
  setDT(index_df); setDT(med); setDT(enroll)

  # Continuous FFS-observable enrollment across the lookback through index (no MA-only spans).
  e <- merge(enroll, index_df[, .(person_id, index_date)], by = "person_id")
  ok <- e[enroll_start <= index_date - LOOKBACK &
          enroll_end   >= index_date & !ma_only, unique(person_id)]
  cohort <- index_df[person_id %chin% ok]

  # Pre-index claims only: [index_date - LOOKBACK, index_date)
  m <- merge(med, cohort[, .(person_id, index_date)], by = "person_id")
  pre <- m[service_date >= index_date - LOOKBACK & service_date < index_date]

  cnt <- function(flag) pre[code_type == flag,
                            .(n = uniqueN(code)), by = person_id]
  for (f in c("SCREEN", "VACCINE", "WELLVISIT")) {
    col <- paste0("n_", tolower(f))
    cohort[cnt(f), (col) := i.n, on = "person_id"]
    cohort[is.na(get(col)), (col) := 0L]
  }
  # Composite health-seeking index = distinct preventive touchpoints (a hdPS proxy).
  cohort[, health_seeking_index := n_screen + n_vaccine + n_wellvisit]
  cohort[]
}

negative_control_rate <- function(index_df, med, enroll, fu_days = 365L, control = "ACCIDENT") {
  cohort <- health_seeking_cohort(index_df, med, enroll)
  nc <- merge(med[code_type == control], cohort[, .(person_id, index_date)], by = "person_id")
  nc <- nc[service_date > index_date & service_date <= index_date + fu_days]
  first <- nc[, .(ev = min(service_date)), by = person_id]   # first event only (acute dedup)
  cohort[, nc_event := as.integer(person_id %chin% first$person_id)]
  cohort[]  # fewer accidents in the treated arm => residual healthy-user bias
}