← Methods repository
concept

eSource, EDC, and Source Data Verification

The regulatory and operational discipline for defining electronic source data, capturing or transferring those data into electronic data capture systems, preserving audit trails and data originator metadata, and verifying critical data against source records using risk-based source data verification rather than blind 100 percent checking.

Data_Quality_Assessmentesourceedcelectronic-data-capturesource-data-verificationsdvrisk-based-monitoringaudit-traildata-integrity
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

eSource means the original study data are electronic, EDC is the study database that stores case report form data, and source data verification checks important EDC fields against the original source. The point is traceability: a reviewer should be able to see where a value came from, who or what created it, when it changed, and whether critical fields were checked. More checking is not always better; risk-based verification targets the data that can change safety, eligibility, endpoints, or the study conclusion.

eSource, electronic data capture (EDC), and source data verification (SDV)

describe the chain from original clinical investigation data to the analyzable trial or registry dataset. eSource is source data initially recorded in electronic form or transferred directly from an electronic source. EDC is the system that stores case report form data and study-specific fields. SDV is the monitoring activity that checks selected EDC data against the source record, such as an EHR note, lab result, device file, imaging report, ePRO entry, or the EDC itself when the eCRF is the source.

In RWE-adjacent primary research, this chain matters because data increasingly originate outside paper charts: EHR extracts, direct EHR-to-EDC transfer, central labs, imaging vendors, wearables, ePRO apps, registries, claims extracts, and home devices. Each source can be valid, but only if the protocol and data-management plan identify the authorized source data originator, the source location, the data element identifier, the audit trail, and the reconciliation path into the analysis dataset. A clean-looking EDC field is not evidence of quality unless its source and transformations are traceable.

Core conceptual distinction

eSource is about where the original data live and how they are captured. EDC is about where study data are stored and curated. SDV is about how selected values are checked against their source. These are often collapsed into one operational phrase, but they answer different questions. "The value is in EDC" does not tell you whether it came from an EHR interface, manual transcription, a device vendor, or the subject's direct entry. "The monitor verified it" does not tell you whether the right records were selected, whether the source itself had an audit trail, or whether the check targeted variables that matter to the estimand and safety.

The modern quality question is not "did we verify every field?" It is "did we preserve reliability, integrity, traceability, and fitness for purpose for the data elements that can change the study conclusion or participant safety?" FDA's eSource guidance emphasizes authorized source data originators, data element identifiers, audit trails, capture into the eCRF, investigator responsibilities, and computerized systems. FDA's electronic systems/records/signatures guidance frames the broader requirement that electronic records be trustworthy, reliable, and generally equivalent to paper records.

Pros, cons, and trade-offs

- vs paper source plus manual EDC transcription: eSource reduces transcription, enables near-real-time review, and preserves metadata. Cost: interfaces, system validation, access controls, audit trails, and vendor governance become part of the evidence package. Prefer eSource when data already exist electronically and the source system can preserve traceability. - vs EDC-as-source: Direct entry into an eCRF can be efficient when the eCRF is genuinely the first place the observation is recorded. Cost: the investigator must be able to corroborate or explain the value, and the eCRF audit trail becomes the source audit trail. Do not use EDC-as-source to hide missing clinical documentation. - vs 100 percent SDV: Risk-based SDV focuses monitoring on critical variables, high-risk sites, unexpected patterns, and safety/endpoint data. Cost: it requires prospective risk assessment and central monitoring analytics. Prefer risk-based SDV for large pragmatic or registry studies; reserve 100 percent SDV for small, high-risk, or highly manual settings where every field is critical. - vs secondary RWD extracts: Claims, EHR, and registry extracts often arrive as curated datasets rather than study EDC. The eSource discipline still applies: document provenance, extraction logic, data transformations, audit trail, refresh date, and reconciliation to source when challenged.

When to use

Use this concept whenever a study collects primary data in EDC, imports data from EHR or registry systems, uses ePRO/wearable/DHT feeds, supports an FDA-regulated clinical investigation, runs a pragmatic or decentralized trial, or builds an audit-ready registry intended for regulatory or HTA use. It is also relevant when an RWE study uses source abstraction or chart review to validate claims/EHR phenotypes: the abstraction form, source record, reviewer, timestamp, and discrepancy process must be traceable.

When NOT to use - and when it is actively misleading

Do not treat SDV as a substitute for data quality by design. Verifying an incorrect or ambiguous source record only proves the EDC copied the ambiguity. Do not claim eSource traceability if the upstream device, app, spreadsheet, or EHR extract lacks an audit trail or version history. Do not use 100 percent SDV of noncritical fields as theater while ignoring endpoint algorithms, consent status, eligibility, randomization, safety events, and key covariates. Do not call an EHR extract source-verified unless the extraction logic, source tables, transformation rules, and sampled record checks are documented. It is actively misleading to report "source verified" without stating which variables, what source, what sampling fraction, what discrepancy threshold, and what corrective action process were used.

Data-source operational depth

