← Methods repository
concept

Treatment Failure and Non-Response in RWE

A pre-specified real-world endpoint or classification rule that identifies inadequate benefit after treatment initiation, combining disease-specific response evidence (labs, scores, imaging, PROs, clinician assessment) with treatment-pattern proxies such as escalation, switch, discontinuation, next line of therapy, rescue therapy, or recurrent acute care, while explicitly separating pharmacologic non-response from non-adherence, intolerance, access barriers, and informative intercurrent events.

Outcome_Measureoutcome_measuretreatment-failurenon-responseinadequate-responseloss-of-responsetreatment-escalationrescue-therapytreatment-patterns
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

Treatment failure or non-response means that a treatment did not produce enough benefit or did not remain acceptable in routine care. In real-world data, that can be measured directly when EHRs or registries contain labs, scores, imaging, or clinician-assessed response; in insurance claims it is usually inferred from what happens next, such as dose escalation, rescue therapy, switching, stopping, or moving to a new line of therapy. The honest label matters: a claims switch is a proxy for failure, not proof that the drug biologically failed.

Treatment failure / non-response

in RWE is not one universal code or one universal endpoint. It is a constructed clinical status: after a patient starts a therapy and has a pre-specified adequate-trial window, the study classifies the patient as having no response, partial/inadequate response, loss of response, or treatment failure using the best available real-world evidence. In an EHR or registry that may be a disease activity score, laboratory value, imaging interpretation, patient-reported outcome, or clinician note. In claims it is usually a proxy: dose escalation, add-on therapy, switch to a new class, advancement to the next line of therapy, discontinuation without a refill, procedure/rescue medication, or a failure-related hospitalization. The central RWE discipline is to state which construct is being measured. "No response to drug" is different from "treatment strategy failure," and both are different from "the patient stopped filling the drug."

Core conceptual distinction

Three layers must be kept separate and pre-specified. - Biologic or clinical response status. Did the disease improve enough by an anchored assessment time? Examples: tumor response category, HbA1c reduction, rheumatoid arthritis disease activity, asthma exacerbation control, remission score, pain/function improvement, or biomarker normalization. This is the closest real-world analogue of "response" but requires a measurement source and an assessment cadence. - Treatment-pattern failure proxy. Did the treating system behave as if the therapy was not adequate? Examples: dose escalation above a protocol threshold, add-on/augmentation after an adequate trial, switch to a different therapy, next line of therapy, rescue corticosteroids, treatment-related procedure, or discontinuation. This is scalable in claims but mixes inadequate efficacy with toxicity, patient preference, affordability, formulary changes, pregnancy planning, and access problems. - Estimand / intercurrent-event strategy. The same switch or rescue therapy can be the endpoint itself under a composite strategy ("switch/rescue = failure"), ignored under a treatment-policy strategy, censored under a while-on-treatment strategy, or modeled as a hypothetical strategy ("what if rescue had not occurred?"). ICH E9(R1) treats discontinuation, alternative treatment, rescue medication, and death as intercurrent events that affect the interpretation or existence of the measurement; RWE should do the same rather than letting the database default decide.

Outcome variants that should be named explicitly

- No response / primary non-response. No clinically meaningful improvement from baseline after an adequate exposure and assessment window. Operationally this usually requires baseline status, a response threshold, and a fixed landmark (for example, 12 or 24 weeks) or a first eligible post-index assessment. - Partial or inadequate response. Some improvement occurs but the patient remains above a disease-activity threshold or below a responder threshold. This is not a binary "failed" state unless the protocol defines the threshold and the handling of missing post-baseline measurements. - Loss of response / secondary failure. The patient first meets a response criterion, then later worsens beyond a pre-specified threshold, needs escalation, starts rescue therapy, or advances to a new line. This requires retaining both the initial response date and the later failure date. - Treatment escalation. Dose increase, interval shortening, therapeutic drug monitoring-triggered dose change, add-on/augmentation, procedure, rescue medication, or higher-intensity setting after a minimum adequate-trial window. Escalation is often the most clinically interpretable claims proxy for inadequate control, but it is still a proxy for a physician decision, not the disease state itself. - Switch, discontinuation, or next line of therapy. A switch or line advancement is strong evidence that the original regimen did not remain acceptable or effective, but reason is usually unobserved in claims. Discontinuation alone is the weakest failure proxy because it also captures intolerance, affordability, remission, patient preference, death, loss of insurance, and unobserved care. - Rescue therapy or acute-care failure. Oral steroids, rescue biologic, unscheduled procedure, ED visit, hospitalization, transfusion, dialysis start, or other urgent intervention can be folded into a failure composite when it is a clinically recognized consequence of uncontrolled disease. Each component needs its own outcome algorithm and de-duplication window.

