Healthcare Data Integration, Interoperability

COSD: The Architecture of Cancer Data in England

COSD Architecture

Every year, around 375,000 people in England receive a cancer diagnosis. Each of those diagnoses generates a cascade of clinical events — referrals, staging investigations, MDT decisions, treatments, follow-ups — all of which must be captured, standardised, and reported to the National Disease Registration Service. The mechanism through which all of this flows is COSD: the Cancer Outcomes and Services Dataset.

COSD is not simply a data collection form. It is a precisely-specified, schema-governed, coded XML standard that constitutes the backbone of cancer intelligence in England. It defines not just what is collected, but in which vocabulary (ICD-O-3, SNOMED CT, OPCS-4, TNM), at which point in the pathway, and in what hierarchical structure. It is, in a very real sense, the language in which cancer data speaks nationally.

For engineering teams building cancer data platforms, COSD is both a gift and a challenge. The schemas are rigorous and well-documented. The content is clinically rich. But the complexity is real: 13 site-specific record types, a modular XSD hierarchy spanning over 20 schema files, coded values drawn from multiple clinical ontologies, and a standard that evolves with each TRUD release.

What is COSD — and Who Owns It?

COSD is the national standard for cancer data collection in England, mandated by NHS England and operated by the National Disease Registration Service (NDRS). NDRS replaced the previous network of regional cancer registries and now acts as the single national collector and custodian of cancer data in England.

The standard defines:

  • What data providers must submit for cancer patients — diagnoses, staging, treatments, pathway milestones, outcomes
  • In what structure and codes — XML schemas, value sets, SNOMED CT, ICD-O-3, OPCS-4, TNM
  • At which points in the care pathway — referral, diagnosis, staging, treatment, follow-up

In practice, NHS Trusts and cancer services generate COSD XML submissions from their clinical systems and submit them to NDRS via secure channels. Downstream platforms ingest that XML, validate it against the schemas, transform it into an internal data model, and may further map it to standardised analytics models such as OMOP CDM.

The current production version is COSD v10.2.0, distributed via NHS TRUD.

Getting COSD Schemas from NHS TRUD

COSD schemas are freely available — but only through TRUD (Technology Reference data Update Distribution), NHS England’s official distribution platform for reference data and technical standards. TRUD distributes coding schemes, messaging specifications, and XML schemas including COSD.

Access requires a free account and acceptance of per-product licence terms.

Step-by-step

1. Register at isd.digital.nhs.uk/trud3/ Create an account using your organisational email. NHS or organisational domain email is strongly recommended over personal addresses to simplify licence compliance paperwork downstream.

2. Search and subscribe to the COSD product Once logged in, search for “Cancer Outcomes and Services Dataset”. Locate the core COSD product and review the NHS data standards licence terms before subscribing. Subscription is free.

3. Download the release zip From the product’s Releases page, select the version matching your target (e.g. v10.2.0). The zip contains: all XSDs, sample XML submissions, and Excel/PDF field-level documentation — the latter being essential reference material for your implementation team, as it details permitted value sets, mandatory/optional flags, and clinical definitions for every element.

4. Version-control and align Extract schemas into a versioned path in your repository (e.g. documents/nhs_schemas/cosd/xml/). When upgrading versions, run a structured diff against your mapper script and XSD hierarchy document, then execute regression tests using the official TRUD sample XML before promoting to production.

Critical: Your XSD validation pipeline, mapper script, internal data model, and the XML submissions coming from Trusts must all reference the same COSD version. A mismatch — even a minor version difference — can result in silent data loss when new fields are unrecognised or deprecated fields continue to be parsed.

The 13 Cancer Record Types

COSD organises cancer data by tumour site group. Each record type corresponds to a distinct XSD, a set of site-specific data extensions, and different business rules for validation, staging, and treatment details.

From an implementation perspective, the valid record types are:

def validRecordTypes = [
    'BreastRecord', 'CNSRecord', 'ColorectalRecord', 'CTYARecord',
    'GynaecologicalRecord', 'HaematologicalRecord', 'LiverRecord', 'LungRecord',
    'OtherRecord', 'SarcomaRecord', 'SkinRecord', 'UpperGIRecord', 'UrologicalRecord'
] as Set

BreastRecord

Breast cancers. Includes breast-specific risk factors, hormone receptor status (ER, PR, HER2), BRCA/germline variant status, and surgical detail (mastectomy vs. breast-conserving surgery). High submission volume. Schema: COSD-v10-2-0_BREAST.xsd.

CNSRecord

