Switch, Add-On, and Augmentation Rules
A set of pre-specified operational rules that classify a treatment modification observed in longitudinal data as a switch, an add-on, an augmentation, a combination start, or a line advancement, based on the timing and overlap of exposure episodes across drug classes.
On this page
When a patient changes their drug regimen, analysts need a precise rule to decide what kind of change happened. A switch means the first drug stopped and a second drug took its place; an add-on (or augmentation) means the second drug was added while the first was still being taken. The difference is decided by one thing you can see in pharmacy claims data: does the first drug's supply of pills still have days left on the calendar when the second drug's fills begin? If yes, the two drugs overlap and it is an add-on; if no, the first drug had already run out (or nearly so) before the second started, and it is a switch. Getting this right matters because grouping switchers and add-on patients together quietly mixes two very different clinical decisions.
Switch, add-on, and augmentation rules
are the algorithm that turns a stream of dispensings or administrations into a classified treatment trajectory. Once exposure episodes have been built (see exposure-episode-construction-rwe), every point where a patient's regimen changes must be labeled, because the label — not the raw fill — is what defines cohorts, index dates, follow-up start, lines of therapy, and the comparator in a treatment-pattern or comparative-effectiveness study. The same calendar event (a new fill of drug B while the patient is on drug A) is a switch, an add-on, or an augmentation depending entirely on the timing rules and the clinical interpretation you pre-specify; getting the rule wrong silently misclassifies exposure for everyone in the cohort.
Core conceptual distinction
Four transitions must be separated, and the operational tell for each is timing, not the drug itself.
- Switch — class A stops (no fill within a grace/gap window) and class B starts. The patient is on B instead of A. Operationally: `start(B) - end_of_supply(A) <= SWITCH_GAP_DAYS` (a near-contiguous handoff) AND no further A fills.
- Add-on / combination — class B starts while class A's `days_supply` is still active. Both classes overlap. If A was itself recently initiated (the patient was effectively treatment-naive to the combination), this is a planned combination start; if A had been running for a while, B is an add-on.
- Augmentation — a specific, clinically loaded subtype of add-on: B is added to an ongoing, persistent A that was given an adequate therapeutic trial without resolution (e.g., adding an atypical antipsychotic to an SSRI in treatment-resistant depression, or a thiazide to an ACE inhibitor in uncontrolled hypertension). The operational tell that distinguishes augmentation from a plain add-on is prior persistence on A (`days_on_A_before_B >= AUGMENT_PRIOR_PERSISTENCE_DAYS`, often an adequate-trial window such as 28–56 days) plus continuation of A after B starts.
- Line advancement — the regimen as a whole changes after a maintenance gap or a documented progression/failure event, starting a new line of therapy. This is the unit oncology, MS, and IRA Medicare price-negotiation analyses report on. These thresholds — `SWITCH_GAP_DAYS`, `OVERLAP_DAYS_FOR_ADDON`, `AUGMENT_PRIOR_PERSISTENCE_DAYS`, the maintenance-gap that closes a line — are the judgment-dependent parameters; every consequential analysis must vary them in sensitivity analyses.
Pros, cons, and trade-offs
- vs a single naive rule (e.g., "any new drug class = switch"): Explicit, separately-tunable rules are transparent, reproducible, and defensible to FDA/EMA/HTA reviewers, and they prevent the dominant error of collapsing add-ons and augmentations into switches (which inflates "switching" and empties out "combination" exposure). Cost: more code, more diagnostics, and the need to defend each threshold. Prefer explicit rules for any regulatory-grade or HTA study.
- vs purely clinical (chart-adjudicated) classification: Rule-based classification scales to millions of patients and is fully reproducible; chart review captures intent ("inadequate response", "intolerance") that timing alone cannot. The augmentation-vs-add-on distinction in particular is an intent construct that claims approximate via prior persistence. Prefer rules at scale, but validate against charts where the switch/augment distinction drives the estimand.
- vs ignoring the distinction entirely (treat all post-index drugs as time-varying covariates): Folding everything into a time-varying confounder is defensible for some causal questions but discards the treatment-pattern endpoint and makes "what did patients actually do next" unanswerable. Prefer explicit classification whenever sequencing, lines, or persistence-to-next-treatment is the outcome.
When NOT to use — and when it is actively misleading or dangerous
- When the underlying exposure episodes are unreliable. These rules are only as good as the `days_supply`, gap, and stockpiling assumptions feeding them (see grace-period-gap-rules-rwe, stockpiling-carryover-rules-rwe). Garbage episodes produce confident, wrong labels.
- When data cannot observe the comparator drug. In Medicare Advantage-only person-time, fee-for-service pharmacy and medical claims are absent, so an "add-on" can be an artifact of one class being invisible. Restrict to fully observable enrollment before classifying.
- When augmentation requires intent that the data cannot carry. Calling an add-on an "augmentation" without evidence of prior adequate trial fabricates a treatment-resistance phenotype. If the estimand hinges on intent, validate against charts or drop the augmentation label.
- Infused/clinic-administered or inpatient drugs. Oncology infusions, biologics, and inpatient bundles have no `days_supply`; applying oral gap logic to them is dangerous (see infused-biologic-administration-capture-rwe, inpatient-bridging-exposure-rwe). Use administration-interval logic instead.
- When line definitions are imposed without progression data. In oncology, defining line advancement purely by drug gaps — without a progression or new-regimen signal — conflates a treatment holiday with progression and miscounts lines.
Data-source operational depth
- Claims (FFS): The workhorse substrate. Build class-level episodes from pharmacy NDCs (`fill_date`, `days_supply`) and from medical/HCPCS J-codes for clinic-administered drugs. Failure modes: 90-day mail order and stockpiling distend `days_supply` so overlaps look like add-ons; same-day duplicate or reversed claims create phantom combinations (de-duplicate and net out reversals first); adjudication lag means recent fills are incomplete near the data cut. Require continuous medical and pharmacy enrollment across the classification window so "no fill of A" is true absence, not unobserved care.
- Claims (Medicare Advantage vs FFS): MA-only person-time lacks FFS claims; a switch can look like a discontinuation and an add-on can be invisible. Exclude MA-only spans or restrict to A/B/D FFS enrollees (see medicare-ffs-ma-commercial-claims-differences-rwe).
- EHR: Classification keys off orders/administrations, not dispensings, and order ≠ taken. Visit-driven capture means a drug added by an outside specialist is missing, so an augmentation is misread as monotherapy continuation; external care leakage is the dominant bias. Link to pharmacy fills where possible.
- Registry: Often carries adjudicated regimen/line and progression but incomplete fill history; strong for the line-advancement label, weak for the day-level switch/add-on timing. Link to claims for fill-level resolution.
- Linked claims–EHR: Best substrate — EHR progression/intent plus claims completeness — but order/fill/service date discrepancies must be reconciled before deciding which event came first, since the switch-vs-add-on label is decided by day-level ordering.
Worked claims example (antidepressant augmentation vs switch, FFS pharmacy)
Question: among adults who initiate an SSRI for depression, classify the first regimen modification. Inputs: pharmacy fills with `person_id`, `fill_date`, `days_supply`, `drug_class` in {SSRI, SNRI, ATYPICAL_ANTIPSYCHOTIC}; continuous medical+pharmacy FFS enrollment. Thresholds: `SWITCH_GAP_DAYS = 30`, `OVERLAP_DAYS_FOR_ADDON = 1`, `AUGMENT_PRIOR_PERSISTENCE_DAYS = 56` (an adequate SSRI trial).
- Build SSRI episodes by stitching consecutive fills with gaps <= 30 days; the episode's covered period runs from the first `fill_date` to the last `fill_date + days_supply`. Patient: SSRI fills 2024-01-03 (30d), 2024-02-01 (30d), 2024-03-02 (30d) — covered through 2024-03-31, 87 persistent days.
- On 2024-03-10 an aripiprazole (ATYPICAL) fill appears.
- Is the SSRI still active on 2024-03-10? Yes (covered through 2024-03-31), so this is an overlap → not a switch.
- Had the patient been persistent on the SSRI for >= 56 days before 2024-03-10? Days on SSRI before the add = 2024-03-10 − 2024-01-03 = 67 days >= 56 → label = augmentation (atypical added to an adequately-trialed, ongoing SSRI). Contrast: had the SSRI instead stopped (last covered day 2024-02-05) and an SNRI started 2024-02-20 with no further SSRI fills, then `start(SNRI) − end(SSRI) = 15 <= 30` and SSRI does not resume → label = switch. Had the aripiprazole been added on 2024-01-20 (only 17 SSRI-days, < 56) while the SSRI continued → label = add-on (not augmentation): combination too early to call treatment-resistant. Sensitivity analyses re-run all labels at `SWITCH_GAP_DAYS` ∈ {15, 30, 60} and `AUGMENT_PRIOR_PERSISTENCE_DAYS` ∈ {28, 56, 84}, and report a transition table (counts of switch / add-on / augmentation / line-advance) before and after each threshold change.
Decision diagram
flowchart TD
Mod[New fill of class B while/after class A] --> Q1{Class A still has active days_supply<br/>when B starts? overlap >= OVERLAP_DAYS_FOR_ADDON}
Q1 -- No --> Q2{B starts within SWITCH_GAP_DAYS of A's<br/>last covered day, and A does not resume?}
Q2 -- Yes --> SW[SWITCH<br/>B instead of A]
Q2 -- No --> LA[LINE ADVANCE / NEW EPISODE<br/>gap exceeds maintenance window]
Q1 -- Yes --> Q3{Persistent on A for >=<br/>AUGMENT_PRIOR_PERSISTENCE_DAYS<br/>adequate trial before B?}
Q3 -- Yes --> AUG[AUGMENTATION<br/>B added to adequately-trialed ongoing A]
Q3 -- No --> AO[ADD-ON / COMBINATION<br/>B added to A early]gantt title Augmentation example - atypical added to an adequately-trialed SSRI dateFormat YYYY-MM-DD axisFormat %b section SSRI (index class) SSRI episode (fills 1/3, 2/1, 3/2; covered through 3/31) :done, ssri, 2024-01-03, 2024-03-31 section Atypical antipsychotic Aripiprazole start (day 67 of SSRI, SSRI still active) :milestone, ari, 2024-03-10, 0d Augmentation: B added to ongoing, persistent A :active, aug, 2024-03-10, 21d
Worked example
Scenario
Patient 2001 is an adult who starts sertraline (an SSRI antidepressant) on January 5, 2024. We want to classify what happens when a second drug appears in their pharmacy record on March 10, 2024 — but the answer depends entirely on whether the patient also refilled their sertraline in early March. We trace two parallel versions of events: Scenario S (Switch) where the sertraline was not refilled before March 10, and Scenario A (Add-on/Augmentation) where a March 1 refill means sertraline is still active when the second drug arrives.
Dataset
Pharmacy fills as they appear in a claims table — same patient, two scenarios that differ only in whether Drug A (sertraline) has a third fill on 2024-03-01.
| person_id | scenario | fill_date | drug | drug_class | days_supply |
|---|---|---|---|---|---|
| 2001 | Both | 2024-01-05 | sertraline | SSRI | 30 |
| 2001 | Both | 2024-02-02 | sertraline | SSRI | 30 |
| 2001 | Scenario A only | 2024-03-01 | sertraline | SSRI | 30 |
| 2001 | Both | 2024-03-10 | aripiprazole | ATYPICAL | 30 |
Steps
Result
- Switch
Scenario S: Drug A last active 2024-03-02, Drug B starts 2024-03-10, gap = 7 days <= 30-day grace period, Drug A does not resume → classification = SWITCH
- Augmentation
Scenario A: Drug A active through 2024-03-30, Drug B starts 2024-03-10, overlap = 21 days, prior persistence on Drug A = 65 days >= 56-day threshold → classification = AUGMENTATION
Trade-offs
Runnable example
Classify the FIRST treatment modification per patient as switch / add_on / augmentation / line_advance from claims-style pharmacy fills. Required input (cleaned, de-duplicated, reversals netted out): rx : person_id, fill_date (datetime), drug_class (str), days_supply (int) # one row per fill Episodes are built per...
import pandas as pd
import numpy as np
SWITCH_GAP_DAYS = 30 # max gap to treat consecutive fills as one episode / a contiguous switch handoff
OVERLAP_DAYS_FOR_ADDON = 1 # min active-supply overlap of two classes to call an add-on/combination
AUGMENT_PRIOR_PERSISTENCE_DAYS = 56 # adequate-trial persistence on the first class before an add-on becomes augmentation
def _episodes(g: pd.DataFrame) -> pd.DataFrame:
# Stitch one drug_class's fills into covered episodes (gap-tolerant).
g = g.sort_values("fill_date")
g["end"] = g["fill_date"] + pd.to_timedelta(g["days_supply"], unit="D")
ep_start, ep_end, rows = None, None, []
for _, r in g.iterrows():
if ep_start is None:
ep_start, ep_end = r["fill_date"], r["end"]
elif r["fill_date"] <= ep_end + pd.Timedelta(days=SWITCH_GAP_DAYS):
ep_end = max(ep_end, r["end"]) # extend (stockpiling caps at observed end)
else:
rows.append((ep_start, ep_end)); ep_start, ep_end = r["fill_date"], r["end"]
rows.append((ep_start, ep_end))
return pd.DataFrame(rows, columns=["ep_start", "ep_end"])
def classify_first_modification(rx: pd.DataFrame) -> pd.DataFrame:
out = []
for pid, p in rx.groupby("person_id"):
eps = (p.groupby("drug_class", group_keys=True)
.apply(_episodes)
.reset_index(level=0).reset_index(drop=True))
eps = eps.sort_values("ep_start")
first = eps.iloc[0] # the index regimen class/episode
index_class = first["drug_class"]
later = eps[(eps["ep_start"] > first["ep_start"]) & (eps["drug_class"] != index_class)]
if later.empty:
out.append((pid, index_class, None, "no_modification")); continue
nxt = later.iloc[0] # first modification event
overlap_days = (min(first["ep_end"], nxt["ep_end"]) - nxt["ep_start"]).days
index_still_active = overlap_days >= OVERLAP_DAYS_FOR_ADDON
prior_persistence = (nxt["ep_start"] - first["ep_start"]).days
if not index_still_active and (nxt["ep_start"] - first["ep_end"]).days <= SWITCH_GAP_DAYS:
label = "switch"
elif index_still_active and prior_persistence >= AUGMENT_PRIOR_PERSISTENCE_DAYS:
label = "augmentation"
elif index_still_active:
label = "add_on"
else:
label = "line_advance" # gap exceeds maintenance window -> new line/episode
out.append((pid, index_class, nxt["drug_class"], label))
return pd.DataFrame(out, columns=["person_id", "index_class", "modifier_class", "modification"])Classify the first treatment modification per patient (switch / add_on / augmentation / line_advance) with data.table. Input mirrors the Python version: rx : person_id, fill_date (Date), drug_class (character), days_supply (integer) Thresholds are the judgment-dependent constants varied in sensitivity analyses.
library(data.table)
SWITCH_GAP_DAYS <- 30L
OVERLAP_DAYS_FOR_ADDON <- 1L
AUGMENT_PRIOR_PERSISTENCE_DAYS <- 56L
build_episodes <- function(d) { # d: fills of ONE person+class, sorted by fill_date
setorder(d, fill_date)
d[, end := fill_date + days_supply]
es <- d$fill_date[1L]; ee <- d$end[1L]; out <- list()
if (nrow(d) > 1L) for (i in 2:nrow(d)) {
if (d$fill_date[i] <= ee + SWITCH_GAP_DAYS) ee <- max(ee, d$end[i])
else { out[[length(out)+1L]] <- list(ep_start = es, ep_end = ee); es <- d$fill_date[i]; ee <- d$end[i] }
}
out[[length(out)+1L]] <- list(ep_start = es, ep_end = ee)
rbindlist(out)
}
classify_first_modification <- function(rx) {
setDT(rx)
eps <- rx[, build_episodes(.SD), by = .(person_id, drug_class), .SDcols = c("fill_date","days_supply")]
setorder(eps, person_id, ep_start)
eps[, {
first_class <- drug_class[1L]; fs <- ep_start[1L]; fe <- ep_end[1L]
later <- which(ep_start > fs & drug_class != first_class)
if (length(later) == 0L) .(index_class = first_class, modifier_class = NA_character_, modification = "no_modification")
else {
j <- later[1L]
overlap_days <- as.integer(min(fe, ep_end[j]) - ep_start[j])
active <- overlap_days >= OVERLAP_DAYS_FOR_ADDON
prior <- as.integer(ep_start[j] - fs)
lab <- if (!active && as.integer(ep_start[j] - fe) <= SWITCH_GAP_DAYS) "switch"
else if (active && prior >= AUGMENT_PRIOR_PERSISTENCE_DAYS) "augmentation"
else if (active) "add_on"
else "line_advance"
.(index_class = first_class, modifier_class = drug_class[j], modification = lab)
}
}, by = person_id]
}Classify the first treatment modification per patient (switch / add_on / augmentation / line_advance) in SAS. Required input (post data-management, de-duplicated, reversals netted): work.rx : person_id, fill_date (SAS date), drug_class (char), days_supply (num) Step 1 stitches per-class episodes with a gap-tolerant...
%let switch_gap = 30; /* max gap to stitch fills / call a contiguous switch */
%let addon_ovl = 1; /* min overlap days to call an add-on/combination */
%let augment = 56; /* prior persistence on index class -> augmentation */
proc sort data=work.rx; by person_id drug_class fill_date; run;
/* Step 1: gap-tolerant episodes per person x drug_class. */
data episodes;
set work.rx; by person_id drug_class fill_date;
retain ep_start ep_end;
end_supply = fill_date + days_supply;
if first.drug_class then do; ep_start = fill_date; ep_end = end_supply; end;
else if fill_date <= ep_end + &switch_gap then ep_end = max(ep_end, end_supply);
else do;
output; /* close prior episode */
ep_start = fill_date; ep_end = end_supply;
end;
if last.drug_class then output; /* flush final episode */
keep person_id drug_class ep_start ep_end;
format ep_start ep_end date9.;
run;
/* Step 2: index regimen = earliest episode; first modification = earliest later episode in a different class. */
proc sql;
create table first_index as
select person_id, drug_class as index_class, ep_start as fs, ep_end as fe
from episodes
group by person_id
having ep_start = min(ep_start);
create table modification as
select i.person_id, i.index_class, m.drug_class as modifier_class,
(min(i.fe, m.ep_end) - m.ep_start) as overlap_days,
(m.ep_start - i.fs) as prior_persistence,
case
when calculated overlap_days < &addon_ovl and (m.ep_start - i.fe) <= &switch_gap then 'switch'
when calculated overlap_days >= &addon_ovl and calculated prior_persistence >= &augment then 'augmentation'
when calculated overlap_days >= &addon_ovl then 'add_on'
else 'line_advance'
end as modification length=12
from first_index i
inner join episodes m
on i.person_id = m.person_id and m.drug_class ne i.index_class and m.ep_start > i.fs
group by i.person_id
having m.ep_start = min(m.ep_start);
quit;Citations
- [1]Hess LM, Krein PM, Haldane D, Han Y, Sireci AN. Defining treatment regimens and lines of therapy using real-world data in oncology. Future Oncology. 2021;17(15):1865-1877.
- [2]Hripcsak G, Ryan PB, Duke JD, et al. Characterizing treatment pathways at scale using the OHDSI network. Proceedings of the National Academy of Sciences. 2016;113(27):7329-7336.