← Methods repository
concept

Stockpiling and Carryover Rules

The episode-construction rule that decides whether days_supply from an early (overlapping) refill is carried forward to extend later exposure coverage, and how much accumulated oversupply is allowed to accrue before it is capped or reset.

Exposure_Definitionexposure-definitionstockpilingcarryoverdays-supplydrug-eratreatment-episodeadherence-measurementperson-time
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

When a patient refills a chronic medication before the current supply runs out, they build up a surplus of pills on hand — that is called stockpiling. A carryover rule decides what to do with that surplus: instead of throwing away the leftover days and restarting the clock at each new fill date, the carryover rule shifts each new fill's coverage forward so the extra days are banked and pushed to the end of the timeline. This matters because without carryover you can manufacture a fake gap in coverage even when the patient always had pills available, and with carryover the true coverage end date is later than the last fill date alone would suggest.

Stockpiling and carryover rules

govern what happens when a patient refills a chronic medication before the prior fill's supply has run out. Each pharmacy claim carries a `fill_date` and a `days_supply`; naively, exposure runs from `fill_date` to `fill_date + days_supply`. But real refill behavior is bursty — patients refill early (90-day mail order, vacation overrides, copay timing), so consecutive supply windows overlap. The carryover rule decides whether that overlap is (a) discarded (the clock restarts at each new fill), (b) preserved by shifting the new fill's coverage to begin only after the prior supply is exhausted (so excess days "bank" and push the run-out date later), or (c) preserved but capped so accumulated oversupply cannot grow without bound. It is the single most consequential — and most often unspecified — decision in turning dispensing records into a person-time exposure timeline, and it directly changes both adherence metrics (PDC/MPR numerators) and the exposed/unexposed person-time that feeds incidence rates and hazard ratios.

Core conceptual distinction

— three rules sit on a spectrum and produce materially different timelines from identical claims. (1) No carryover (truncate-at-next-fill / "as dispensed"): a new fill resets the window; any unused days from the prior fill are thrown away. This is the most conservative for current exposure but understates total drug acquired and can manufacture artificial "gaps" the moment a patient refills early. (2) Full carryover (shift-forward stitching): the new fill's coverage is shifted to start at `max(fill_date, prior_run_out)`, so banked days accumulate and the run-out date drifts forward — the basis of OMOP drug-era construction with a `gap` parameter and of carryover-allowed PDC. (3) Capped carryover: full carryover, but cumulative excess is held to a ceiling (commonly 30–90 days, or "no more than one extra dispensing"), preventing implausible months of banked supply from a string of early refills. Orthogonal to all three is the gap-reset rule: when an observed gap between run-out and the next fill exceeds a permissible threshold, the episode closes and a new one begins (no carryover across the gap). The estimand distinction is sharp: a carryover-allowed timeline measures theoretical inventory / cumulative acquisition (good for chronic-effectiveness "ever-treated" or PDC-style adherence), whereas a no-carryover or short-cap timeline approximates current pharmacologic exposure at a point in time (what a safety rate of an acute event actually requires). Choosing the wrong one is not a tuning detail — it changes the quantity estimated.

Pros, cons, and trade-offs

(each compared to the named alternative). - Full carryover vs no carryover. Full carryover correctly credits early refillers as continuously covered, avoids spurious gaps, and matches how chronic adherence (PDC/MPR with stockpiling allowed) is meant to be measured; it is the realistic default for steady-state chronic therapy. Cost: it pushes the modeled run-out date later than the patient's actual drug-taking, so in a safety analysis an adverse event occurring after the patient truly stopped can be misclassified as "on drug," inflating exposed person-time and biasing the incidence rate toward the null. Prefer no carryover when the estimand is current exposure to an acute hazard; prefer full carryover for cumulative adherence and chronic-effectiveness contrasts. - Capped vs uncapped full carryover. Capping (e.g., excess ≤ 90 days, or drop pre-run-out duplicate fills beyond one) prevents the pathological case where serial early refills bank a year of phantom supply that keeps a long-discontinued patient "exposed." Cost: the cap is an arbitrary tuning knob that must be pre-specified and sensitivity-tested; too tight a cap re-creates artificial gaps. Prefer capping in any safety or per-protocol analysis; report the cap and vary it. - vs simply using OMOP drug-era / `drug_era_gap`. The OMOP drug-era is a packaged carryover-with-gap implementation (default 30-day persistence window, configurable gap). It is reproducible and standard across the network, but its single global gap parameter hides the stockpiling decision and rarely caps oversupply — auditing the resulting eras against raw fills is still required. Prefer the OMOP era for federated/standardized work, but document and, if needed, override its gap and add a cap. - vs grace-period gap rules. A grace period is about closing an episode after a permissible gap; the carryover rule is about banking surplus before a gap occurs. They are complementary and must be specified together — a generous grace period plus uncapped carryover is the combination most likely to fabricate immortal-style exposed time.

