Voluntary (Non-Imposed) Post-Authorisation Safety Study
A sponsor-initiated post-authorisation safety study that is not a condition of the marketing authorisation, conducted under GVP Module VIII to identify, characterise, or quantify a safety hazard or confirm the safety profile of an already-authorised medicine.
On this page
A Post-Authorization Safety Study (PASS) is research a drug company runs on a medicine that regulators have already approved, specifically to look for safety problems in real-world use. A voluntary PASS is one the company chooses to run on its own, rather than because a regulatory agency made it a condition of approval. Because the drug is already on the market and patients are taking it as their doctor prescribes, these studies almost always use existing records — insurance claims, hospital records, or disease registries — instead of enrolling people in a controlled experiment. The goal is to answer the question: does this approved drug cause harm we did not fully see before approval, and how often?
A post-authorisation safety study (PASS) is, under EMA Good Pharmacovigilance Practices (GVP) Module VIII, "any study relating to an authorised medicinal product conducted with the aim of identifying, characterising or quantifying a safety hazard, confirming the safety profile of the medicine, or measuring the effectiveness of risk-management measures."
A PASS is voluntary (non-imposed) when the marketing-authorisation holder initiates it on its own accord rather than because a competent authority has made it a binding condition of the authorisation. Most voluntary PASS are non-interventional: the medicine is prescribed in the usual manner per the marketing authorisation, treatment is not decided by a protocol, and no additional diagnostic or monitoring procedures are applied — so the study is a secondary-data cohort, case-control, self-controlled, or registry analysis rather than a trial.
Core conceptual distinction
. The defining axis is regulatory status and control, not the analytic method — the same new-user cohort can be either a voluntary or an imposed PASS. (1) Voluntary vs imposed: an imposed PASS is a condition of the marketing authorisation under Article 9, 21a, or 22a of Directive 2001/83/EC (Annex II / the risk management plan), so the PRAC assesses the draft protocol before the study starts and assesses the final results, protocol substantial amendments need approval, milestones are binding, and non-completion carries regulatory and legal consequences (variation, suspension, fees).
A voluntary PASS sits outside that mandatory oversight: the sponsor controls timing, scope, and publication; PRAC protocol pre-approval is not required (though ENCePP/EU PAS Register registration and the ENCePP Code of Conduct are strongly encouraged and increasingly expected by HTA bodies and journals).
(2) Non-interventional vs clinical-trial PASS: a voluntary PASS may legally be a clinical trial, but in practice it is overwhelmingly non-interventional, which is what places it in the realm of RWE database design. The estimand is the same family of pharmacovigilance quantities — absolute incidence of an adverse event of special interest (AESI), a comparative hazard versus an active comparator or background population, or a standardised incidence ratio against an external reference — assessed for safety, with the analytic burden concentrated on outcome ascertainment, susceptibility windows, and confounding by indication rather than on demonstrating efficacy.
Pros, cons, and trade-offs
.
- vs imposed PASS: A voluntary PASS gives the sponsor design latitude, faster start (no PRAC protocol gate), and control over scope and dissemination — useful for hypothesis-generating signal characterisation, label-enrichment evidence, or HTA-facing safety packages. Cost: it carries less a priori regulatory weight, PRAC has not endorsed the protocol, and a voluntary study cannot by itself discharge a binding pharmacovigilance obligation. Prefer voluntary when the safety question is sponsor-driven and not a regulatory condition; an imposed PASS is required when the authority has mandated the evidence as a condition of marketing.
- vs spontaneous-reporting / disproportionality signal detection: A PASS supplies a defined denominator (person-time at risk), a comparator, and protocol-prespecified outcome definitions, so it quantifies and tests a hazard rather than merely flagging it. Cost: far more expensive and slower than mining a spontaneous-report database. Prefer a PASS to characterise or refute a signal that disproportionality analysis has already raised.
- vs a head-to-head comparative-effectiveness study: A PASS is governed by the pharmacovigilance legal framework (GVP) and is safety-focused, so it inherits PSUR/RMP linkage, qualified-person-for-pharmacovigilance accountability, and adverse-event reporting obligations that a generic effectiveness study does not. Cost: that governance overhead is wasted if the question is purely comparative effectiveness. The analytic core of a non-interventional PASS is usually an active-comparator new-user or self-controlled design — the PASS label adds the regulatory wrapper.
When NOT to use — and when it is actively misleading or dangerous
.
- The study is a condition of the marketing authorisation. If PRAC or a national authority has imposed it, a voluntary design does not satisfy the obligation; submitting voluntary work in its place is a compliance failure. Use the imposed pathway with PRAC protocol assessment.
- The intervention departs from routine care. Allocating treatment by protocol, adding non-routine tests, or randomising converts the study into a clinical trial; calling it a "non-interventional PASS" mislabels it and evades the correct ethics/regulatory regime — a serious integrity problem.
- The data cannot support the safety estimand. A rare AESI needs a denominator and follow-up that a short, fragmented data source cannot deliver; reporting an "incidence" on unstable person-time is misleading. If only signal detection is feasible, do not dress it up as a quantitative PASS.
- Confounding by indication is unaddressed. Comparing a drug to non-users for a safety outcome reproduces channelling bias; without an active comparator and time-zero alignment, a "reassuring" or "alarming" PASS result can be an artefact, not the drug.
Data-source operational depth
.
- Claims (FFS or commercial): Exposure is the pharmacy claim (NDC + `fill_date` + `days_supply`); AESIs are captured from inpatient/outpatient diagnosis and procedure codes. Require continuous medical + pharmacy enrollment across baseline so absence of prior exposure and outcomes is observed, not missing. Failure modes: Medicare Advantage-only person-time lacks fee-for-service claims, so AESI ascertainment is silently incomplete — restrict to enrollees with Parts A/B/D (or commercial medical+pharmacy) and exclude MA-only spans. Acute, hospitalisation-coded AESIs (e.g. anaphylaxis, DKA, acute liver injury) are well captured; insidious or outpatient-managed events are not. Claims carry no death cause and weak severity, so adjudication-ready code algorithms with PPV from prior validation are essential.
- EHR: Labs, vitals, problem lists, and notes sharpen AESI definitions (e.g. ALT/AST thresholds for Hy's-law liver injury) and baseline risk factors that claims miss — a real advantage for safety. But visit-driven capture means a patient who leaves the network is differentially lost, and an out-of-network hospitalisation for the very AESI of interest can be invisible; define observation windows explicitly and treat loss to follow-up as potentially informative.
- Registry (disease/product/pregnancy): Strongest for adjudicated, clinically rich safety outcomes and for products with mandated pregnancy or device registries; typically weak for complete drug exposure and for a contemporaneous comparator. Link to claims for the full fill history and to a death index to firm up censoring and fatal-outcome capture.
- Linked claims–EHR–vital records: The ideal substrate for a safety PASS — EHR severity + claims completeness + reliable mortality — but linkage selects the linkable subset and introduces order/fill/service-date discrepancies that must be reconciled before time-zero and the susceptibility window are fixed.
Worked claims example
Voluntary, non-interventional PASS to quantify the incidence of acute liver injury (ALI) among new users of a recently authorised oral antifungal, with an active comparator, in a commercial + Medicare FFS database.
- Eligibility: age ≥18 and ≥365 days of continuous A/B/D (or commercial medical+pharmacy) enrollment before the first dispensing — the baseline window in which prior ALI and risk factors (alcohol-related codes, hepatitis, hepatotoxic co-medications) are measured.
- New-user washout: no fill of the study drug or the comparator antifungal in the prior 365 days, so person-time starts at a true initiation.
- Time zero = first qualifying `fill_date`; assign arm from the dispensed NDC.
- Prespecified AESI algorithm: first inpatient ALI diagnosis (ICD code on a hospital claim) with no ALI code in baseline; this first-event coding plus the washout removes prevalent disease.
- Susceptibility / risk window: from time zero through the last covered day (`fill_date` + `days_supply`) plus a prespecified 30-day carry-over, reflecting drug-induced liver injury latency.
- Person-time and censoring: accrue at risk until the first ALI event, disenrollment, death, end of data, or end of the risk window; exclude MA-only spans so person-time reflects FFS-observable claims.
- Output: crude incidence rate per 1,000 person-years per arm, an age/sex-standardised incidence ratio against the comparator, and a Cox or Fine-Gray comparative hazard with death as a competing risk.
- Pre-registration in the EU PAS Register and a negative-control outcome to probe residual confounding complete the protocol — making the voluntary study defensible to PRAC, HTA reviewers, and journals even without imposed oversight.
Decision diagram
flowchart TD
Q[Sponsor safety question on an authorised product] --> Cond{Is the study a CONDITION<br/>of the marketing authorisation?}
Cond -->|Yes - Annex II / Art. 9, 21a, 22a| Imp[Imposed PASS<br/>PRAC assesses protocol + results<br/>binding milestones]
Cond -->|No - sponsor initiative| Vol[Voluntary PASS<br/>sponsor controls timing + scope<br/>ENCePP / EU PAS Register encouraged]
Vol --> Int{Does it depart from routine care?<br/>protocol-assigned treatment, extra tests, randomisation?}
Int -->|Yes| Trial[Clinical-trial PASS<br/>CTR / GCP framework]
Int -->|No| NI[Non-interventional PASS<br/>secondary-data RWE design under GVP Module VIII]
NI --> Eng[Analytic engine: active-comparator new-user<br/>or self-controlled design; AESI estimand]gantt title Voluntary non-interventional PASS timeline for one new initiator (claims) dateFormat YYYY-MM-DD axisFormat %b %Y section Baseline Continuous FFS enrollment + drug washout + no prevalent AESI :done, base, 2023-01-01, 2023-12-31 section Time zero First qualifying fill -> arm assignment :milestone, t0, 2024-01-01, 0d section Risk window On-treatment exposure (days_supply) :active, exp, 2024-01-01, 120d AESI latency carry-over (30 days) :crit, carry, 2024-05-01, 30d section Censoring First AESI / death / disenroll / data end :milestone, cen, 2024-05-31, 0d
Worked example
Scenario
A company has received approval for a new oral antifungal drug. The label mentions a possible risk of liver injury, but the pre-approval trials were too small and too short to measure how often this happens in ordinary patients. The company decides — without being told to by a regulator — to run a voluntary PASS using insurance claims data to find out how common liver injury is among the first real-world users, compared to patients taking an older antifungal. Below is a simplified comparison showing how this voluntary PASS differs from a PASS that a regulator has imposed as a condition of approval.
Dataset
Imposed vs voluntary PASS: a side-by-side comparison of key features
| Feature | Imposed PASS | Voluntary PASS (this concept) |
|---|---|---|
| Who requires it? | Regulatory agency (e.g., EMA/PRAC) — it is a legal condition of approval | The company itself — no regulator has demanded it |
| What question does it answer? | A specific safety question the regulator identified as unanswered before approval | A safety question the sponsor considers important or useful for label or HTA purposes |
| Real-world safety after approval? | Yes — conducted in patients using the approved drug in routine care | Yes — same setting, same kind of real-world data |
| Who reviews the protocol first? | PRAC (the EMA safety committee) must assess and approve the protocol before the study starts | No mandatory regulatory pre-review; ENCePP registration is strongly encouraged |
| What happens if it is not completed? | Legal and regulatory consequences — possible suspension or fines | No legal penalty, but the company loses the scientific and reputational value it sought |
| How does it differ from a pre-approval trial? | Both differ from trials: the drug is prescribed normally, no random assignment, no extra tests added by the protocol | Same — non-interventional, observational, based on routine care records |
Steps
Result
A voluntary PASS is used when the sponsor wants to identify or quantify a real-world safety concern for an approved drug on its own initiative. It follows the same non-interventional, claims- or EHR-based design as an imposed PASS, but sits outside mandatory regulatory oversight — making it faster to start and more flexible in scope, while carrying less inherent regulatory authority than a study the agency required.
Trade-offs
Runnable example
Non-interventional voluntary-PASS engine: build a new-user safety cohort, ascertain a first-event AESI from a validated code algorithm, accrue FFS-observable person-time over a days_supply-based risk window, and return crude incidence rates per arm.
import pandas as pd
import numpy as np
WASHOUT_DAYS = 365 # drug-free + continuous-enrollment baseline that defines a "new user"
CARRYOVER_DAYS = 30 # AESI latency added to the last covered day to close the risk window
def build_pass_cohort(rx: pd.DataFrame, enroll: pd.DataFrame, dx: pd.DataFrame) -> pd.DataFrame:
rx = rx.sort_values(["person_id", "fill_date"])
study = rx[rx["drug_class"].isin(["STUDY", "COMPARATOR"])]
# Time zero = first fill of study drug or active comparator; arm = drug dispensed that day.
idx = (study.groupby("person_id").first().reset_index()
.rename(columns={"fill_date": "index_date", "drug_class": "arm"}))
# New-user washout: drop anyone with a study/comparator fill in the WASHOUT_DAYS before index.
prior = study.merge(idx[["person_id", "index_date"]], on="person_id")
prior = prior[(prior["fill_date"] < prior["index_date"]) &
(prior["fill_date"] >= prior["index_date"] - pd.Timedelta(days=WASHOUT_DAYS))]
idx = idx[~idx["person_id"].isin(prior["person_id"])].copy()
# Continuous, FFS-observable enrollment across baseline through index (no MA-only spans -> no silent AESI gaps).
e = enroll.merge(idx[["person_id", "index_date"]], on="person_id")
e["covers"] = ((e["enroll_start"] <= e["index_date"] - pd.Timedelta(days=WASHOUT_DAYS)) &
(e["enroll_end"] >= e["index_date"]) & (~e["ma_only"]))
idx = idx[idx["person_id"].isin(e.loc[e["covers"], "person_id"])].copy()
# Exclude prevalent AESI: require no AESI dx in the baseline window (first-event definition).
base_dx = dx[dx["aesi"]].merge(idx[["person_id", "index_date"]], on="person_id")
prevalent = base_dx[(base_dx["dx_date"] < base_dx["index_date"]) &
(base_dx["dx_date"] >= base_dx["index_date"] - pd.Timedelta(days=WASHOUT_DAYS))]
idx = idx[~idx["person_id"].isin(prevalent["person_id"])].copy()
# Risk window end = last covered day (fill_date + days_supply) over on-treatment fills, plus carry-over.
on_tx = study.merge(idx[["person_id", "index_date", "arm"]], on="person_id")
on_tx = on_tx[on_tx["fill_date"] >= on_tx["index_date"]]
on_tx["covered_end"] = on_tx["fill_date"] + pd.to_timedelta(on_tx["days_supply"], unit="D")
rx_end = on_tx.groupby("person_id")["covered_end"].max() + pd.Timedelta(days=CARRYOVER_DAYS)
idx = idx.merge(rx_end.rename("risk_end"), on="person_id")
# Censor at min(risk window end, disenrollment, end of data); first incident AESI on/after index = event.
disenroll = enroll.groupby("person_id")["enroll_end"].max().rename("disenroll")
idx = idx.merge(disenroll, on="person_id")
idx["fu_end"] = idx[["risk_end", "disenroll"]].min(axis=1)
inc = dx[dx["aesi"]].merge(idx[["person_id", "index_date", "fu_end"]], on="person_id")
inc = inc[(inc["dx_date"] >= inc["index_date"]) & (inc["dx_date"] <= inc["fu_end"])]
first_evt = inc.groupby("person_id")["dx_date"].min().rename("event_date")
idx = idx.merge(first_evt, on="person_id", how="left")
idx["event"] = idx["event_date"].notna().astype(int)
idx["exit_date"] = idx["event_date"].fillna(idx["fu_end"])
idx["person_days"] = (idx["exit_date"] - idx["index_date"]).dt.days.clip(lower=0)
rates = (idx.groupby("arm")
.agg(events=("event", "sum"), person_years=("person_days", lambda d: d.sum() / 365.25))
.assign(ir_per_1000py=lambda t: 1000 * t["events"] / t["person_years"]))
return rates.reset_index()Non-interventional voluntary-PASS cohort + crude incidence with data.table. Inputs mirror the Python version: rx : person_id, fill_date (Date), drug_class in {'STUDY','COMPARATOR'}, days_supply enroll : person_id, enroll_start (Date), enroll_end (Date), ma_only (logical) dx : person_id, dx_date (Date), aesi...
library(data.table)
WASHOUT_DAYS <- 365L
CARRYOVER_DAYS <- 30L
build_pass_cohort <- function(rx, enroll, dx) {
setDT(rx); setDT(enroll); setDT(dx)
setorder(rx, person_id, fill_date)
study <- rx[drug_class %chin% c("STUDY", "COMPARATOR")]
# Time zero = first study/comparator fill; arm = drug dispensed that day.
idx <- study[, .(index_date = fill_date[1L], arm = drug_class[1L]), by = person_id]
# New-user washout.
s <- merge(study, idx[, .(person_id, index_date)], by = "person_id")
prior <- unique(s[fill_date < index_date & fill_date >= index_date - WASHOUT_DAYS, person_id])
idx <- idx[!person_id %chin% prior]
# FFS-observable continuous enrollment across baseline through index (no MA-only spans).
e <- merge(enroll, idx[, .(person_id, index_date)], by = "person_id")
ok <- e[enroll_start <= index_date - WASHOUT_DAYS & enroll_end >= index_date & !ma_only,
unique(person_id)]
idx <- idx[person_id %chin% ok]
# First-event: drop prevalent AESI in the baseline window.
bd <- merge(dx[aesi == TRUE], idx[, .(person_id, index_date)], by = "person_id")
prevalent <- unique(bd[dx_date < index_date & dx_date >= index_date - WASHOUT_DAYS, person_id])
idx <- idx[!person_id %chin% prevalent]
# Risk window end = max(fill_date + days_supply) over on-treatment fills + carry-over.
ot <- merge(study, idx[, .(person_id, index_date)], by = "person_id")[fill_date >= index_date]
ot[, covered_end := fill_date + days_supply]
rxend <- ot[, .(risk_end = max(covered_end) + CARRYOVER_DAYS), by = person_id]
idx <- merge(idx, rxend, by = "person_id")
# Censor at min(risk_end, disenrollment); first incident AESI in window = event.
dis <- enroll[, .(disenroll = max(enroll_end)), by = person_id]
idx <- merge(idx, dis, by = "person_id")
idx[, fu_end := pmin(risk_end, disenroll)]
ev <- merge(dx[aesi == TRUE], idx[, .(person_id, index_date, fu_end)], by = "person_id")
ev <- ev[dx_date >= index_date & dx_date <= fu_end, .(event_date = min(dx_date)), by = person_id]
idx <- merge(idx, ev, by = "person_id", all.x = TRUE)
idx[, event := as.integer(!is.na(event_date))]
idx[, exit_date := fifelse(is.na(event_date), fu_end, event_date)]
idx[, person_days := pmax(as.integer(exit_date - index_date), 0L)]
idx[, .(events = sum(event), person_years = sum(person_days) / 365.25), by = arm
][, ir_per_1000py := 1000 * events / person_years][]
}Non-interventional voluntary-PASS cohort construction, person-time accrual, and a Fine-Gray comparative hazard (AESI with death as a competing risk) in SAS. Required input datasets (post data-management): work.rx : person_id, fill_date, drug_class ('STUDY'/'COMPARATOR'), days_supply work.enroll : person_id,...
%let washout = 365;
%let carryover = 30;
/* Time zero = earliest study/comparator fill; arm = drug dispensed that day. */
proc sort data=work.rx(where=(drug_class in ('STUDY','COMPARATOR'))) out=rx_q;
by person_id fill_date;
run;
data idx;
set rx_q;
by person_id;
if first.person_id;
index_date = fill_date;
format index_date date9.;
length arm $12;
arm = drug_class;
keep person_id index_date arm;
run;
/* New-user washout: no study/comparator fill in the washout window before index. */
proc sql;
create table newuser as
select i.* from idx i
where not exists (
select 1 from work.rx p
where p.person_id = i.person_id and p.drug_class in ('STUDY','COMPARATOR')
and p.fill_date < i.index_date and p.fill_date >= i.index_date - &washout);
quit;
/* FFS-observable continuous enrollment across baseline through index (no MA-only spans). */
proc sql;
create table enrolled as
select n.* from newuser n
where exists (
select 1 from work.enroll e
where e.person_id = n.person_id and e.ma_only = 0
and e.enroll_start <= n.index_date - &washout and e.enroll_end >= n.index_date);
quit;
/* First-event definition: exclude prevalent AESI in the baseline window. */
proc sql;
create table incident as
select e.* from enrolled e
where not exists (
select 1 from work.dx d
where d.person_id = e.person_id and d.aesi = 1
and d.dx_date < e.index_date and d.dx_date >= e.index_date - &washout);
quit;
/* Risk-window end = max(fill_date + days_supply) on-treatment + carry-over; disenrollment = max enroll_end. */
proc sql;
create table windows as
select c.person_id, c.arm, c.index_date,
(select max(r.fill_date + r.days_supply) from work.rx r
where r.person_id = c.person_id and r.fill_date >= c.index_date
and r.drug_class in ('STUDY','COMPARATOR')) + &carryover as risk_end format=date9.,
(select max(e.enroll_end) from work.enroll e
where e.person_id = c.person_id) as disenroll format=date9.
from incident c;
quit;
/* Outcome status (AESI=1, competing death=2, censored=0) and person-time to first event or censoring. */
proc sql;
create table survdata as
select w.person_id, w.arm,
min(w.risk_end, w.disenroll) as fu_end format=date9.,
(select min(d.dx_date) from work.dx d
where d.person_id = w.person_id and d.aesi = 1
and d.dx_date >= w.index_date) as aesi_date format=date9.,
(select min(d.dx_date) from work.dx d
where d.person_id = w.person_id and d.death = 1
and d.dx_date >= w.index_date) as death_date format=date9.,
w.index_date
from windows w;
quit;
data survdata;
set survdata;
_exit = min(coalesce(aesi_date, .i), coalesce(death_date, .i), fu_end);
if .i = _exit then _exit = fu_end; /* no event -> censor at fu_end */
time = max(_exit - index_date, 0);
if aesi_date ne . and aesi_date <= fu_end and aesi_date = _exit then status = 1; /* AESI */
else if death_date ne . and death_date <= fu_end and death_date = _exit then status = 2; /* competing death */
else status = 0; /* censored */
run;
/* Fine-Gray subdistribution hazard for the AESI, death as competing risk. */
proc phreg data=survdata;
class arm (ref='COMPARATOR');
model time*status(0) = arm / eventcode=1 risklimits;
hazardratio arm;
run;Citations
- [1]Engel P, Almas MF, De Bruin ML, Starzyk K, Blackburn S, Dreyer NA. Lessons learned on the design and the conduct of Post-Authorization Safety Studies: review of 3 years of PRAC oversight. British Journal of Clinical Pharmacology. 2017;83(4):884-893.
- [2]Almas MF, Girardi A, Crisafulli S, et al. Identifying regulatory outcomes of Non-interventional Post-Authorisation Safety Studies (PASS) in the European repository of studies using publicly available information. Frontiers in Drug Safety and Regulation. 2025;5:1574430.