Pros, cons, and trade-offs

- Clinical response endpoint vs claims treatment-pattern proxy. A clinical response endpoint is closer to the patient state and can distinguish no response from partial response and loss of response. Cost: EHR/registry measurement is missing, irregular, site-specific, and often visit-driven. A treatment-pattern proxy is scalable and complete in claims when medical + pharmacy benefits are observable, but it measures a care decision. Prefer clinical response when the data contain validated scores/labs/imaging at usable cadence; prefer a proxy only as a pragmatic endpoint or sensitivity analysis, with the proxy label preserved. - Composite treatment failure vs component-specific endpoints. A composite ("no response OR escalation OR switch OR rescue") raises event counts and matches real-world decision making, but a frequent low-specificity component can dominate the endpoint. Always store the triggering component and report the component breakdown. Prefer a composite for net clinical strategy failure; prefer components when the causal interpretation depends on efficacy rather than tolerability or access. - Failure including non-adherence vs pharmacologic failure among adherent users. A payer may want the net effect of initiating a strategy, where non-adherence is part of real-world performance. A clinician or regulator may want the pharmacologic effect among patients who actually received an adequate trial. These are different estimands. If non-adherence is counted as failure, call it strategy failure; if not, define minimum exposure/PDC/persistence rules and account for adherence as an intercurrent event.

When to use

Use a treatment-failure/non-response endpoint when the research question is about real-world effectiveness, sequencing, unmet need, treatment-resistant disease, time to next treatment, rescue therapy burden, or the population that remains uncontrolled after starting a therapy. It is especially useful in chronic inflammatory disease, oncology, diabetes, asthma/COPD, epilepsy, migraine, depression, heart failure, rare disease, and any setting where response is multidimensional and routine care produces treatment changes before hard endpoints accrue.

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

- Claims-only data labeled as clinical non-response. Claims can show what was billed or dispensed; they usually cannot show tumor shrinkage, remission, disease activity, symptom improvement, or clinician intent. Label a claims-only endpoint as "proxy treatment failure" or "time to treatment change," not non-response, unless validated against charts. - No adequate-trial window. A switch three days after initiation may be a formulary correction or intolerance, not failure. Require minimum exposure, minimum persistence, and enough time for the therapy to plausibly work before declaring no response. - Informative measurement cadence. Patients who are sicker, wealthier, treated at academic centers, or on drugs requiring monitoring have more labs, scans, and notes. More measurement means more opportunities to detect failure. Report assessment frequency by arm and consider landmark windows, inverse-probability-of-observation weights, or source restriction. - Discontinuation treated as efficacy failure without reason. Discontinuation can mean toxicity, remission, cost, death, pregnancy, side-effect fear, or plan disenrollment. It is a valid component of a net strategy-failure composite, but not a clean pharmacologic non-response endpoint. - Ignoring death and other terminal events. For a non-fatal failure endpoint, death prevents later escalation/switch and should usually be a competing event or an unfavorable composite component, not ordinary censoring. In frail or oncology cohorts, censoring death can make a high-mortality treatment look falsely "failure-free." - Post-hoc threshold shopping. Trying several response thresholds, gap rules, and escalation definitions until the result is pleasing creates a non-reproducible endpoint. Lock the threshold hierarchy in the protocol/SAP and route alternates to sensitivity analysis.

