Restart, Rechallenge, and New-Episode Rules
A protocol-specified set of exposure-episode rules that classify a later dispensing of the same drug as continuation of an ongoing episode, a restart after a permissible gap, a rechallenge after a safety-driven dechallenge, or a distinct new treatment episode, because each classification changes who is counted, when follow-up starts, and what the estimand means.
On this page
When a patient stops a drug and then refills it later, analysts must decide whether that later fill continues the original treatment period or starts a brand-new one — and, critically, whether the restart happened after a safety scare on the drug. The rules in this concept draw a firm line around four situations: continuing without a real gap, restarting after an ordinary gap, restarting specifically because a doctor rechallenged after a bad reaction, and beginning a clinically fresh course after a very long break. Getting the classification right matters because every count of who is being treated, for how long, and from what starting point is built on top of these rules.
Restart, rechallenge, and new-episode rules
are the deterministic logic that turns a stream of pharmacy dispensings (or orders/administrations) into discrete treatment episodes and decides how to handle a re-appearance of the same drug after exposure has lapsed. The rules are not a single threshold; they are a small decision tree applied per `person_id` per drug, evaluated in date order over `fill_date` and `days_supply`, against
- the gap since the prior episode's covered end,
- whether an intervening adverse event / intolerance triggered the stop, and
- whether the indication or clinical context has changed. Because every downstream quantity — incidence-rate denominators, persistence/discontinuation, time-zero for a new-user contrast, drug-utilization counts, and per-member cost denominators — is built on top of these episodes, the rules must be written into protocol/SAP language before programming and stress-tested with sensitivity analyses on the thresholds that drive them.
Core conceptual distinction
Four mutually exclusive states must be separable, and conflating any two is a reviewable error:
- Continuation — the next fill arrives within the allowable gap (typically the prior `days_supply` end plus a pre-specified grace period). It extends the same episode; no new time-zero, no new "initiation."
- Restart — exposure lapsed beyond the grace period but re-initiation reflects ordinary stop/start behavior (cost, forgetting, a drug holiday), with no intervening adverse event. Whether a restart opens a new analytic episode depends on the question: for persistence it is a new episode; for cumulative-dose effects it may be the same chronic exposure resumed.
- Rechallenge — re-initiation after a dechallenge that was itself driven by an adverse event or intolerance. This is a safety-specific construct: the dechallenge-positive / rechallenge-positive sequence is one of the strongest individual-level signals of drug causality (it is an explicit item in the Naranjo and WHO-UMC causality algorithms). A rechallenge is never "just another restart" — the prior stop carries information about the outcome.
- New episode — the re-appearance belongs to a clinically distinct course: a different indication, a gap so long the prior course is irrelevant (a "new-episode" threshold, e.g., > 365 days), or a re-qualifying diagnostic event. A new episode legitimately resets time-zero and washout for a new-user-style analysis.
The estimand must name which states open a new at-risk episode and which do not. A cause-specific hazard for first discontinuation treats restart as a new spell; an as-treated cumulative-exposure model stitches restarts into continuous person-time with on/off indicators; a rechallenge safety analysis conditions follow-up on the dechallenge-rechallenge sequence itself (and is the design behind prescription-sequence-symmetry and case-only rechallenge studies).
Pros, cons, and trade-offs
- vs a single fixed-gap "any refill = same episode" rule: Explicit four-state rules are transparent, reproducible, and defensible to FDA/EMA/HTA reviewers, and they prevent the silent merging of a safety rechallenge into a benign restart. Cost: more code, more diagnostics, and more thresholds to justify and vary in sensitivity analysis. Prefer the explicit rules for any consequential comparative-safety, effectiveness, utilization, or cost-denominator analysis.
- vs prescription-sequence-symmetry (PSSA) / case-only rechallenge designs: PSSA exploits the temporal symmetry of an event around the (re)start to self-control for time-invariant confounding and is excellent for hypothesis screening. Cost: it answers a narrower signal-detection question and assumes the event does not itself affect the probability of the second dispensing. Prefer cohort episode rules when you need rate or cumulative-incidence contrasts; prefer PSSA for rapid, confounding-robust signal screening of a suspected rechallenge effect.
- vs collapsing everything into prevalent-user person-time: Counting all dispensings as one undifferentiated exposure is simplest but destroys time-zero, re-introduces immortal time (the survivor who lives long enough to refill), and makes "restart vs rechallenge" invisible. Never prefer this for causal contrasts.
When NOT to use — and when it is actively misleading or dangerous
- When the data cannot observe the gap. If person-time inside a gap is unobservable (e.g., Medicare Advantage enrollees whose fee-for-service pharmacy claims are not in the source), a "gap" may be missingness, not a true stop — classifying it as a restart or new episode manufactures spurious initiations. Restrict to continuously observable (e.g., Part D / commercial pharmacy-benefit) person-time before applying the rules.
- When you let a rechallenge masquerade as a restart in a safety study. If the dechallenge was AE-driven and you fold the re-initiation into ongoing person-time, you both dilute the rechallenge signal and bias the comparator — survivors who tolerated and resumed look healthier (depletion of susceptibles). This is the classic place the method becomes dangerous.
- When new-episode resets create immortal time. Resetting time-zero at a "new episode" defined using future information (e.g., requiring the patient to survive to a later qualifying fill) re-creates immortal time bias (Suissa). The qualifying logic must use only information available at the candidate time-zero.
- When stockpiling/oversupply fakes continuation. Mail-order 90-day fills, sample fills, and refill-ahead behavior inflate `days_supply` coverage and erase real gaps; without stockpiling/carry-over rules the algorithm will call a true discontinuation a continuation.
Data-source operational depth
- Administrative claims (FFS vs MA vs commercial): The episode is built from `fill_date` + `days_supply` + NDC. Failure modes: (1) MA-only person-time lacks FFS pharmacy claims — a clean-looking 200-day gap may simply be a period you cannot see; require continuous Part A/B/D (or commercial medical + pharmacy) enrollment across each gap you intend to classify, and exclude MA-only spans. (2) Claims reversals and same-day duplicates inflate fill counts — collapse to net paid dispensings before stitching. (3) Adjudication/run-out lag truncates the last observable fill — censor at end-of-data, not at the last fill. (4) Bundled/inpatient drugs are invisible in Part D — an apparent gap during a hospitalization is often bridged inpatient exposure (see inpatient-bridging-exposure-rwe).
- EHR: Exposure is the order or administration, not the dispensing; restarts/rechallenges are frequently captured in unstructured notes ("rechallenged after rash resolved") that structured order tables miss, and external-care leakage means a restart prescribed elsewhere is invisible. Differential, encounter-driven capture makes gaps look longer for patients who simply left the system; treat loss to follow-up as potentially informative and prefer linked dispensing.
- Registry: Often strongest for the reason a drug was stopped (adjudicated AE → enables true rechallenge classification) but weak for complete refill history; link to claims for fills and to a death index so a "permanent discontinuation" is not actually an unrecorded death.
- Linked claims–EHR–registry: The ideal substrate — registry/EHR supply the AE that defines a dechallenge while claims supply the complete fill history — but order/fill/administration date discrepancies and linkage selection must be reconciled before assigning episode boundaries.
Worked claims example
Question: classify exposure to drug X (an oral immunomodulator) into episodes in a commercial + Medicare FFS database, distinguishing a safety rechallenge from a routine restart. Setup per `person_id`, drug X NDCs only, sorted by `fill_date`; require continuous medical + pharmacy enrollment (no MA-only spans) across every evaluated gap. Define `covered_through = fill_date + days_supply`, GRACE = 30 days, RESTART_MAX = 180 days, NEW_EPISODE = 365 days. Walking the fills: - 2023-02-01, days_supply 30 → covered_through 2023-03-03. Next fill 2023-03-10: gap = 7 days ≤ GRACE → continuation (same episode; do not reset time-zero).
- That episode's last fill is 2023-04-10 (covered_through 2023-05-10). Next fill 2023-08-01: gap = 83 days, in (GRACE, RESTART_MAX]. Check for an intervening AE diagnosis (e.g., a hepatotoxicity dx + drug discontinuation in 2023-05) → none found → restart (new persistence episode; same chronic exposure for a cumulative-dose model).
- Suppose instead an inpatient dx of drug-induced hepatitis appears 2023-05-15 with no further X fills for months, then X re-appears 2024-01-15. Because the stop was AE-driven (a dechallenge) and the re-initiation follows it, this is a rechallenge — flagged for the dechallenge-positive/rechallenge-positive safety analysis, not silently merged.
- A fill of X appearing 2025-06-01, > NEW_EPISODE days after the prior covered end and accompanied by a re-qualifying indication, opens a new episode: reset washout and time-zero for a new-user-style contrast. Diagnostics: pre/post episode counts, the distribution of computed gaps with the threshold cut points overlaid, patient-level timelines for a sample, the share of "gaps" occurring during unobservable MA spans, and a sensitivity analysis varying GRACE (15/30/60), RESTART_MAX (90/180), and the AE-window used to define a dechallenge.
Decision diagram
flowchart TD
F[Next same-drug fill<br/>gap = fill_date - prior covered_through] --> G{gap <= grace?}
G -- yes --> C[Continuation<br/>same episode, no new time-zero]
G -- no --> A{AE-driven dechallenge<br/>before this re-initiation?}
A -- yes --> R[Rechallenge<br/>safety estimand; do NOT merge into person-time]
A -- no --> N{gap > new-episode threshold<br/>or new indication?}
N -- yes --> E[New episode<br/>reset washout + time-zero]
N -- no --> S[Restart<br/>new persistence spell;<br/>same chronic exposure for cumulative-dose]gantt title One patient, drug X: continuation, restart, rechallenge, new episode dateFormat YYYY-MM-DD axisFormat %b %Y section Episode 1 Fill + days_supply (covered) :done, e1a, 2023-02-01, 30d Refill within grace (continuation) :done, e1b, 2023-03-10, 30d section Restart Gap 83d, no AE -> restart :active, rs, 2023-08-01, 30d section Rechallenge AE dx (dechallenge) :crit, ae, 2023-05-15, 1d Re-initiation after AE -> rechallenge :crit, rc, 2024-01-15, 30d section New episode Gap > 365d + new indication -> reset time-zero :milestone, ne, 2025-06-01, 0d
Worked example
Scenario
Patient 2047 is prescribed methotrexate (an oral immunomodulator used for rheumatoid arthritis) starting January 10, 2023. She fills it twice in the spring and appears to be continuing therapy without interruption. Then she stops for several months after developing abnormal liver labs in May — a safety-driven dechallenge. Her rheumatologist rechallenges her in October at a lower dose. We want to label each fill as continuation, restart, or rechallenge, and identify which fills belong to Episode 1 versus Episode 2.
Dataset
Pharmacy claims rows for patient 2047 (methotrexate only, one row per fill, already cleaned for duplicates).
| person_id | fill_date | drug | days_supply | covered_through |
|---|---|---|---|---|
| 2047 | 2023-01-10 | methotrexate | 90 | 2023-04-09 |
| 2047 | 2023-04-05 | methotrexate | 90 | 2023-07-03 |
| 2047 | 2023-10-15 | methotrexate | 90 | 2024-01-12 |
Steps
Result
- Label
Episode 1 (continuation): Jan 10 – Jul 3, 2023 (174 covered days across 2 fills). Episode 2 (rechallenge): starts Oct 15, 2023. Fill C is flagged as a safety rechallenge — not a routine restart — because the May 22 liver-labs event is within 90 days of the end of Episode 1.
- Value
2 episodes; Fill C state = rechallenge
Trade-offs
Runnable example
Classify same-drug fills into continuation / restart / rechallenge / new-episode states from claims-style inputs. Required inputs (already cleaned: reversals and same-day duplicates collapsed, restricted to the target drug's NDCs, restricted to continuously enrolled, FFS-observable person-time): rx : person_id,...
import pandas as pd
import numpy as np
GRACE_DAYS = 30 # consecutive fills within days_supply + GRACE extend the SAME episode
RESTART_MAX_DAYS = 180 # gap in (GRACE, RESTART_MAX] -> restart; below new-episode threshold
NEW_EPISODE_DAYS = 365 # gap > this (or new indication) -> a clinically distinct new episode
AE_WINDOW_DAYS = 90 # an AE within this window of the prior covered end marks a dechallenge
def classify_episodes(rx: pd.DataFrame, ae: pd.DataFrame) -> pd.DataFrame:
rx = rx.sort_values(["person_id", "fill_date"]).copy()
rx["covered_through"] = rx["fill_date"] + pd.to_timedelta(rx["days_supply"], unit="D")
ae_by_person = ae.groupby("person_id")["ae_date"].apply(list).to_dict()
out_rows = []
for pid, g in rx.groupby("person_id", sort=False):
ae_dates = ae_by_person.get(pid, [])
episode_id = 0
prev_covered = None
for row in g.itertuples(index=False):
if prev_covered is None:
state = "new_episode" # first observed fill opens episode 0
else:
gap = (row.fill_date - prev_covered).days
if gap <= GRACE_DAYS:
state = "continuation"
else:
# Was the prior stop driven by an adverse event? -> rechallenge.
dechallenge = any(
0 <= (a - prev_covered).days <= AE_WINDOW_DAYS or
0 <= (prev_covered - a).days <= AE_WINDOW_DAYS
for a in ae_dates
)
if dechallenge:
state = "rechallenge"
elif gap <= RESTART_MAX_DAYS:
state = "restart"
else:
state = "new_episode" # gap > NEW_EPISODE (RESTART_MAX < NEW_EPISODE) or any long gap
if state != "continuation":
episode_id += 1 # restart/rechallenge/new_episode open a new analytic episode
out_rows.append((pid, row.fill_date, row.covered_through, episode_id, state))
# Coverage can extend if a restart overlaps the prior tail; take the later end.
prev_covered = row.covered_through if prev_covered is None else max(prev_covered, row.covered_through)
return pd.DataFrame(out_rows,
columns=["person_id", "fill_date", "covered_through", "episode_id", "state"])Same four-state episode classifier with data.table. Inputs mirror the Python version: rx : person_id, fill_date (Date), days_supply (integer) ae : person_id, ae_date (Date) # adverse-event dates defining a possible dechallenge Input must be pre-cleaned (reversals/duplicates collapsed, single drug, continuously...
library(data.table)
GRACE_DAYS <- 30L
RESTART_MAX_DAYS <- 180L
NEW_EPISODE_DAYS <- 365L
AE_WINDOW_DAYS <- 90L
classify_episodes <- function(rx, ae) {
setDT(rx); setDT(ae)
setorder(rx, person_id, fill_date)
rx[, covered_through := fill_date + days_supply]
ae_list <- split(ae$ae_date, ae$person_id)
rx[, c("episode_id", "state") := {
eid <- 0L; prev_cov <- as.Date(NA); ad <- ae_list[[as.character(.BY$person_id)]]
eids <- integer(.N); sts <- character(.N)
for (i in seq_len(.N)) {
if (is.na(prev_cov)) {
st <- "new_episode"
} else {
gap <- as.integer(fill_date[i] - prev_cov)
if (gap <= GRACE_DAYS) {
st <- "continuation"
} else {
dechallenge <- !is.null(ad) && any(abs(as.integer(ad - prev_cov)) <= AE_WINDOW_DAYS)
st <- if (dechallenge) "rechallenge"
else if (gap <= RESTART_MAX_DAYS) "restart"
else "new_episode"
}
}
if (st != "continuation") eid <- eid + 1L
eids[i] <- eid; sts[i] <- st
prev_cov <- if (is.na(prev_cov)) covered_through[i] else max(prev_cov, covered_through[i])
}
list(eids, sts)
}, by = person_id]
rx[, .(person_id, fill_date, covered_through, episode_id, state)]
}Four-state episode classification via a sorted DATA step with BY-group state carried in RETAIN. Required inputs (post data-management: single drug, reversals/duplicates collapsed, continuously observable person-time): work.rx : person_id, fill_date, days_supply work.ae : person_id, ae_date (adverse-event dates that...
%let grace = 30; /* days_supply + grace extends the same episode */
%let restartmax = 180; /* gap in (grace, restartmax] -> restart */
%let newepisode = 365; /* gap > this (or new indication) -> new episode */
%let aewindow = 90; /* AE within this window of prior covered end = dechallenge */
/* Nearest AE to each fill's prior covered-through is computed by joining the AE table.
Here we flag, per fill, whether ANY AE fell within +/- aewindow of the prior covered end. */
proc sort data=work.rx; by person_id fill_date; run;
proc sort data=work.ae; by person_id ae_date; run;
data work.episodes;
set work.rx;
by person_id;
retain prev_cov episode_id;
format fill_date covered_through date9.;
/* Load all AE dates into a hash ONCE (keyed by person_id, multidata for >1 AE/person).
A do-until(eof) SET of work.ae inside the main step would read the whole AE table on the
first rx row and exhaust it, so later fills could never look up an AE; the hash lets every
fill probe its person's AE dates independently via find()/find_next(). */
if _n_ = 1 then do;
declare hash ae(dataset:"work.ae", multidata:"Y");
ae.defineKey("person_id");
ae.defineData("ae_date");
ae.defineDone();
end;
covered_through = fill_date + days_supply;
if first.person_id then do; prev_cov = .; episode_id = 0; end;
length state $12;
if prev_cov = . then state = "new_episode";
else do;
gap = fill_date - prev_cov;
if gap <= &grace then state = "continuation";
else do;
/* dechallenge if any AE for this person is within aewindow of the prior covered end */
dech = 0;
rc = ae.find(); /* first AE for this person_id */
do while (rc = 0);
if abs(ae_date - prev_cov) <= &aewindow then dech = 1;
rc = ae.find_next(); /* walk remaining AEs for this person */
end;
if dech then state = "rechallenge";
else if gap <= &restartmax then state = "restart";
else state = "new_episode";
end;
end;
if state ne "continuation" then episode_id + 1; /* open a new analytic episode */
prev_cov = max(prev_cov, covered_through);
keep person_id fill_date covered_through episode_id state;
run;Citations
- [1]Andrade SE, Kahler KH, Frech F, Chan KA. Methods for evaluation of medication adherence and persistence using automated databases. Pharmacoepidemiology and Drug Safety. 2006;15(8):565-574.
- [2]Naranjo CA, Busto U, Sellers EM, et al. A method for estimating the probability of adverse drug reactions. Clinical Pharmacology and Therapeutics. 1981;30(2):239-245.
- [3]Ray WA. Evaluating medication effects outside of clinical trials: new-user designs. American Journal of Epidemiology. 2003;158(9):915-920.