Central nervous system tumours. Adds CNS-specific staging (e.g. Chang staging for medulloblastoma), WHO CNS grade, and neurological performance status fields not present in core COSD. Schema: COSD-v10-2-0_CNS.xsd.

ColorectalRecord

Colorectal cancers. Site-specific fields for peritoneal involvement, extramural vascular invasion (EMVI), Dukes staging, and circumferential resection margin (CRM) status. High submission volume. Schema: COSD-v10-2-0_COLORECTAL.xsd.

CTYARecord

Children, Teenagers, and Young Adults. Adds paediatric/young-adult specific fields including CCLG tumour classification, principal treatment centre designation, clinical trial participation, and parental consent status. Schema: COSD-v10-2-0_CTYA.xsd.

GynaecologicalRecord

Ovarian, cervical, uterine, and vulval cancers. FIGO staging, HPV status, peritoneal involvement, and cytoreductive surgery detail. Schema: COSD-v10-2-0_GYNAECOLOGICAL.xsd.

HaematologicalRecord

Leukaemias, lymphomas, and myeloma. Disease-specific staging systems (Ann Arbor, Durie-Salmon, ISS), cytogenetic risk group, bone marrow trephine status, and transplant eligibility. Schema: COSD-v10-2-0_HAEMATOLOGICAL.xsd.

LiverRecord

Liver cancers including HCC and cholangiocarcinoma. Cirrhosis type and cause, surveillance scan history, Barcelona Clinic Liver Cancer (BCLC) stage, cholangiocarcinoma anatomical category, and biliary risk factors. Schema: COSD-v10-2-0_LIVER.xsd.

// Site-specific liver fields — LiverRecord only
liverSurveillanceScans        : [email protected](),
liverCirrhosisType            : [email protected](),
causeOfLiverCirrhosis         : [email protected](),
cholangiocarcinomaCategory    : [email protected](),
cholangiocarcinomaRiskFactorsType : diag.Cholangiocarcinoma.CholangiocarcinomaRiskFactorsType.@code.text(),

LungRecord

Lung cancers. Lung health check indicator, bronchoscopy findings, mediastinal sampling status, EGFR/ALK mutation status, performance status, and surgical fitness assessment. Schema: COSD-v10-2-0_LUNG.xsd.

OtherRecord

Cancers not covered by a dedicated site schema — a generic pathway using core COSD modules without site-specific extensions. Provides data coverage for rare tumour types. No site-specific XSD extension.

SarcomaRecord

Soft tissue and bone sarcomas. Rare tumour-specific staging, specialist sarcoma centre designation, surgical margin status (R0/R1/R2), and limb salvage vs. amputation detail. Schema: COSD-v10-2-0_SARCOMA.xsd.

SkinRecord

Melanoma and non-melanoma skin cancers. For melanoma: Breslow thickness, Clark level, ulceration status, and sentinel lymph node biopsy result. For non-melanoma: excision margin status and reconstruction approach. Schema: COSD-v10-2-0_SKIN.xsd.

UpperGIRecord

Oesophageal, gastric, and pancreatic cancers. Barrett’s surveillance history, Siewert classification for junctional tumours, neoadjuvant therapy response grading, and resection type (Ivor Lewis, total gastrectomy, Whipple’s). Schema: COSD-v10-2-0_UPPERGI.xsd.

UrologicalRecord

Prostate, bladder, kidney, and testicular cancers. PSA values, Gleason/ISUP grade group, NMIBC vs. MIBC bladder classification, nephrectomy type, and serum tumour markers (AFP, beta-HCG, LDH) for testicular. Schema: COSD-v10-2-0_UROLOGICAL.xsd.

The XSD Schema Hierarchy

COSD’s schema is intentionally modular. The root XSD (COSD-v10-2-0.xsd) imports a constellation of domain-specific and utility schemas. Understanding this hierarchy is essential for both validation pipeline construction and for knowing which XSD to consult when debugging a field-level issue.