- EHR eSource: High value for labs, vitals, medications, diagnoses, encounters, and notes, especially in EHR-embedded trials. Failure modes are local build differences, flowsheet reuse, late-entered notes, copied-forward text, interface mapping errors, and source table changes. Preserve source system, table/field, extraction date, transformation code, and investigator review status. - EDC direct entry: Appropriate when the eCRF is the first capture point, such as a study-specific assessment performed only for the protocol. Failure modes are missing corroboration, user-role confusion, late corrections, and inadequate audit-trail review. The data originator and timestamp must be retained. - Vendor DHT/ePRO/lab feeds: Useful for high-frequency or central measurements, but the source may be outside the EDC. Failure modes include file reprocessing, algorithm updates, timezone changes, missing device metadata, and vendor-side corrections. Require data transfer specifications and retained raw/source files. - Claims/registry extracts: In pragmatic trials and RWE studies, source verification is usually not field-by-field chart comparison. It is provenance and extract verification: confirm the data supplier, extract criteria, code lists, refresh date, record counts, linkage, and sampled source-to-extract concordance for critical elements.

Worked example

A pragmatic oncology registry trial collects baseline ECOG performance status, randomization arm, grade >=3 adverse events, and progression date. ECOG is entered directly into EDC by the clinician during the visit and is therefore EDC-as-source. Randomization comes from the EHR trial module. Lab-based safety events come from an EHR interface. Progression date comes from radiology report abstraction. A risk-based SDV plan selects 100 percent verification for informed consent, eligibility, randomization, death, progression, and grade >=3 adverse events; 20 percent verification for key baseline covariates; and central monitoring for all sites. The monitor finds that one site has high EHR-to-EDC lab discrepancy rates because local units changed after an interface update. The fix is not to verify more manually forever; it is to correct the interface mapping, reprocess affected records, document the audit trail, and re-run discrepancy checks.

Worked example

Scenario

An oncology registry trial uses several electronic sources. The monitor checks whether critical EDC values match their authorized sources and whether discrepancies trigger corrective action.

Dataset

Simplified source-to-EDC verification sample.

subject_iddata_elementsource_systemsource_valueedc_valuecriticaldiscrepancy
S001randomization_armEHR trial moduleArm AArm ATrue
S002ECOGEDC direct entry11True
S003grade3_neutropeniaEHR lab interfaceTrueTrueTrue
S004smoking_statusEHR abstractionformerunknownTrue

Steps

  • Identify the authorized source for each data element before verification starts.

  • Verify all critical fields or use a pre-specified high sampling fraction for them.

  • Separate critical discrepancies from noncritical discrepancies because they carry different corrective actions.

  • Investigate clustered discrepancies by site, source system, interface, or calendar time.

  • Correct the root cause, not only the visible EDC value.

Result

S003 is a critical discrepancy that can affect safety analysis and must be queried and root-caused. S004 is still a data-quality issue, but it is lower priority because it is noncritical to the primary endpoint and safety rules.

Runnable example

python implementation

Risk-based SDV discrepancy profile from a sampled source-to-EDC comparison. Inputs: checks : subject_id, site_id, data_element, source_system, source_value, edc_value, critical (bool) Returns discrepancy rates by element/site and a critical-field query list.

import pandas as pd

def sdv_profile(checks):
    df = checks.copy()
    df["source_norm"] = df["source_value"].astype(str).str.strip().str.upper()
    df["edc_norm"] = df["edc_value"].astype(str).str.strip().str.upper()
    df["discrepancy"] = df["source_norm"] != df["edc_norm"]

    by_element = (df.groupby(["data_element", "critical"])
                    .agg(n_checked=("subject_id", "size"),
                         discrepancies=("discrepancy", "sum"))
                    .reset_index())
    by_element["discrepancy_rate"] = by_element["discrepancies"] / by_element["n_checked"]

    by_site = (df.groupby("site_id")
                 .agg(n_checked=("subject_id", "size"),
                      discrepancies=("discrepancy", "sum"),
                      critical_discrepancies=("discrepancy", lambda x: int((x & df.loc[x.index, "critical"]).sum())))
                 .reset_index())
    by_site["discrepancy_rate"] = by_site["discrepancies"] / by_site["n_checked"]

    queries = df[df["discrepancy"] & df["critical"]].copy()
    return {"by_element": by_element, "by_site": by_site, "critical_queries": queries}
r implementation

R/data.table SDV discrepancy profile. Inputs: checks : subject_id, site_id, data_element, source_system, source_value, edc_value, critical

library(data.table)

sdv_profile <- function(checks) {
  setDT(checks)
  checks[, source_norm := toupper(trimws(as.character(source_value)))]
  checks[, edc_norm := toupper(trimws(as.character(edc_value)))]
  checks[, discrepancy := source_norm != edc_norm]

  by_element <- checks[, .(
    n_checked = .N,
    discrepancies = sum(discrepancy),
    discrepancy_rate = mean(discrepancy)
  ), by = .(data_element, critical)]

  by_site <- checks[, .(
    n_checked = .N,
    discrepancies = sum(discrepancy),
    critical_discrepancies = sum(discrepancy & critical),
    discrepancy_rate = mean(discrepancy)
  ), by = site_id]

  list(
    by_element = by_element,
    by_site = by_site,
    critical_queries = checks[discrepancy == TRUE & critical == TRUE]
  )
}