Data-source operational depth

- Claims (FFS / commercial with complete medical + pharmacy). Observable signals are fills, days_supply, medical-claim administrations, procedures, diagnosis-coded acute events, ED/hospital use, and rescue medications. Require continuous observable enrollment and complete pharmacy + medical benefits; exclude or flag MA-only/capitated spans where missing claims can masquerade as no escalation, discontinuation, or no rescue therapy. Build exposure episodes before failure classification, apply stockpiling/carry-over and inpatient-bridging rules, and pre-specify whether switch, dose escalation, augmentation, rescue therapy, and discontinuation each trigger failure. Failure mode: a pharmacy benefit change or PA denial looks like clinical failure; without reason-for-change data, keep the component label and avoid causal language. - EHR. Strongest for labs, vitals, scores, medication orders/administrations, clinician notes, and radiology text. Use structured fields where available and NLP/abstraction for response language only after validation. Failure modes: orders are not fills, problem lists lag reality, external care is missing, and assessment frequency differs by site and arm. Capture baseline value, response assessment date, value/source, and whether the assessment was scheduled, clinically prompted, or opportunistic if the data allow it. - Registry. Strong for clinician-adjudicated response categories, disease activity, stage, and reasons for switch, but may miss complete medication fills and out-of-registry care. Use the registry to validate response/failure classification and link to claims for continuous treatment and rescue-medication capture. - Linked claims-EHR-registry-vital records. Best substrate: clinical response from EHR/registry, complete treatment history from claims, reasons for change from notes/registry, and death as a competing/composite event. Linkage selection and date discrepancies must be reconciled before assigning failure dates.

Worked example (claims + EHR inadequate response composite)

Question: among new users of biologic A for inflammatory bowel disease, estimate time to proxy treatment failure over 12 months. (1) Index date = first administration/fill after 365 days with no biologic A and complete medical + pharmacy enrollment. (2) Adequate-trial window = 90 days after index; events before day 90 are classified as early intolerance/access events unless the protocol makes them failure. (3) Clinical response component from EHR: post-index fecal calprotectin or disease activity score at 90-180 days; no response if the value fails to improve by the disease-specific threshold or remains above the active-disease cutoff. (4) Pattern proxy components from claims: dose escalation/interval shortening after day 90, systemic corticosteroid rescue after day 90, IBD-related hospitalization, switch to a different advanced therapy, or discontinuation after a permissible gap not bridged by another observable therapy. (5) Failure date = earliest qualifying component date; store `failure_component`, `failure_source`, and `adequate_trial_met`. (6) Death before failure is a competing event for time-to-failure and a component in the net clinical failure composite if the estimand says death is unfavorable. (7) Sensitivities vary adequate-trial window (60/90/120 days), discontinuation gap (45/60/90 days), and whether discontinuation without switch counts as failure.

Interpreting the output

If Patient 9180 starts biologic A on 2024-01-05, has 92 persistent days of therapy, receives steroid rescue on 2024-04-20, dose escalation on 2024-05-18, and switches to biologic B on 2024-07-01, the composite failure endpoint fires on 2024-04-20 with component = "rescue therapy." The later dose escalation and switch are retained as subsequent treatment-pattern events but do not change the time-to-first-failure endpoint. If the research question is pharmacologic non-response, the analyst must check whether adherence and adequate exposure were sufficient before calling the rescue event non-response; if the research question is strategy failure, the rescue event can be counted directly.

Index definitions

Source-backed definitions and variants for the index or checklist family.

namedefinitionsourceusenotes
Clinical non-responseFailure to meet a pre-specified disease-specific response threshold after an adequate exposure and assessment window.Disease-specific response criteria and protocol/SAP definitionBest endpoint when structured labs, scores, imaging, PROs, or clinician assessments are available.Requires baseline status, assessment timing, threshold, and missing-measurement handling.
Proxy treatment failureTreatment-pattern signal that the initial strategy was not adequate or acceptable, such as escalation, rescue therapy, switch, discontinuation, or next line of therapy.Claims/EHR treatment-pattern algorithmsScalable endpoint in claims or mixed data when clinical response is not consistently observed.Measures care decisions and strategy failure, not pure pharmacologic efficacy.
Loss of responseInitial response followed by later worsening, treatment escalation, rescue therapy, switch, or new line of therapy.Longitudinal response and treatment-pattern dataChronic disease, oncology, and immune-mediated disease analyses where response can wane.Requires retaining both first response date and subsequent failure date.