COSD-v10-2-0.xsd                          ← root, validation entry point
├── COSD-v10-2-0_DEMOGRAPHICS.xsd
├── COSD-v10-2-0_PATIENTIDENTITYDETAILS.xsd
├── COSD-v10-2-0_PRIMARYPATHWAY.xsd
├── COSD-v10-2-0_NONPRIMARYPATHWAY.xsd
├── COSD-v10-2-0_DIAGNOSTICPROCEDURES.xsd
├── COSD-v10-2-0_IMAGING.xsd
├── COSD-v10-2-0_TREATMENT.xsd
├── COSD-v10-2-0_LABORATORYRESULTS.xsd
├── COSD-v10-2-0_MULTIDISCIPLINARYTEAMMEETINGS.xsd
├── COSD-v10-2-0_HOLISTICNEEDSASSESSMENT...xsd
├── Site-specific extensions:
│   ├── COSD-v10-2-0_BREAST.xsd
│   ├── COSD-v10-2-0_LUNG.xsd
│   ├── COSD-v10-2-0_CNS.xsd
│   ├── COSD-v10-2-0_LIVER.xsd
│   ├── COSD-v10-2-0_HAEMATOLOGICAL.xsd
│   ├── COSD-v10-2-0_GYNAECOLOGICAL.xsd
│   ├── COSD-v10-2-0_RENALTUMOURS.xsd
│   └── ... (all 13 site groups)
└── COSD-v10-2-0_DATA_TYPES.xsd           ← shared type definitions, load first

The dependency ordering matters for schema validators. Load DATA_TYPES.xsd first, then the domain module schemas, then site-specific extensions, and finally the root. A COSD_XSD_HIERARCHY.md in your schema directory should document this load order explicitly and be updated on every version upgrade.

The Ingestion Pipeline

A typical COSD ingestion architecture moves through four stages:

Stage 1 — Trust XML Generation. NHS Trusts generate COSD XML from their clinical systems (PAS, cancer management systems). The root element is the record type: <BreastRecord>, <LungRecord>, etc.

Stage 2 — Schema Validation. Incoming XML is validated against the COSD XSD hierarchy. A production-grade implementation surfaces field-level error messages back to the submitting provider — not just a binary pass/fail. Invalid records are quarantined, not silently dropped.

Stage 3 — NiFi Transformation. Apache NiFi flows execute a Groovy mapper script to convert validated COSD XML into a flat JSON/DTO representation. This is where XML GPath extraction, coded value normalisation, and nested array handling (treatments, imaging episodes, MDT meetings) all occur.

Stage 4 — ETL to Data Vault and OMOP. A .NET ETL engine persists the transformed data to a Data Vault model (raw vault → business vault), and optionally maps to OMOP CDM for standardised analytics.

The mapper script is not just a transform — it is your organisation’s canonical interpretation of what COSD means in your domain. Every field extraction choice, every null-handling decision, every code path is an implicit design decision about your data model.

Field-Level Mapping: Inside mapper.groovy

The NiFi Groovy mapper is the connective tissue between NHS standards and your internal model. The following sections cover the most architecturally significant field groups.

Envelope and Record Identity

recordType      : xml.name().toString(),
recordId        : [email protected](),
uploadBatchId   : flowFile.getAttribute('uploadbatch.id'),
organisationId  : flowFile.getAttribute('uploadbatch.organisationId'),

xml.name() retrieves the XML root element name, used to route records to site-specific processing logic. The organisationId from NiFi FlowFile attributes enables multi-tenancy — the same pipeline can ingest COSD from multiple Trusts with full data isolation.

Patient Identity

nhsNumber                            : [email protected](),
localPatientIdentifier               : xml.PatientIdentityDetails.LocalPatientIdentifier.text(),
nhsNumberStatusIndicatorCode         : xml.PatientIdentityDetails.NhsNumberStatusIndicatorCode.@code.text(),
personBirthDate                      : xml.PatientIdentityDetails.PersonBirthDate.text(),
organisationIdentifierCodeOfProvider : xml.PatientIdentityDetails.OrganisationIdentifierCodeOfProvider.@extension.text(),

Note the distinction between [email protected]() for HL7 identifier attributes and .text() for plain text elements. Confusing these is a common source of silent empty fields in implementations.

Demographics

ethnicCategory                         : [email protected](),
personStatedGenderCode                 : [email protected](),
personSexualOrientationCodeAtDiagnosis : xml.Demographics.PersonSexualOrientationCodeAtDiagnosis.@code.text(),
postcodeOfUsualAddressAtDiagnosis      : xml.Demographics.PostcodeOfUsualAddressAtDiagnosis.text(),
streetAddressLine                      : (xml.Demographics.Address.StructuredAddress.StreetAddressLine.text()
                                          ?: xml.Demographics.Address.UnstructuredAddress.StreetAddressLine.text()),

The address fallback pattern (Elvis operator ?:) handles the real-world variability in Trust XML — some submit StructuredAddress, others UnstructuredAddress. Ethnic category uses ONS ethnic group codes; gender and sexual orientation use NHS-specific coded value sets from the COSD documentation.

Diagnosis and Staging