When to use

— any time pharmacy dispensing is converted to a longitudinal exposure or adherence variable: PDC/MPR computation, drug-era / treatment-episode construction, time-updated exposure for Cox or pooled-logistic models, and persistence (time-to-discontinuation) analyses. The rule must be written into the protocol/SAP before programming and reported explicitly, because it is invisible in the final estimate yet drives it.

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

(decision rules below). - Acute-event safety analyses with full/uncapped carryover. If the outcome is an acute event (e.g., GI bleed, syncope, rhabdomyolysis) and you allow uncapped carryover, you extend "exposed" person-time past the patient's true last dose. An event after real cessation is then counted as exposed, the exposed incidence rate is diluted, and a true harm is biased toward the null. Use no-carryover or a short cap and align exposure to current pharmacology. - Discontinuation / deprescribing / persistence studies. Carryover masks the very gaps you are trying to detect; banked supply makes a patient who stopped look persistent. Carryover should be off (or minimal) and the gap-reset rule drives the discontinuation date. - PRN / as-needed and titrated drugs. `days_supply` for as-needed inhalers, nitroglycerin, opioids, or insulin is fiction (the field reflects the dispensed quantity, not consumption), so any carryover arithmetic compounds a fabricated denominator. Do not build inventory timelines for these from `days_supply` alone. - Implausible accumulation left uncapped. A patient with twelve 30-day fills in six months under full carryover banks ~180 phantom days; uncapped, they remain "covered" long after they could plausibly still hold supply. Always cap or flag-and-review impossible inventories.

Data-source operational depth

(each with real failure modes and workarounds). - Claims (FFS). `fill_date` + `days_supply` are the substrate. Real failure modes: (i) 90-day mail order overlapping a 30-day retail fill — a same-week refill of a smaller script looks like massive stockpiling that is really a channel switch; de-duplicate by NDC/strength and prefer the larger supply. (ii) Same-day duplicate paid claims (reversal + re-bill, split fills) double-count days_supply unless collapsed. (iii) Free samples, 340B, and discount-card fills never appear in claims, so true acquisition is undercounted and apparent gaps are artifactual. Workaround: pre-specify de-duplication, cap carryover, and run the timeline both with and without the cap. - Medicare FFS vs Medicare Advantage (MA). MA-only person-time lacks fee-for-service Part D claims in many datasets, so a "gap" during MA enrollment is missingness, not discontinuation, and any carryover/gap logic applied across it is invalid. Restrict to enrollees with observable Part D (or commercial pharmacy benefit) and censor or exclude MA-only person-time before stitching episodes. - Long-term-care (LTC) and inpatient stays. Bundled/per-diem LTC pharmacy and inpatient medications usually do not generate individual retail claims; an institutional stay produces an apparent gap mid-episode. Carryover from the pre-admission fill can either correctly bridge it or wrongly bank supply — decide explicitly and see inpatient-bridging rules. Differential institutionalization by arm (more frequent in the sicker/older arm) then induces differential carryover error. - EHR. Order/medication-list "active" dates are not dispensings; carryover arithmetic on EHR e-prescribing data without linked fill confirmation overstates real acquisition (the prescription may never have been filled). Prefer linked pharmacy claims; if only EHR, treat "active medication" windows as a separate, weaker exposure definition. - Registry / linked. Registries rarely capture complete dispensing; link to claims for fills and reconcile order/fill/service-date discrepancies before assigning run-out dates. Linkage selection (only the linkable subset) can correlate with refill behavior.

Worked claims example