Worked example

Scenario

A patient starts biologic A for inflammatory bowel disease on 2024-01-05. The protocol defines adequate exposure as at least 90 days of persistence. After that window, any of the following can trigger proxy treatment failure first: steroid rescue, dose escalation, switch to another advanced therapy, IBD hospitalization, or EHR-documented no response. The patient receives steroid rescue before any later escalation or switch, so the failure date is the rescue date.

Dataset

One-patient treatment and response record. The component that occurs first after the adequate-trial window fires the time-to-first-failure endpoint.

person_idevent_dateevent_typesourcequalifies_after_adequate_trial
91802024-01-05biologic_A_startpharmacy/infusion claimnot applicable
91802024-04-05adequate_trial_metderived persistence ruleyes
91802024-04-20steroid_rescuepharmacy claimyes
91802024-05-18dose_escalationmedical/pharmacy claimyes
91802024-07-01switch_to_biologic_Bpharmacy/infusion claimyes

Steps

  • Set the index date to 2024-01-05, the first observable biologic A fill or administration.

  • Require the adequate-trial window to be met before classifying a pattern change as treatment failure. Here the patient remains persistent through 2024-04-05, so the window is met.

  • List all qualifying post-window failure signals in date order. The first is systemic steroid rescue on 2024-04-20.

  • Assign failure = 1, failure_date = 2024-04-20, failure_component = steroid_rescue, and failure_source = pharmacy claim.

  • Retain later dose escalation and switch as subsequent trajectory data, but do not move the time-to-first-failure date.

  • In reporting, call this proxy treatment failure unless chart/lab evidence confirms clinical non-response.

Result

Proxy treatment failure occurs on 2024-04-20, 106 days after index, triggered by steroid rescue after the adequate trial window. Dose escalation and switch occur later and are retained as component history but do not redefine the first failure date.

Timeline Spec

Title

Treatment failure composite for one patient

Window
Start

2024-01-05

End

2024-07-01

Label

Biologic A start through observed switch

Events
  • Label

    Biologic A start

    Start

    2024-01-05

    Quantity

    Day 0 - index treatment initiation

  • Label

    Adequate trial met

    Start

    2024-04-05

    Marker Day

    91

    Quantity

    90+ days persistent on biologic A

  • Label

    Steroid rescue

    Start

    2024-04-20

    Marker Day

    106

    Quantity

    First qualifying failure component

    Flag

    composite_trigger

  • Label

    Dose escalation

    Start

    2024-05-18

    Marker Day

    134

    Quantity

    Later component; retained, not first failure

  • Label

    Switch to biologic B

    Start

    2024-07-01

    Marker Day

    178

    Quantity

    Later component; retained, not first failure

Spans
  • Kind

    exposed

    Start

    2024-01-05

    End

    2024-04-05

    Label

    Adequate-trial window

  • Kind

    followup

    Start

    2024-04-05

    End

    2024-04-20

    Label

    At risk for failure after adequate trial

Result
Label

Failure date = 2024-04-20; component = steroid rescue; time to failure = 106 days

Value

106

Caption

The patient is not judged for failure until the adequate-trial window is met. The first qualifying failure signal after that point is steroid rescue, so the composite endpoint fires there.

Alt Text

A horizontal patient timeline from January 5 to July 1, 2024. The adequate trial window ends on April 5. A steroid rescue marker on April 20 is flagged as the first failure component; later dose escalation and switch markers are shown but do not change the first-failure date.

Runnable example

python implementation

Minimal treatment-failure composite builder. Inputs are already cleaned and restricted to observable person-time: index : person_id, index_date persistence: person_id, persistent_days_on_index clinical : person_id, assessment_date, response_class # e.g.,...

