UK childhood immunisation

greenbook

Turning the Green Book from a PDF into a computable, versioned source of truth - and an engine that can actually read it.

Where we are

Today, the schedule is a document

The Green Book is a PDF

The UK childhood immunisation schedule - Green Book Chapter 11 - is published as human-readable PDFs on GOV.UK. As of 2026 there is no computable version. The PDF is the source of truth.

So every digital system that needs the schedule re-implements it by hand from the PDF - a lossy, error-prone derivative. We call this "digital paper":

Word document

Authored by experts, but only as prose.

PDF on GOV.UK

The published, authoritative artefact.

Hand-written code

Each vendor reverse-engineers the rules. Diverges, drifts, breaks.

"Is this child fully vaccinated?"

A deceptively hard question. To answer it you have to know three separate things:

1

Which schedule applied when they were born - and what was in scope by the time each dose was due.

2

What they actually received - the recorded doses, from possibly several sources.

3

Whether what they received satisfies the schedule that applied to them.

And "fully vaccinated" turns out not to mean one thing - we will come back to that.

The schedule is a moving target

A child born in 1998 has a genuinely different "complete" schedule than one born in 2010 or 2020. The schedule is not one document but a series of dated snapshots.

1992 · Hib introduced

1999 · MenC introduced

2006 · PCV introduced

2013 · Rotavirus introduced

2015 · MenB introduced

2017 · 5-in-1 → 6-in-1

2019 · HPV extended to boys

2020 · PCV 3+0 → 2+1

This is a valid-time problem: evaluating someone born in 2003 needs the schedule as it stood in 2003. No open-source project anywhere solves this for a national schedule in a principled, versioned way.

Where we're going

Flip the source of truth

One trusted upstream source

What if the computable schedule were the source of truth, and the PDF, the website, and clinical tools were all generated from it?

Today - "digital paper"

Word document → PDF → each system re-implements the rules by hand. The code is a derivative of the document, and may be wrong.

greenbook - one upstream source

Experts author the Schedule directly in a computable form → the PDF, websites, and clinical systems are all rendered downstream from the same trusted data.

Build it correctly for the current schedule first, so historical versions become an additive extension - not a rewrite.

The domain model

A shared language

The words we use, used precisely - the same in the spec, the code, and this talk.

Schedule → Series → Dose

The schedule is built as a nested structure, authored series-by-series:

Schedule

A versioned set of recommended immunisations for one Jurisdiction, effective from a date.

Series

One vaccination programme within it - "6-in-1 primary", "MMR second dose" - an ordered set of doses.

Dose

One expected administration, with target / earliest / latest age and a minimum interval.

Authored series-centric; the familiar age-centric table is rendered from it for publication.

Products and antigens

Antigen

A disease target that vaccination protects against - diphtheria, Hib, measles.

Product

A specific marketed vaccine, identified by a SNOMED code - e.g. Infanrix Hexa.

One Product covers one or more Antigens. The product map records that bridge:

Infanrix Hexa (6-in-1) → diphtheria · tetanus · pertussis · polio · Hib · hepatitis B

Product class - the unit the Green Book names

The Green Book does not name brands. It names a Product class: "6-in-1", "MMR", "Td/IPV".

  • A product class groups interchangeable products - Infanrix Hexa and Vaxelis are both 6-in-1.
  • It is the conformance key: how a recorded dose is matched to a series.
  • One class can serve several series - MMR maps to both the first-dose and second-dose series; the ages tell them apart.
A Series is the programme unit. A Product class is the conformance key. Don't conflate them.

The key insight

Two questions, not one

Conformance vs coverage

Two different clinical questions, with two different matching rules:

Conformance

"Did the patient get the doses the Green Book named, at valid ages?"

Matched by Product class. Answered per series.

Coverage

"What diseases is the patient protected against?"

Computed across the Antigens of every product received. Answered per antigen.

Collapsing these two into one - using antigen overlap to answer both - was the original bug.

Why it matters: the 6-in-1 trap

A 6-in-1 dose contains Hib, tetanus, diphtheria and polio - antigens that also appear in later booster series.

Match by antigen overlap wrong

The 6-in-1 dose is dragged into the Hib/MenC and Td/IPV booster series and flagged "invalid - given too early". Clinically nonsense: it is a primary dose, not a failed booster.

Match by product class right

A 6-in-1 dose conforms only to the 6-in-1 series. Hib protection is still real - but that is the separate coverage question, not conformance.

Two questions, two answers. Hib coverage: satisfied. Hib/MenC booster conformance: not yet.

Answering the real question

"Fully vaccinated?" - it depends

Two honest answers

Up-to-date for age headline

Every dose due by now has been given. A perfectly on-schedule 6-month-old is up-to-date for age - even though MMR and HPV still lie ahead.

UpToDateForAge · BehindForAge · Unvaccinated · Unknown

Fully vaccinated strict flag

Every dose at every age has been given. That same 6-month-old is not fully vaccinated - and that is the correct answer.

We rejected a "fully immunised for life stage" status: with new adult vaccines (shingles, pneumococcal) it is an unstable moving target.

Honest about messy records

Real records are not tidy. Two cases that naive tools hide, greenbook surfaces:

Outside standard schedule

A dose given too early or too late is recorded as received but does not count toward completion - labelled, not hidden, and not harshly called "invalid". It was a real clinical event.

Unmatched dose

A dose whose product class fits no series here (a 5-in-1 against the 2026 schedule), or an unknown code - surfaced, not silently dropped.

A 5-in-1 unmatched against today's schedule conforms under historical versioning when the applicable schedule asked for a 5-in-1 primary course.

Proof of concept

It runs today

From a FHIR record to a clinical answer

Give the engine a patient's FHIR bundle and a Schedule; it returns the headline status and the per-series gaps.

$ greenbook evaluate ...
      six-month-infant.json

Up-to-date status: UP_TO_DATE_FOR_AGE
Fully vaccinated:  no

[COMPLETE] 6-in-1    3/3  up to date
[COMPLETE] Rotavirus 2/2  up to date
[PARTIAL ] MenB      2/2  up to date
[NONE    ] MMR       0/0  up to date
$ greenbook evaluate ...
      behind-toddler.json

Up-to-date status: BEHIND_FOR_AGE
Fully vaccinated:  no

[COMPLETE] 6-in-1   3/3  up to date
[PARTIAL ] MenB     2/3  BEHIND
[NONE    ] Hib/MenC 0/1  BEHIND
[NONE    ] MMR #1   0/1  BEHIND

Same engine, same schedule. The on-schedule infant is up to date; the toddler's catch-up worklist falls out automatically.

Where this goes

Historical versioning

Evaluate against the schedule that applied at the patient's birth - the hard, valuable part. The file-per-version design makes it additive.

render

Generate the published age-centric table from the data - proving the thesis: the PDF comes from the data, not the data from the PDF.

A live web demo

Set a date of birth, pick doses from a menu, and watch the evaluation update in real time.

Beyond the UK

The format is global by design - a jurisdiction block and per-coding-system product maps. Other countries can follow.

greenbook

The computable, versioned
Green Book does not exist.

This project creates it.

Rust library & CLI · AGPL-3.0 · github.com/pacharanero/greenbook