A patient (`person_id = 7`) with continuous FFS Part D enrollment has three 30-day fills of a statin: `fill_date` = 2024-01-01, 2024-01-20, 2024-02-25, each `days_supply = 30`. The second fill arrives 19 days into the first 30-day supply (11 days of overlap → banked surplus); the third arrives after a real gap. - No carryover (truncate-at-next-fill): episode coverage = [Jan 1, Jan 20) then [Jan 20, Feb 19) then [Feb 25, Mar 26). Run-out before the third fill is Feb 19; the Feb 19→Feb 25 stretch is a 6-day gap, and the 11 banked days are discarded. Cumulative excess = 0. - Full carryover (shift-forward): fill 2 is shifted to start at the prior run-out (Jan 31), so coverage runs Jan 1 → Mar 2 continuously; cumulative excess after fill 2 = 11 days. Fill 3 (Feb 25) arrives 5 days before the carried run-out (Mar 2), so excess grows to 16 days and run-out moves to Apr 1. No gap is declared — the early refills are credited. - Capped carryover (cap = 90 days): identical to full carryover here because 16 < 90; the cap only bites after many early refills. (If the same patient kept refilling every 19–25 days, uncapped excess would balloon; the cap would hold run-out to at most prior_run_out + 90.) - Gap-reset (permissible gap = 15 days): under no-carryover the Feb 19→Feb 25 gap (6 days) is < 15, so the episode does not reset and the third fill continues the same episode; had the third fill been 2024-03-20 (29-day observed gap > 15), the episode would close on Feb 19 and a new episode would start Mar 20. The four rules give run-out dates of Mar 26 (no carryover), Apr 1 (full/capped carryover) and different episode counts — from one PDC/incidence-rate input. PDC over a 90-day Jan 1–Mar 31 window: no-carryover credits 84 covered days (gap of 6) → PDC ≈ 0.93; full carryover credits all 90 → PDC = 1.00. The choice, not the data, moved the metric.

Worked example

Scenario

Patient 2201 takes a daily statin for cholesterol. We are watching a 90-day window from January 1 through March 30, 2024. She picks up three 30-day fills but refills early each time, building a surplus. We want to find the carryover-adjusted coverage end date and compare it to what the last fill date alone would suggest.

Dataset

Raw pharmacy claims rows for patient 2201 — one row per fill as an analyst would see them.

person_idfill_datedrugdays_supply
22012024-01-01atorvastatin30
22012024-01-22atorvastatin30
22012024-02-19atorvastatin30

Steps

  • Fill A starts Jan 01 and covers 30 days: Jan 01 through Jan 30. The supply would run out on Jan 31.

  • Fill B arrives Jan 22 — nine days before Fill A runs out on Jan 31. That early refill creates 9 banked surplus days.

  • With carryover, Fill B's coverage is shifted to start when Fill A actually runs out (Jan 31), so Fill B covers Jan 31 through Feb 29 and its run-out shifts to Mar 01.

  • Fill C arrives Feb 19 — eleven days before Fill B's carried run-out of Mar 01. That early refill banks 11 more surplus days (total banked = 9 + 11 = 20 days).

  • With carryover, Fill C's coverage shifts to start Mar 01, covers Mar 01 through Mar 30, and its run-out becomes Mar 31.

  • Coverage is continuous from Jan 01 through Mar 30 with no gaps — the three shifted fills stitch together with zero uncovered days.

  • Without carryover the last fill (Feb 19 + 30 days) would end Mar 19, leaving Mar 20 through Mar 30 uncovered — an 11-day gap that does not reflect reality, since the patient was holding surplus pills the whole time.

Result

Carryover-adjusted coverage end: 2024-03-30 (run-out date 2024-03-31). Over the 90-day window (Jan 01 to Mar 30), the patient had medication on hand every day: covered days = 90, PDC = 90/90 = 1.00. Without carryover only 79 of the 90 days are credited (an 11-day gap Mar 20 to Mar 30), giving PDC = 79/90 = 0.88. The 12-point difference comes entirely from how the analyst handles the banked surplus, not from any difference in the patient's actual fills.

Timeline Spec

Title

Stockpiling with full carryover — three early statin fills for patient 2201

Window
Start

2024-01-01

End

2024-03-30

Label

Denominator: 90-day observation window (Jan 01 to Mar 30)

Events
  • Label

    Fill A

    Start

    2024-01-01

    Length Days

    30

    Quantity

    30 days_supply

  • Label

    Fill B (9-day early refill)

    Start

    2024-01-22

    Length Days

    30

    Quantity

    30 days_supply

  • Label

    Fill C (11-day early refill)

    Start

    2024-02-19

    Length Days

    30

    Quantity

    30 days_supply

Spans
  • Kind

    covered

    Start

    2024-01-01

    End

    2024-03-19

    Label

    79 days covered under both rules

  • Kind

    covered

    Start

    2024-03-20

    End

    2024-03-30

    Label

    11 extra days credited only with carryover (banked surplus)

Result
Label

Carryover-adjusted coverage end: 2024-03-30 — PDC 1.00 vs 0.88 without carryover

Value

1.0

Caption

