A care tool for one of healthcare's biggest, least-visible problems: finding the chronic patients quietly falling off their treatment, so a pharmacy can help them back onto it before it becomes a hospital bed.
A self-directed project, born from an interest in health tech: how far can you model patient adherence from the data a pharmacy already has? Built and validated end to end on a five-year synthetic pharmacy, over 800,000 dispensation lines across ~3,600 patients, with no real patient data anywhere in it.
A live, in-browser visualisation of the whole synthetic pharmacy: five years of dispensations resolving into patients, then into the gaps the engine flags. Drag to orbit.
The thesis
Around half of all patients on long-term medication don't take it as prescribed (WHO), one of the largest and least-visible problems in healthcare. The cost is human first: worse outcomes, avoidable hospitalisations, and, by OECD estimates, close to 200,000 premature deaths in Europe every year. It is also staggeringly expensive, an estimated €125 billion in avoidable spending across Europe annually.
Adhera is, first, a care tool. The evidence of who is slipping already sits in every pharmacy's ERP: who picked up what, and when. Adhera reads it and turns it into an assistential signal, which chronic patients are falling off their treatment, and why, so the pharmacy can reach out and help them stay on it. The margin a pharmacy loses to that non-adherence is the same signal seen from the other side, which is what makes doing right by the patient and protecting the business the very same action.
What it does
Four stages, from a raw legacy database to a patient the pharmacy can help.
Reads the pharmacy
Discovers the schema of a messy, real-world pharmacy ERP database, maps it to a clean canonical model through per-system adapters, and pseudonymises every patient identifier at the boundary. The unglamorous 80%: turning a legacy on-prem database into trustworthy analytics input.
Measures adherence
Builds each chronic patient's medication-coverage timeline and computes PDC (Proportion of Days Covered), the standard pharmacoepidemiology adherence metric, with days-of-supply inference and carry-forward. No invented method: the same measure payers and researchers use.
Explains the gaps
A coverage gap alone means nothing. A deterministic rules engine separates genuine drop-off from its benign look-alikes: therapy switches, renewal lag, stockouts, hospitalisations and patient churn, so a pharmacist sees cause, not just a number.
Turns the signal into care
The point isn't a dashboard, it's a patient helped. The signal flags exactly which patients need a gentle, opt-in reminder to refill before they lapse, so the pharmacy can act as the care provider it already is. The dispensing margin recovered when a patient stays on therapy is the by-product that pays for the care.
How it tells a real lapse from a false alarm
A patient is "chronic" once their history shows a treatment is ongoing, several refills of the same therapy over many months. For each one, Adhera rebuilds a day-by-day coverage timeline: how many days each pack should last, inferred from its size and dosage, and even from the patient's own repurchase rhythm, carried forward until the medicine runs out. When coverage runs dry for longer than a grace period, that is a gap.
But a gap on its own is just an empty stretch on a calendar, it could be a dozen harmless things. The hard part, and the heart of the engine, is deciding why, by cross-referencing the pharmacy's own data to rule each explanation in or out before a single patient is ever flagged:
Ruled outTherapy switch
Another drug in the same therapeutic class (ATC) starts as this one stops, the prescriber changed the treatment. No lapse.
Ruled outStock shortage
The exact product was in a national supply shortage during the gap, cross-checked against the AEMPS/CIMA shortage registry. Not the patient's doing.
Ruled outHospitalisation
Two or more of the patient's chronic therapies pause together with no pharmacy activity at all, the signature of an inpatient stay, not a lapse at home.
Act on itRenewal due
The prescription plan simply expired. A timely nudge to renew keeps the patient covered, the gentlest of the actionable cases.
Different signalLeft the pharmacy
The patient stopped buying everything, including non-prescription items, they moved or changed pharmacy. A different signal: a lost patient, not a lapsing one.
Act on itGenuine non-adherence
None of the above explains it. A real, silent lapse, exactly the patient a reminder is built for, and the only kind that counts toward the recoverable figure alongside renewals.
Only the genuine lapses and the renewals survive that filter into the actionable signal, and every number is a floor: when the cause is ambiguous, the engine leaves the patient out rather than raise a false alarm.
How it's built
Read-only and private by construction
A single connection layer can only issue read-only queries; nothing the code does can write to a pharmacy's database. Raw identifiers, name, ID, prescription card, never leave the ingestion boundary, downstream the engine sees only salted hashes. No real patient data exists anywhere in the project.
Deterministic and reproducible
Same input plus same code version yields identical output, no hidden randomness, no wall-clock. Every figure carries its denominator, exclusions and confidence as adjacent data, and adherence numbers are reported as conservative floors, since fills made at another pharmacy are invisible to any single store.
Validated like research
The engine under Adhera is a deterministic rules pipeline, not a machine-learning model, and deliberately so: in a GDPR-bound, patient-safety setting you need a result you can explain line by line, reproduce exactly and defend to a regulator. The validation discipline is ML-grade anyway: a synthetic ground-truth oracle labels every gap with its true cause and the engine is scored against it blind, yielding precision of 1.000 on five of six cause categories with a full confusion matrix.
PythonPolarsMSSQLPharmacoepidemiology (PDC)Synthetic datapytest + CI
Why I built it
Adhera is applied health-data engineering and analytics, not machine learning, and deliberately so. In a setting bound by GDPR, patient safety and real money, a black-box predictor would be a liability: you need a result you can explain line by line, reproduce exactly, and defend to a regulator. So the core is a deterministic, auditable rules engine, grounded in established pharmacoepidemiology, and validated with the rigour ML brings to evaluation rather than to prediction.
I built it to learn the hard parts of health tech from the data up: messy real-world records, strict privacy boundaries, and the discipline of shipping a number you'd stake your name on. A predictive layer, who is about to drop off, would be the next step. It belongs on a foundation that is honest first.