← Methods repository
concept

EHR-Embedded Pragmatic Trial with Point-of-Care Randomization

A pragmatic randomized trial in which eligibility screening, random treatment assignment, intervention delivery, and outcome ascertainment are integrated into the electronic health record or care workflow at the clinical encounter where a real treatment decision is being made.

Study_Designehr-embedded-trialembedded-pragmatic-trialpoint-of-care-randomizationlearning-health-systempragmatic-trialrandomized-trialclinical-decision-supportelectronic-health-record
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

This is a randomized trial that happens inside normal care. The electronic health record finds an eligible patient at a real decision point, flips the treatment assignment, records that assignment as time zero, and then follows outcomes using routine records. It keeps the main strength of a trial - random assignment - while reducing the extra clinic visits, forms, and narrow eligibility of a conventional trial.

An EHR-embedded pragmatic trial with point-of-care randomization is a randomized experiment built into routine clinical care. The EHR identifies an eligible patient at a decision point, presents trial information or a clinical workflow, records consent or waiver-compatible enrollment status, randomizes at the point of care, stamps the randomization timestamp as time zero, and then uses EHR, claims, registry, patient-reported, or device data to ascertain outcomes. The trial is pragmatic because it studies usual-care populations, real clinicians, routine workflows, and outcomes that matter in practice. It is still a trial because treatment assignment is randomized.

The defining operational feature is the EHR-randomization join. Eligibility is not a research coordinator's spreadsheet that later becomes an EHR note. The care system itself triggers the trial: an order composer, best-practice alert, registry tab, clinical decision support module, portal workflow, or embedded randomization service fires when a patient meets criteria and a decision is due. The assignment is logged before the treatment strategy is chosen, and the assigned arm is visible to the clinician or workflow as needed. This is the design pattern behind many embedded pragmatic clinical trials and patient-centered network trials such as ADAPTABLE, where patient-centered recruitment and EHR/claims follow-up enabled a large comparative-effectiveness question at low marginal cost.

Core conceptual distinction

This design sits between three close neighbors. It is a pragmatic trial because it preserves routine-care delivery and broad eligibility. It is an EHR-based study because the EHR supplies eligibility, workflow, covariates, and often outcomes. It is not a target-trial emulation because assignment is actually randomized rather than inferred from observed choices. It is not merely a cluster-randomized CDS rollout unless the randomization unit is a clinic or provider; here the usual unit is the patient encounter, patient, clinician, or order event at the point of care.

The estimand is usually an intention-to-treat effect of assignment to a treatment or care strategy under usual care. Time zero is the randomization timestamp, not the first downstream order, fill, note, or claim. That timestamp discipline is the main safeguard against immortal time and post-assignment selection. Secondary per-protocol or as-treated analyses can be useful, but they must handle non-adherence, treatment switching, discontinuation, and out-of-network follow-up using the same censoring and weighting methods used in pragmatic and observational RWE.

Pros, cons, and trade-offs

- vs conventional explanatory RCT: EHR-embedded trials reduce recruitment and follow-up burden, can enroll broader routine-care populations, and preserve the protection of randomization. Cost: blinding is often difficult, outcome ascertainment is limited by routine data, workflow friction can reduce enrollment, and data quality depends on health-system capture. - vs observational target-trial emulation: Randomization eliminates confounding by indication at assignment. Cost: the study must be prospective, needs governance, consent/waiver decisions, clinician engagement, and an operational randomization service. Prefer EHR-embedded randomization when equipoise and workflow feasibility exist; use emulation when randomization is infeasible or unethical. - vs registry-based randomized trial: A registry trial uses a registry as the enrollment and outcome backbone. EHR-embedded randomization uses the care record and order workflow. EHR wins on real-time clinical workflow and local covariates; registries win on disease-specific curation and adjudicated outcomes. - vs cluster-randomized trial: Patient- or encounter-level point-of-care randomization is more statistically efficient and avoids cluster design effects. Cluster randomization is better for provider-, clinic-, or system-level interventions where individual randomization would contaminate care.