Each fill bar starts at the actual fill date, making the early-refill overlaps visible as stockpiling. The carryover rule shifts each fill's effective coverage to start at the prior run-out, so the banked surplus days push the final coverage end from Mar 19 (no carryover) to Mar 30 (with carryover) — an 11-day extension that changes PDC from 0.88 to 1.00.

Alt Text

Timeline with three 30-day statin fill bars for patient 2201 plotted against a 90-day observation window. Fill A starts Jan 01, Fill B starts Jan 22 overlapping the end of Fill A, and Fill C starts Feb 19 overlapping the carryover projection of Fill B. Two stacked coverage spans are shown below the fills: a light green bar from Jan 01 to Mar 19 labeled 79 days covered under both rules, and a darker green bar from Mar 20 to Mar 30 labeled 11 extra days credited only with carryover, illustrating how banked surplus days extend coverage beyond what the last fill date alone implies.

Runnable example

python implementation

Stockpiling/carryover episode construction from claims-style pharmacy fills. Required input (cleaned, de-duplicated): rx : one row per fill -> person_id, fill_date (datetime64), days_supply (int) For ONE drug per person. Returns one row per fill with the...

import pandas as pd
import numpy as np

def build_episodes(rx: pd.DataFrame,
                   rule: str = "capped",      # 'none' | 'full' | 'capped'
                   cap_days: int = 90,        # max banked excess under 'capped'
                   reset_gap_days: int = 30   # observed gap that closes an episode
                   ) -> pd.DataFrame:
    rx = rx.sort_values(["person_id", "fill_date"]).copy()
    out = []
    for pid, g in rx.groupby("person_id", sort=False):
        prev_run_out = None          # carried run-out date of the open episode
        excess = 0                   # banked surplus days (for capping)
        episode = 0
        for _, r in g.iterrows():
            fill = r["fill_date"]
            sup = int(r["days_supply"])
            new_ep = False
            if prev_run_out is None:
                start = fill
            else:
                gap = (fill - prev_run_out).days          # >0 = real gap, <0 = early refill
                if gap > reset_gap_days:                   # true discontinuation -> new episode
                    new_ep = True
                    excess = 0
                    start = fill
                elif rule == "none" or gap >= 0:           # no overlap: start at fill
                    start = fill
                else:                                       # early refill -> carry forward
                    banked = -gap                          # overlapping (surplus) days
                    if rule == "capped":
                        banked = min(banked, max(0, cap_days - excess))
                    excess += banked
                    start = fill + pd.Timedelta(days=banked) if rule != "none" else fill
            run_out = start + pd.Timedelta(days=sup)
            if new_ep or prev_run_out is None:
                episode += 1
            prev_run_out = run_out
            out.append({"person_id": pid, "fill_date": fill, "days_supply": sup,
                        "episode": episode, "episode_start": start,
                        "run_out_date": run_out, "cumulative_excess": excess,
                        "new_episode": new_ep})
    return pd.DataFrame(out)
r implementation

Stockpiling/carryover episode construction with data.table. Input mirrors the Python version: rx : person_id, fill_date (Date), days_supply (integer); one drug per person. rule in {'none','full','capped'}; cap_days caps banked excess; reset_gap_days closes...

library(data.table)

build_episodes <- function(rx, rule = "capped", cap_days = 90L, reset_gap_days = 30L) {
  setDT(rx); setorder(rx, person_id, fill_date)
  rx[, {
    prev_run_out <- as.Date(NA); excess <- 0L; episode <- 0L
    res <- vector("list", .N)
    for (i in seq_len(.N)) {
      fill <- fill_date[i]; sup <- as.integer(days_supply[i]); new_ep <- FALSE
      if (is.na(prev_run_out)) {
        start <- fill
      } else {
        gap <- as.integer(fill - prev_run_out)            # >0 real gap, <0 early refill
        if (gap > reset_gap_days) {                        # true discontinuation -> new episode
          new_ep <- TRUE; excess <- 0L; start <- fill
        } else if (rule == "none" || gap >= 0) {
          start <- fill
        } else {                                            # early refill -> carry forward
          banked <- -gap
          if (rule == "capped") banked <- min(banked, max(0L, cap_days - excess))
          excess <- excess + banked
          start <- fill + banked
        }
      }
      run_out <- start + sup
      if (new_ep || is.na(prev_run_out)) episode <- episode + 1L
      prev_run_out <- run_out
      res[[i]] <- list(fill_date = fill, days_supply = sup, episode = episode,
                       episode_start = start, run_out_date = run_out,
                       cumulative_excess = excess, new_episode = new_ep)
    }
    rbindlist(res)
  }, by = person_id]
}