import pandas as pd

ADEQUATE_TRIAL_DAYS = 90
FAILURE_TYPES = {
    "rescue_therapy",
    "dose_escalation",
    "switch",
    "next_line",
    "discontinuation",
    "failure_hospitalization",
}
CLINICAL_FAILURE_CLASSES = {"no_response", "partial_inadequate_response", "loss_of_response"}

def build_treatment_failure(index, persistence, clinical, events):
    idx = index.merge(persistence, on="person_id", how="left")
    idx["adequate_trial_met"] = idx["persistent_days_on_index"].fillna(0) >= ADEQUATE_TRIAL_DAYS
    idx["trial_end"] = idx["index_date"] + pd.to_timedelta(ADEQUATE_TRIAL_DAYS, unit="D")

    clinical_fail = clinical[clinical["response_class"].isin(CLINICAL_FAILURE_CLASSES)].copy()
    clinical_fail = clinical_fail.rename(columns={"assessment_date": "failure_date"})
    clinical_fail["failure_component"] = clinical_fail["response_class"]
    clinical_fail["failure_source"] = "clinical_response_assessment"

    proxy_fail = events[events["event_type"].isin(FAILURE_TYPES)].copy()
    proxy_fail = proxy_fail.rename(columns={"event_date": "failure_date", "event_type": "failure_component"})
    proxy_fail["failure_source"] = "treatment_pattern_proxy"

    candidates = pd.concat([
        clinical_fail[["person_id", "failure_date", "failure_component", "failure_source"]],
        proxy_fail[["person_id", "failure_date", "failure_component", "failure_source"]],
    ], ignore_index=True)

    candidates = candidates.merge(idx[["person_id", "index_date", "trial_end", "adequate_trial_met"]], on="person_id")
    candidates = candidates[(candidates["adequate_trial_met"]) & (candidates["failure_date"] >= candidates["trial_end"])]

    first = (candidates.sort_values(["person_id", "failure_date"])
             .groupby("person_id", as_index=False)
             .first())
    first["time_to_failure_days"] = (first["failure_date"] - first["index_date"]).dt.days
    return first
r implementation

R/data.table version of the treatment-failure composite. Inputs: index person_id, index_date persistence person_id, persistent_days_on_index clinical person_id, assessment_date, response_class events person_id, event_date, event_type Clinical non-response...

library(data.table)

build_treatment_failure <- function(index, persistence, clinical, events,
                                    adequate_trial_days = 90L) {
  setDT(index); setDT(persistence); setDT(clinical); setDT(events)
  failure_types <- c("rescue_therapy", "dose_escalation", "switch",
                     "next_line", "discontinuation", "failure_hospitalization")
  clinical_failure <- c("no_response", "partial_inadequate_response", "loss_of_response")

  idx <- merge(index, persistence, by = "person_id", all.x = TRUE)
  idx[is.na(persistent_days_on_index), persistent_days_on_index := 0L]
  idx[, adequate_trial_met := persistent_days_on_index >= adequate_trial_days]
  idx[, trial_end := index_date + adequate_trial_days]

  cfail <- clinical[response_class %in% clinical_failure,
                    .(person_id, failure_date = assessment_date,
                      failure_component = response_class,
                      failure_source = "clinical_response_assessment")]
  pfail <- events[event_type %in% failure_types,
                  .(person_id, failure_date = event_date,
                    failure_component = event_type,
                    failure_source = "treatment_pattern_proxy")]
  cand <- rbindlist(list(cfail, pfail), use.names = TRUE, fill = TRUE)
  cand <- merge(cand, idx[, .(person_id, index_date, trial_end, adequate_trial_met)], by = "person_id")
  cand <- cand[adequate_trial_met == TRUE & failure_date >= trial_end]
  setorder(cand, person_id, failure_date)
  first <- cand[, .SD[1], by = person_id]
  first[, time_to_failure_days := as.integer(failure_date - index_date)]
  first[]
}