When to use

Use this design when a real clinical decision has equipoise, can be randomized without disrupting safe care, and can be triggered inside the EHR or patient portal. Good candidates are dose comparisons, approved-drug comparative effectiveness, lab-monitoring strategies, outreach workflows, order-set defaults, diagnostic testing strategies, and care-management interventions. The data substrate must capture eligibility before assignment, assignment itself, the delivered treatment strategy, important baseline covariates, outcomes, censoring, and safety follow-up.

When NOT to use - and when it is actively misleading

Do not use point-of-care randomization when the EHR cannot identify eligible patients before treatment selection or when the randomization trigger fires after clinicians have effectively chosen the arm. Do not randomize if equipoise is absent or if the intervention cannot be delivered safely in routine care. Do not rely on an EHR-only outcome when out-of-network events are common and differential by arm. Do not analyze by treatment received as the primary result without preserving the randomized assignment. It is actively misleading to call a study EHR-randomized if the EHR merely records an assignment made elsewhere after post-eligibility exclusions or clinician steering.

Data-source operational depth

- EHR: Supplies eligibility triggers, randomization workflow, orders, clinical covariates, and clinician-facing intervention delivery. Failure modes include alert fatigue, clinicians bypassing randomization, eligibility logic drift, local build differences across sites, and visit-driven outcome capture. Require versioned eligibility logic, randomization audit logs, and a reconciliation report from fired triggers to assignments. - Claims: Useful for fills, utilization, out-of-network hospitalizations, and enrollment/censoring. Failure modes include adjudication lag, benefit changes, and Medicare Advantage or other encounter-data incompleteness. Use a maturity buffer and restrict outcome person-time to observable coverage when claims are required. - Registry: Adds disease-specific severity and adjudicated outcomes when the EHR is too noisy. Failure modes are registry participation gaps and data-entry lag. Link registry outcomes to the EHR assignment table using a stable patient key and timestamp. - Linked EHR-claims-PGHD-device: Often the best substrate: EHR randomizes and captures severity, claims complete utilization and fills, and PGHD/device streams capture patient experience or function. Linkage selection and date reconciliation must be reported.

Worked example

Question: among adults with established ASCVD and an active aspirin prescription, does an EHR-embedded point-of-care strategy assigning 81 mg vs 325 mg aspirin affect 12-month major cardiovascular events and bleeding? (1) Eligibility trigger: at a primary-care or cardiology encounter, the EHR checks ASCVD diagnosis, active aspirin use, no recent major bleed, no contraindication, and no competing trial enrollment. (2) Randomization: before the clinician edits the aspirin order, the EHR calls the trial randomization service stratified by site and prior MI; the returned arm and timestamp are written to an immutable assignment table. (3) Time zero: the assignment timestamp, not the subsequent order date or pharmacy fill date. (4) Delivery: the clinician receives an order-set default for assigned dose but can override; overrides remain in the ITT analysis. (5) Outcome ascertainment: EHR captures local events and labs, claims capture out-of-network hospitalizations and fills, and a mortality source captures death. (6) Analysis: ITT by assigned dose, with secondary as-treated analysis using pharmacy fills; censor at disenrollment, death for nonfatal outcomes, or data end after claims maturity. (7) Diagnostics: report trigger-to-randomization conversion, clinician overrides, crossovers, site balance, missing outcome capture, and linkability to claims.

Worked example

Scenario

An EHR-embedded aspirin-dose trial randomizes eligible ASCVD patients to an 81 mg or 325 mg dose at a routine cardiology visit. The table shows the assignment log that becomes the analysis spine.

Dataset

Simplified EHR point-of-care randomization assignment log.

