Confounding by Indication and Channeling Bias
The dominant structural confounding in pharmacoepidemiology: the medical indication for a drug — and especially its severity — simultaneously determines who receives treatment and independently elevates (or lowers) the outcome risk, so that crude observational associations between drug use and outcomes reflect the underlying disease rather than any true causal drug effect; channeling is the specific variant in which newer drugs are preferentially prescribed to patients who are sicker, have failed prior therapy, or carry more comorbidity.
On this page
Confounding by indication happens when the very reason a doctor prescribes a drug — for example, treating severe diabetes — also makes the patient more likely to have bad outcomes, so a naive comparison makes the drug look harmful even if it has no true effect.
Channeling is a related pattern where newer drugs get prescribed mainly to the sickest patients or those who failed older drugs, so studies comparing the new drug to the old one find worse outcomes in the new-drug group — not because the drug is worse, but because the patients were already sicker before they started it.
In insurance claims data this bias is especially hard to fix because severity is only partly coded: the database knows a patient has diabetes, but not how severe or well-controlled it is. The most reliable design fix is to compare two drugs prescribed for the same condition, so that the indication and its severity are shared across both groups and cancel out.
Core definition and the backdoor path
Confounding by indication (CBI) is the systematic error that arises when the clinical reason a drug is prescribed — the indication — is itself a determinant of the outcome under study. In a directed acyclic graph, the indication and its severity open a backdoor path: Indication → Treatment and Indication → Outcome. Because healthcare database studies cannot randomize patients to treatment, patients who receive a given drug will always differ systematically from those who do not, in exactly the ways prescribers consider clinically relevant.
This is not a data-quality flaw that more careful collection can eliminate — it is a structural consequence of how medical prescribing works.
The aggravating feature in claims and EHR data is that severity within a diagnosis is substantially unmeasured. An ICD code for "type 2 diabetes" is recorded for a patient whose HbA1c is 6.5% on diet alone and for a patient with HbA1c of 11%, recurrent hospitalizations, and emerging neuropathy. The prescriber knows the difference; the claims database records neither. The same binary code masks a severity gradient that drives both treatment escalation and outcome risk.
CBI is therefore the strongest and most difficult-to-fix confounding source in pharmacoepidemiology, because the most important part of the confounder — the part that drives the prescribing decision — is the part the database cannot see.
Channeling: the original Petri and Urquhart framing
Channeling is a specific, common manifestation of CBI in which a new drug is systematically prescribed to a different — and typically sicker — patient population than an established comparator. Petri and Urquhart (1991) coined the term to describe how initial prescribers of a new agent tend to be specialists who see the most severely ill, treatment-refractory patients: exactly the patients who would be expected to have worse outcomes regardless of the new drug's true efficacy or safety.
The COX-2 selective inhibitor era (celecoxib, rofecoxib, 1999–2004) is the canonical case study. COX-2 inhibitors were approved and marketed as safer alternatives to traditional NSAIDs for patients at elevated gastrointestinal risk — patients with prior GI bleeding, peptic ulcer history, or concurrent anticoagulant use. Observational studies in the early post-market period found higher cardiovascular event rates in COX-2 users than in NSAID users, partly because the channeled patient population — older, more comorbid, more cardiovascularly vulnerable — was already at higher baseline cardiovascular risk.
Disentangling the true pharmacological cardiovascular signal from the channeling signal required careful active-comparator designs and restriction analyses; both effects were real, but their relative magnitudes could not be estimated reliably without controlling the channeling.
Confounding by contraindication and the reverse direction
CBI operates in both directions. When an indication increases both treatment probability and outcome risk, treated patients appear sicker in the crude analysis (the drug appears harmful or less effective than it truly is). When a contraindication — a condition that makes the drug dangerous — drives withholding of treatment, the untreated patients carry the higher risk: anticoagulants are withheld from patients with high bleeding risk; ACE inhibitors are avoided in bilateral renal artery stenosis; beta-blockers were historically avoided in asthma.
In these settings the treated patients are the healthier ones, and the crude association flatters the drug — the mirror image of the channeling pattern. Both directions of CBI are operationally invisible in claims unless the contraindication is fully and consistently coded.
Direction-of-bias reasoning
The direction of crude confounding depends on whether the indication/contraindication is a risk factor or protective factor for the outcome. If the indication increases outcome risk (severe heart failure → digoxin → higher baseline mortality), treated patients have higher baseline risk and the crude drug-outcome association is confounded upward — the drug appears more harmful or less beneficial than it truly is. If the contraindication increases outcome risk and those patients are left untreated, the crude association is confounded downward — the drug appears more protective than it truly is.
Conducting this direction-of-bias reasoning before analysis is essential for interpreting whether residual confounding would inflate or deflate the effect estimate, and whether it favors or disfavors the study drug — a critical input to sensitivity analysis and regulatory communication.
Why standard covariate adjustment fails: residual severity
Including diagnosis codes, comorbidity indices (Charlson, Elixhauser), and propensity scores in the outcome model attenuates CBI but rarely eliminates it. The fundamental problem is that the severity signals driving prescribing decisions — HbA1c trajectory, spirometry values, frailty score, symptom burden, the clinician's gestalt — are not recorded in claims. Even high-dimensional propensity scores (hdPS), which empirically screen hundreds of claims codes for proxy confounders, can recover indirect severity signals (hospitalizations, emergency encounters, specialist contacts, polypharmacy) but cannot reconstruct continuous physiological measurements the prescriber used.
Residual confounding by unmeasured severity therefore persists in essentially every pharmacoepidemiological cohort study, and its direction is predictable from the indication structure. The claims-based frailty index (CFBI) partially rescues this for elderly populations by aggregating frailty-adjacent codes into a validated composite, but it remains a proxy for the underlying physiological state, not a direct measure of it.
Design fixes, ranked by effectiveness
The only complete fix is randomization. Among observational designs, the hierarchy is: (1) Active-comparator, new-user (ACNU) design: by restricting to initiators of two drugs used for the same indication, the indication itself cancels across arms. Both groups had the indication; the severity confounding that remains is the within-indication severity differential between prescribers' choices, which is typically far smaller than the cross-indication gap. (2) Restriction to a single indication with a narrow severity band reduces the gradient but depends on having severity explicitly coded or measurable.
(3) Self-controlled designs (SCCS, case-crossover): the patient acts as their own control across time periods so stable confounders including the indication and baseline severity cancel. Appropriate for acute, transient exposures; cannot handle time-varying confounders including disease progression. (4) Instrumental variable / regression discontinuity: when a valid instrument exists (physician prescribing preference, formulary threshold, geographic variation), IV methods achieve causal identification even with unmeasured severity, at the cost of estimating only a local average treatment effect and requiring strong, verifiable IV assumptions.
(5) Negative controls and E-value: after the primary analysis, negative-control outcomes or exposures that share the indication-confounding structure without a causal path to the outcome measure the residual bias; the E-value quantifies the minimum unmeasured confounding strength needed to explain away the observed association.
Pros, cons, and trade-offs
Confounding by indication is not a design choice — it is a structural feature of non-randomized prescribing. The trade-offs are among strategies for controlling it:
- Active-comparator new-user design: the most powerful single structural fix. CBI cancels by symmetry when both arms share the indication. Pros: eliminates indication-level confounding with no modeling assumptions; also removes healthy-user bias and prevalent-user bias simultaneously. Cons: answers a comparative (drug A vs drug B) question, not an absolute (drug vs no drug) question; requires a clinically interchangeable comparator; residual within-indication channeling may persist if prescribers differentially select one drug for the sicker within-indication patients.
- Propensity score adjustment (partial fix): addresses measured severity proxies and produces an auditable balance diagnostic. Pros: flexible, standard, transparent. Cons: cannot control unmeasured severity; a balanced PS on measured variables does not imply balance on unmeasured severity gradients, and the appearance of balance can give false confidence.
- Restriction and eligibility narrowing: tightening the cohort to a homogeneous severity stratum reduces the confounding gradient. Pros: conceptually simple. Cons: reduces generalizability; hard to implement in claims without direct severity measurement.
- Instrumental variable / RDD: can achieve causal identification with unmeasured confounding. Pros: removes both measured and unmeasured CBI when the instrument is valid. Cons: valid instruments are rare; identifies LATE, not ATE; requires expert validation of exclusion restriction.
When NOT to use
(meaning: when CBI-specific adjustments are unnecessary or counterproductive)
- When the design already eliminates it structurally: a self-controlled analysis comparing on-treatment to off-treatment windows within the same patient eliminates stable confounders including the indication. Additional CBI adjustment on top of this may introduce collider bias if time-varying severity is also a mediator.
- When the cohort is tightly restricted to a single, narrow indication stratum with documented within-stratum severity balance: the indication-level confounding is largely eliminated and residual channeling within the stratum is the remaining concern.
- Do not adjust for post-baseline severity markers: conditioning on outcomes of disease severity measured after treatment initiation (HbA1c at month 6, post-index symptom score) blocks the causal path and induces collider bias. CBI adjustment must use pre-treatment severity proxies only, measured in the baseline window.
- Do not interpret a balanced propensity score as eliminating CBI: balance on measured confounders does not rule out residual CBI from unmeasured severity. Always supplement with direction-of-bias reasoning, a negative control, and an E-value in any non-randomized study.
Interpreting the output
In the worked example: 1000 severe patients (60% treated, risk = 0.30) and 1000 mild patients (20% treated, risk = 0.10). The drug has no true causal effect (RR = 1.00 within each stratum). The stratum-adjusted RRs are both 1.00. The crude pooled analysis yields treated risk = 200 / 800 = 0.25 and crude RR = 1200 / 800 = 1.50.
(1) Formal interpretation. The crude RR of 1.50 is a confounded estimate. The Mantel-Haenszel stratum-adjusted RR equals 1.00, confirming that the drug has no causal effect within either severity stratum. The 1.50 arises entirely because severe patients — who have both a higher treatment probability (60%) and a higher outcome risk (30%) — are overrepresented among the treated in the pooled analysis. The severity stratum is an unmeasured confounder: if it were perfectly controlled, the association would vanish.
The direction of confounding is positive (crude RR > true RR), consistent with the indication pattern in which sicker patients are more likely to receive treatment and face higher baseline risk. This is the mathematical signature of confounding by indication in a 2-stratum model.
(2) Practical interpretation. A study that does not adequately control for severity will report that the drug increases risk by 50% — potentially triggering regulatory action or prescriber hesitation — when the drug has no true effect. The scale of bias (1.50 vs 1.00) is proportional to the severity gradient in both treatment probability (60% vs 20%) and outcome risk (30% vs 10%). In real pharmacoepidemiological data, these gradients are typically larger and partly unmeasured, so residual confounding after standard covariate adjustment can be substantial and in a predictable direction.
The design remedy — an active-comparator design restricting to the same indication — removes this bias structurally rather than requiring it to be modeled away from partially observed data.
Decision diagram
flowchart LR SEV["Indication severity\n(e.g., HbA1c trajectory,\nfrailty, prior failure)\n— largely unmeasured\nin claims"] TX["Drug treatment\n(new or study drug)"] OUT["Outcome\n(adverse event, hospitalization,\nmortality)"] MED["Prescriber decision\n(indication + severity)"] SEV -->|drives prescribing| MED MED -->|channel to new/study drug| TX SEV -->|direct biological risk| OUT TX -->|true causal effect\n(may be null)| OUT style SEV fill:#ffcccc,stroke:#cc0000 style MED fill:#fff3cc,stroke:#ccaa00
flowchart TD Q["Is there a clinically\ninterchangeable active\ncomparator for the\nsame indication?"] Q -->|"Yes"| ACNU["Active-comparator new-user design\nIndication cancels across arms\nCBI removed structurally"] Q -->|"No"| NONUSER["Non-user comparison\nCBI likely — document it"] NONUSER --> DIR["Direction-of-bias reasoning:\nDoes indication increase or\ndecrease outcome risk?"] DIR --> PS["Propensity score on all available\nseverity proxies (Charlson,\nhospitalizations, frailty index,\nprior-line-of-therapy)"] PS --> NC["Negative-control outcome:\ndoes the 'drug effect' persist\nfor an outcome it cannot cause?"] NC -->|"Yes — residual bias"| EVAL["Report E-value; calibrate;\ndo not interpret causally"] NC -->|"No — bias plausibly controlled"| EST["Report estimate with E-value\nand direction-of-bias caveat"] ACNU --> WITHIN["Within-design channeling check:\nare severity proxies balanced\nbetween arms?"] WITHIN -->|"Imbalanced"| PSACNU["PS or restriction within the\nACNU cohort; report residual E-value"] WITHIN -->|"Balanced"| ESTACNU["Report comparative estimate\nwith E-value sensitivity"]
Worked example
Scenario
A claims-based cohort study asks whether a new oral anti-inflammatory drug increases the risk of a serious adverse event over one year. The database holds 2 000 patients: 1 000 with severe disease and 1 000 with mild disease. Physicians prescribe the new drug to 60% of severe patients (who are at highest need) but to only 20% of mild patients. The true pharmacological effect of the drug is null — within each severity stratum the drug neither increases nor decreases the adverse-event risk (stratum-specific RR = 1.00). The analyst first ignores severity and computes a crude RR, then stratifies by severity to recover the true RR.
Dataset
Four cells of a 2x2-by-stratum table: two severity strata (severe/mild), each split into treated vs untreated. Events and risks are exact by construction (no true drug effect).
| stratum | treatment_status | patients | events | risk |
|---|---|---|---|---|
| severe | treated | 600 | 180 | 0.3 |
| severe | untreated | 400 | 120 | 0.3 |
| mild | treated | 200 | 20 | 0.1 |
| mild | untreated | 800 | 80 | 0.1 |
Steps
Result
Within-stratum results: RR_severe = 0.30 / 0.30 = 1.00; RR_mild = 0.10 / 0.10 = 1.00. Both stratum-specific RRs are null — no true drug effect in either severity group. Crude pooled result: treated risk = 200 / 800 = 0.25; crude RR = 1200 / 800 = 1.50. The crude RR of 1.50 is entirely spurious confounding by indication. Stratifying by severity (or using an active-comparator design where the indication cancels) restores the true RR = 1.00.
Trade-offs
Runnable example
Simulate a confounding-by-indication dataset replicating the worked-example structure (1 000 severe + 1 000 mild patients; treatment probability 60% / 20%; outcome risk 0.30 / 0.10; true drug RR = 1.00 in both strata).
import math
import random
random.seed(42)
# ── Simulation parameters matching the worked example ──────────────────────────────
# True drug effect: RR = 1.00 in both strata (no causal effect)
strata = [
{"stratum": "severe", "n": 1000, "p_treat": 0.60, "base_risk": 0.30},
{"stratum": "mild", "n": 1000, "p_treat": 0.20, "base_risk": 0.10},
]
# Use exact counts from worked example rather than random draws for reproducibility.
# severe: 600 treated (180 events), 400 untreated (120 events)
# mild: 200 treated ( 20 events), 800 untreated ( 80 events)
cells = [
{"stratum": "severe", "treated": 1, "patients": 600, "events": 180},
{"stratum": "severe", "treated": 0, "patients": 400, "events": 120},
{"stratum": "mild", "treated": 1, "patients": 200, "events": 20},
{"stratum": "mild", "treated": 0, "patients": 800, "events": 80},
]
# ── Stratum-specific RRs (should both equal 1.00) ──────────────────────────────────
print("=== Stratum-specific RRs ===")
for stratum_name in ("severe", "mild"):
c = {c["treated"]: c for c in cells if c["stratum"] == stratum_name}
r_treat = c[1]["events"] / c[1]["patients"]
r_untr = c[0]["events"] / c[0]["patients"]
rr = r_treat / r_untr
print(f" {stratum_name}: treated risk = {r_treat:.4f}, "
f"untreated risk = {r_untr:.4f}, RR = {rr:.4f}")
# ── Crude (pooled, ignoring stratum) RR ───────────────────────────────────────────
tot_treat_events = sum(c["events"] for c in cells if c["treated"] == 1)
tot_treat_n = sum(c["patients"] for c in cells if c["treated"] == 1)
tot_untr_events = sum(c["events"] for c in cells if c["treated"] == 0)
tot_untr_n = sum(c["patients"] for c in cells if c["treated"] == 0)
crude_r_treat = tot_treat_events / tot_treat_n # = 200/800 = 0.25
crude_r_untr = tot_untr_events / tot_untr_n # = 200/1200 ≈ 0.167
crude_rr = crude_r_treat / crude_r_untr # = 1.50
print("\n=== Crude (pooled) RR ===")
print(f" Treated: {tot_treat_events}/{tot_treat_n} = {crude_r_treat:.4f}")
print(f" Untreated: {tot_untr_events}/{tot_untr_n} = {crude_r_untr:.6f}")
print(f" Crude RR = {crude_rr:.4f} (expected: 1.50 — entirely from CBI)")
# ── Mantel-Haenszel RR (stratum-adjusted) ─────────────────────────────────────────
# MH numerator term per stratum: (events_treat * n_untr) / total_in_stratum
# MH denominator term: (events_untr * n_treat) / total_in_stratum
mh_num = 0.0
mh_den = 0.0
for stratum_name in ("severe", "mild"):
c = {c["treated"]: c for c in cells if c["stratum"] == stratum_name}
n_total = c[1]["patients"] + c[0]["patients"]
mh_num += (c[1]["events"] * c[0]["patients"]) / n_total
mh_den += (c[0]["events"] * c[1]["patients"]) / n_total
mh_rr = mh_num / mh_den
print("\n=== Mantel-Haenszel Adjusted RR ===")
print(f" MH numerator = {mh_num:.4f}")
print(f" MH denominator = {mh_den:.4f}")
print(f" MH RR = {mh_rr:.4f} (expected: 1.00 — true null effect)")
print()
print(f"Conclusion: Crude RR = {crude_rr:.2f} vs MH-adjusted RR = {mh_rr:.2f}.")
print("The entire excess (1.50 vs 1.00) is confounding by indication.")
print("Design fix: active-comparator new-user design restricts to the same indication,")
print("making severity balance within-stratum rather than requiring stratification.")Replicate the worked-example arithmetic in R and compute the Mantel-Haenszel stratified RR using a 2x2 array (epiR::epi.2by2 or manual computation). Demonstrates the crude vs adjusted discrepancy and how the E-value bounds the unmeasured-severity confounder needed to explain the crude RR of 1.50.
# ── Exact cell counts from the worked example ──────────────────────────────────────
# Rows: treated (1), untreated (0); Columns: event (1), no event (0)
severe_2x2 <- matrix(
c(180, 420, # treated: 180 events, 420 no-events
120, 280), # untreated: 120 events, 280 no-events
nrow = 2, byrow = TRUE,
dimnames = list(treat = c("treated","untreated"), event = c("yes","no"))
)
mild_2x2 <- matrix(
c( 20, 180, # treated: 20 events, 180 no-events
80, 720), # untreated: 80 events, 720 no-events
nrow = 2, byrow = TRUE,
dimnames = list(treat = c("treated","untreated"), event = c("yes","no"))
)
rr_stratum <- function(m) {
r_treat <- m["treated", "yes"] / sum(m["treated", ])
r_untr <- m["untreated", "yes"] / sum(m["untreated", ])
list(r_treat = r_treat, r_untr = r_untr, rr = r_treat / r_untr)
}
cat("=== Stratum-specific RRs ===\n")
sev <- rr_stratum(severe_2x2)
mld <- rr_stratum(mild_2x2)
cat(sprintf(" Severe: treated risk = %.4f, untreated = %.4f, RR = %.4f\n",
sev$r_treat, sev$r_untr, sev$rr))
cat(sprintf(" Mild: treated risk = %.4f, untreated = %.4f, RR = %.4f\n",
mld$r_treat, mld$r_untr, mld$rr))
# ── Crude (pooled) RR ──────────────────────────────────────────────────────────────
pooled <- severe_2x2 + mild_2x2
crude <- rr_stratum(pooled)
cat(sprintf("\n=== Crude RR ===\n Treated risk = %.4f, Untreated = %.6f, Crude RR = %.4f\n",
crude$r_treat, crude$r_untr, crude$rr))
# ── Manual Mantel-Haenszel RR ─────────────────────────────────────────────────────
mh_term <- function(m) {
N <- sum(m)
list(num = m["treated","yes"] * sum(m["untreated",]) / N,
den = m["untreated","yes"] * sum(m["treated",]) / N)
}
ts <- mh_term(severe_2x2)
tm <- mh_term(mild_2x2)
mh_rr <- (ts$num + tm$num) / (ts$den + tm$den)
cat(sprintf("\n=== Mantel-Haenszel Adjusted RR ===\n MH RR = %.4f (expected 1.00)\n", mh_rr))
# ── E-value for the crude RR of 1.50 ─────────────────────────────────────────────
# E-value formula (VanderWeele & Ding 2017): E = RR + sqrt(RR * (RR - 1))
rr_obs <- crude$rr
e_value <- rr_obs + sqrt(rr_obs * (rr_obs - 1))
cat(sprintf("\n=== E-value for crude RR = %.2f ===\n", rr_obs))
cat(sprintf(" E-value = %.4f + sqrt(%.4f * (%.4f - 1)) = %.4f\n",
rr_obs, rr_obs, rr_obs, e_value))
cat(" Interpretation: an unmeasured confounder would need to be associated\n")
cat(sprintf(" with both treatment and outcome by a factor of >=%.2f to explain\n", e_value))
cat(" the crude RR of 1.50. Severity in claims (partially unmeasured) could\n")
cat(" plausibly reach this threshold, supporting the CBI diagnosis.\n")
# ── Conclusion ────────────────────────────────────────────────────────────────────
cat(sprintf("\nCrude RR = %.2f vs MH-adjusted RR = %.2f.\n", crude$rr, mh_rr))
cat("The entire excess is confounding by indication — eliminated by stratification.\n")
cat("Design fix: active-comparator new-user design shares the indication across arms.\n")Citations
- [1]Petri H, Urquhart J. Channeling bias in the interpretation of drug effects. Statistics in Medicine. 1991;10(4):577-581.
- [2]Brookhart MA, Stürmer T, Glynn RJ, Rassen J, Schneeweiss S. Confounding control in healthcare database research: challenges and potential approaches. Medical Care. 2010;48(6 Suppl):S114-120.
- [3]Kyriacou DN, Lewis RJ. Confounding by indication in clinical research. JAMA. 2016;316(17):1818-1819.