primaryDiagnosisIcd                  : [email protected](),
morphologyIcdO3                      : diag.'MorphologyIcd-o-3'[email protected](),
topographyIcdO3                      : diag.'TopographyIcd-o-3'[email protected](),
diagnosisCodeSnomedCt                : [email protected](),
gradeOfDifferentiationAtDiagnosis    : [email protected](),
performanceStatusAdult               : [email protected](),
ki67                                 : [email protected](),
basisOfDiagnosisCancer               : [email protected](),
familialCancerSyndrome               : [email protected](),

ICD-O-3 provides both morphology (histological type, e.g. 8500/3 for invasive ductal carcinoma) and topography (primary site, C-codes). SNOMED CT codes provide an additional clinical diagnostic layer. Ki-67 is a proliferation index used in breast and other cancers — note it uses @value not @code.

TNM staging captures both final pre-treatment and integrated stage:

tCategoryFinalPretreatment        : stag.TCategoryFinalPretreatment.text(),
nCategoryFinalPretreatment        : stag.NCategoryFinalPretreatment.text(),
mCategoryFinalPretreatment        : stag.MCategoryFinalPretreatment.text(),
tnmStageGroupingFinalPretreatment : stag.TnmStageGroupingFinalPretreatment.text(),
tCategoryIntegratedStage          : stag.TCategoryIntegratedStage.text(),
nCategoryIntegratedStage          : stag.NCategoryIntegratedStage.text(),
mCategoryIntegratedStage          : stag.MCategoryIntegratedStage.text(),
tnmStageGroupingIntegrated        : stag.TnmStageGroupingIntegrated.text(),
tnmCodingEdition                  : [email protected](),

Always capture tnmCodingEdition — whether the 7th or 8th edition of TNM was used materially affects what each T/N/M category means clinically, and mixing editions in aggregate analysis is a known data quality pitfall.

Treatments — Nested Arrays

The treatment block is the most structurally complex section in COSD mapping:

treatments: xml.Treatment.collect { t -> [
    cancerTreatmentIntent        : [email protected](),
    treatmentStartDate           : t.TreatmentStartDateCancer.text(),
    modalityRegistration         : [email protected](),
    organisationSiteIdentifier   : t.OrganisationSiteIdentifierOfProviderCancerTreatmentStartDate.@extension.text(),
    endOfTreatmentSummaryDate    : t.EndOfTreatmentSummaryDate.text(),

    // Surgery sub-block
    surgeryProcedureDate         : t.Surgery.ProcedureDate.text(),
    primaryProcedureOpcs         : [email protected](),
    primaryProcedureSnomedCt     : [email protected](),
    asaScore                     : [email protected](),
    surgicalAccessType           : [email protected](),
    unplannedReturnToTheatre     : [email protected](),

    // Consultant surgeons — further nested array
    consultantSurgeons: t.Surgery.ConsultantSurgeon.collect { cs -> [
        issuerCode      : cs.'ProfessionalRegistrationIssuerCode-ConsultantSurgeon'[email protected](),
        entryIdentifier : cs.'ProfessionalRegistrationEntryIdentifier-ConsultantSurgeon'.text()
    ]}
]},

A patient record may have multiple treatment episodes; each surgical treatment may have multiple consultant surgeons. Groovy’s .collect{} idiom handles both levels cleanly. A key advantage: an empty xml.Treatment node produces an empty list, not null — which simplifies downstream null-handling in ETL.

OPCS-4 procedure codes are the primary surgical classification. SNOMED CT procedure codes are optionally present and should be captured where available for OMOP mapping, since OPCS-4 has limited vocabulary coverage in standard OMOP releases.

Risk Factors

tobaccoSmokingStatus              : xml.ClinicalNurseSpecialistAndRiskFactorAssessment.TobaccoSmokingStatus.@code.text(),
tobaccoSmokingCessation           : xml.ClinicalNurseSpecialistAndRiskFactorAssessment.TobaccoSmokingCessation.@code.text(),
historyOfAlcoholCurrent           : xml.ClinicalNurseSpecialistAndRiskFactorAssessment.HistoryOfAlcoholCurrent.@code.text(),
diabetesMellitusType1AndType2Indicator : xml.ClinicalNurseSpecialistAndRiskFactorAssessment.DiabetesMellitusType1AndType2Indicator.@code.text(),
menopausalStatus                  : xml.ClinicalNurseSpecialistAndRiskFactorAssessment.MenopausalStatus.@code.text(),
physicalActivityCurrent           : xml.ClinicalNurseSpecialistAndRiskFactorAssessment.PhysicalActivityCurrent.@code.text(),

These fields support lifestyle risk factor analysis, stratification of outcomes by modifiable factors, and resource planning for CNS input. Completeness on these fields is often lower than for diagnostic fields — important to track in data quality dashboards.