person_idsite_idtrigger_timerandomized_timestratumassigned_armclinician_override
P001SITE_A2025-01-08 09:122025-01-08 09:13prior_mi_yesaspirin_81mg
P002SITE_A2025-01-08 10:452025-01-08 10:46prior_mi_noaspirin_325mgTrue
P003SITE_B2025-01-09 08:20prior_mi_yes

Steps

  • Treat randomized_time as time zero for P001 and P002.

  • Keep P002 in the assigned 325 mg arm for the primary ITT analysis even though the clinician overrode the order.

  • Keep P003 in the trigger funnel but out of the randomized analysis because no assignment occurred.

  • Link the assignment table to EHR/claims outcomes using person_id and follow from randomized_time.

Result

The assignment log creates the trial cohort, time zero, arm, and workflow diagnostics. It also distinguishes randomized participants from eligible triggers that never became trial assignments.

Runnable example

python implementation

Build a stratified point-of-care randomization assignment log and ITT analysis spine. Inputs: triggers : trigger_id, person_id, site_id, trigger_time, eligible, stratum In production, the randomization service should be transactional and auditable. This...

import numpy as np
import pandas as pd

ARMS = ["strategy_a", "strategy_b"]

def assign_within_strata(triggers, block_size=4, seed=20260706):
    rng = np.random.default_rng(seed)
    eligible = triggers[triggers["eligible"]].sort_values(["site_id", "stratum", "trigger_time"]).copy()
    assignments = []

    for (site, stratum), g in eligible.groupby(["site_id", "stratum"], sort=False):
        n = len(g)
        block = np.repeat(ARMS, block_size // len(ARMS))
        arm_pool = []
        while len(arm_pool) < n:
            arm_pool.extend(rng.permutation(block).tolist())
        x = g.copy()
        x["assigned_arm"] = arm_pool[:n]
        x["randomized_time"] = x["trigger_time"]
        x["randomization_stratum"] = f"{site}|{stratum}"
        assignments.append(x)

    return pd.concat(assignments, ignore_index=True)

def make_itt_spine(triggers, outcomes):
    assigned = assign_within_strata(triggers)
    spine = assigned[["person_id", "site_id", "randomized_time", "assigned_arm", "randomization_stratum"]]
    spine = spine.rename(columns={"randomized_time": "index_time"})
    return spine.merge(outcomes, on="person_id", how="left")

def workflow_diagnostics(triggers, assignments):
    return {
        "eligible_triggers": int(triggers["eligible"].sum()),
        "randomized": int(assignments["person_id"].nunique()),
        "conversion": float(assignments["person_id"].nunique() / max(triggers["eligible"].sum(), 1)),
        "arm_counts": assignments["assigned_arm"].value_counts().to_dict(),
    }
r implementation

R/data.table version of a stratified point-of-care randomization assignment log plus ITT spine construction. Inputs: triggers : trigger_id, person_id, site_id, trigger_time, eligible, stratum outcomes : person_id plus endpoint variables

library(data.table)

assign_within_strata <- function(triggers, block_size = 4L, seed = 20260706L) {
  set.seed(seed)
  setDT(triggers)
  arms <- c("strategy_a", "strategy_b")
  block <- rep(arms, each = block_size / length(arms))

  eligible <- triggers[eligible == TRUE][order(site_id, stratum, trigger_time)]
  assigned <- eligible[, {
    pool <- character()
    while (length(pool) < .N) pool <- c(pool, sample(block))
    .SD[, `:=`(
      assigned_arm = pool[seq_len(.N)],
      randomized_time = trigger_time,
      randomization_stratum = paste(site_id, stratum, sep = "|")
    )]
  }, by = .(site_id, stratum)]
  assigned[]
}

make_itt_spine <- function(triggers, outcomes) {
  assigned <- assign_within_strata(triggers)
  spine <- assigned[, .(person_id, site_id, index_time = randomized_time,
                        assigned_arm, randomization_stratum)]
  merge(spine, outcomes, by = "person_id", all.x = TRUE)
}