From COSD to OMOP CDM

OMOP CDM (Observational Medical Outcomes Partnership Common Data Model) is the target analytics standard for federated research networks and many NHS analytics platforms. Converting COSD to OMOP is non-trivial: COSD is pathway-centric and England-specific; OMOP is person-centric and designed for international interoperability.

The core conceptual mappings are:

COSD FieldOMOP TableNotes
primaryDiagnosisIcd (ICD-10)CONDITION_OCCURRENCEStandard ICD-10 mapping via OMOP vocabulary
morphologyIcdO3CONDITION_OCCURRENCEHistology; ICD-O-3 to SNOMED mapping required
treatments[].primaryProcedureOpcsPROCEDURE_OCCURRENCEOPCS-4 has limited standard OMOP coverage
treatments[].primaryProcedureSnomedCtPROCEDURE_OCCURRENCEDirect SNOMED mapping preferred where available
tnmStageGroupingFinalPretreatmentOBSERVATIONNo standard OMOP table for staging
performanceStatusAdult (ECOG)OBSERVATIONECOG maps to LOINC in OMOP vocabularies
laboratoryResults[].ldhMEASUREMENTLab results map cleanly to MEASUREMENT
personBirthDatePERSON.birth_datetimeDirect
ethnicCategory (ONS codes)PERSON.ethnicity_concept_idONS → OMOP concept mapping required

The most common implementation challenge is OPCS-4 concept resolution. OPCS-4 is not well-covered in standard OMOP vocabulary releases, which means custom concept ranges (2,000,000,000+) and local concept mappings are typically required. Capturing both primaryProcedureOpcs and primaryProcedureSnomedCt wherever possible mitigates this, since SNOMED CT maps cleanly to standard OMOP concepts.

Information Governance

COSD carries the most sensitive category of personal health data — identifiable, detailed cancer diagnoses, treatments, and outcomes. The IG framework is correspondingly rigorous.

Data classification. COSD data is Special Category Personal Data under UK GDPR (Article 9 health data). Processing requires an Article 9(2) condition — typically (h) for healthcare provision or (j) for research/public health. NHS Number combined with date of birth and postcode creates significant re-identification risk even without a name.

Technical controls. Minimum requirements for a production COSD platform: TLS 1.3 in transit across all NiFi pipelines; AES-256 encryption at rest in the data vault; role-based access control with least-privilege principles; column-level security on NHS Number and date of birth; and full audit logging on all access to identifiable data.

Regulatory framework. The overlapping requirements include: UK GDPR / Data Protection Act 2018; NHS Data Security and Protection Toolkit; DCB0129/DCB0160 clinical safety; Data Sharing Agreements with provider Trusts; TRUD per-product licence terms; and Confidentiality Advisory Group (CAG) approval where applicable for research uses.

Key Implementation Considerations

Version governance. Track which COSD version each environment (dev, test, prod) supports. Subscribe to TRUD release notifications and plan schema upgrade projects proactively rather than reactively. A structured version upgrade runbook — diff, mapper review, regression test, staged rollout — should be a standing procedure.

Validation feedback loop. Surfacing clear, field-level validation errors back to submitting Trusts is as important as the validation itself. A Trust that receives opaque failure messages will resubmit identical broken XML. Actionable error messages reduce resubmission cycles and improve data quality at source.

Completeness monitoring. COSD defines mandatory, required-if, and optional fields. Build completeness dashboards tracking: percentage of records with valid staging data, percentage with full treatment detail, completeness of demographic fields, and gap rates on key prognostic indicators (performance status, Ki-67, TNM edition). These dashboards serve both data quality management and clinical audit purposes.

Mapping as a single source of truth. The mapper script should be the single authoritative document for how your organisation interprets COSD. Any schema version upgrade must trigger a formal mapper review, not just a validation pipeline update. Field semantics can change between versions even when element names stay the same.

Summary

COSD is the definitional standard for cancer intelligence in England — not just a data format but a nationally mandated clinical ontology governing how cancer events are recorded, coded, and reported. Getting the implementation right matters beyond the technical: the accuracy of England’s national cancer register, the reliability of pathway performance metrics, and the validity of research using this data all depend on engineering decisions made in the ingestion pipeline.

The schemas are freely available from NHS TRUD. The record types are well-defined and clinically meaningful. The mapping from XML to a usable data model is tractable, if detailed. And the path from COSD to OMOP CDM, while requiring careful vocabulary work, is well-understood.

Every field you handle correctly is a contribution to the accuracy of cancer data in England.