DEV Community

Mathéo Delbarre
Mathéo Delbarre

Posted on

Checking drug interactions in places where the internet barely exists

By Mathéo Delbarre, 3rd year CS student at EPITECH Nancy, France


TL;DR

Problem: medical workers in war zones, refugee camps, and rural clinics have to make drug interaction decisions with no internet, on hardware that predates most currently-supported software. A missed contraindication there is not a bug report, it is a patient at risk.
Solution: MenSung, an offline medication interaction checker in Rust. One static binary, one database file, every lookup fully local.
Constraints: runs on a 10-15 year old laptop (Core 2 Duo, 2-4 GB RAM, slow HDD), lookups under 5ms, database integrity verified on every open.
Data: DDInter interactions enriched with RxNorm, WHO ATC, PubChem, and openFDA drug labels. Every license checked directly, not assumed.
Code: github.com/Etoile-Bleu/MenSung


The last time I wrote here, I told you about ZamSync, a sync engine for district clinics in Bhutan that run on 2G and lose power mid-transfer:

And then I wrote about what happened after, because I genuinely was not prepared for it:

I need to start this article by talking about that, because without it, MenSung would not exist.


What your kindness actually did 💝

Since those articles: strangers starred the repo. People forked it to build things I never imagined, like offline-first sync for password managers. KairosOps opened a pull request that fixed a real Windows bug in my code, and I still remember sitting there staring at the notification (I was so happy that someone saw my issue and added a fix 😭). And per-oestergaard left that message in the discussions, the one I keep re-reading, just to say the problem mattered and he was sorry he couldn't help more. He apologized for only being kind. I still think about that.

I said in my last article that the message reminded me why I was building. What I didn't fully understand at the time is that it also changed what I would build next. When strangers from countries you've never visited tell you "this problem is real, keep going", the question stops being "should I keep doing this?" and becomes "okay, what else is broken out there?"

Also, some personal news: I passed my second year! 🎉 I'm now a third-year CS student at EPITECH Nancy. The exams happened somewhere between two pull requests, and honestly, the energy from you all carried me through more of that revision period than I'd like to admit haha.

So this is the next project. It stays in the same world as ZamSync, offline-first software for places where the internet barely exists, but it moves one step further down the chain: from moving medical data to using it at the moment of care.


The problem I couldn't stop thinking about (again)

While researching how clinics in low-connectivity regions actually work for ZamSync, I kept running into a moment in the workflow that scared me more than data loss did.

A patient in a field clinic is already taking one drug. A medical worker is about to give them a second one. The question is simple and brutal: is this combination safe?

If you have internet, this is a solved problem. Medscape, DrugBank, a dozen interaction checkers, all one search away. If you don't have internet, the answer is a paper reference book that may be years out of date, someone's memory at the end of a 14-hour shift, or nothing.

And this is not a small or hypothetical population. Here is what the numbers say:

  • The WHO estimates the global cost of medication errors at US$42 billion annually, and made reducing medication-related harm its third Global Patient Safety Challenge. Medication harm accounts for roughly half of all preventable harm in medical care.
  • Drug-drug interactions specifically are a major slice of that: a 2022 retrospective study of ten years of adverse drug reaction reports found that roughly one in six adverse drug reactions was correlated with a drug-drug interaction, and a descriptive analysis of the FDA's adverse event reporting system links DDIs to tens of thousands of emergency visits and around 195,000 hospitalizations per year in the US alone. That is a country with internet and with pharmacists at every corner.
  • Now move to the settings I actually care about. A study in Zaatari refugee camp in Jordan identified 3,572 drug-therapy problems across 1,533 patients, a mean of 2.33 problems per patient, driven by the lack of structured pharmaceutical care. A review of hospitalized patients in low-resource settings found potential drug-drug interactions in the majority of the patients studied, with the tools to catch them largely absent. And pharmacists working in humanitarian crises have been documenting for years that they are asked to do this job with almost no infrastructure.
  • Meanwhile, per the ITU's Facts and Figures 2024, 2.6 billion people are still offline, and in low-income countries only 27% of the population uses the internet at all. The places with the least connectivity and the oldest hardware are very often the same places with the least pharmaceutical support.

Read those side by side and the gap is hard to unsee. The best interaction data in the world is sitting on web servers, and the people who need it most are the ones who can't reach it.


Why I didn't just use an existing tool

Same discipline as last time: before writing a line of Rust, I looked hard at what already exists, because "I rebuilt something that already existed but in Rust" is not a contribution, it's a hobby (which is fine! but it's not this).

Web checkers (Medscape, DrugBank, Drugs.com) are excellent and free. They also require internet for every single query. Offline, they are worth exactly nothing.

Epocrates and UpToDate Lexidrug genuinely do offline: you download the database to your phone and query locally. These are serious, professional tools and I want to be fair to them. But look at the assumptions they carry: a reasonably modern smartphone, an app store account to install and update, and a paid subscription for the full feature set. In a refugee camp or a rural health post, the machine that's actually available is more often a donated 12-year-old laptop than a current iPhone with a Wolters Kluwer subscription. And neither is open source, so nobody can audit what the tool does with queries, adapt it, or redistribute it freely to a hundred clinics on USB sticks.

Open source? I searched. I found hospital-specific projects, academic prototypes, and APIs that wrap the same public datasets, all of which assume a server or a connection somewhere. I could not find a single tool that is simultaneously open source, fully offline, and built to run on genuinely old hardware.

MenSung Web checkers Epocrates / Lexidrug
Works with zero connectivity Yes No Yes (after setup)
Runs on a 15-year-old laptop Yes Browser-dependent No (smartphone)
Open source, auditable Yes No No
Free to redistribute (USB, LAN) Yes No No
Cost Free Free (online) Subscription

That empty corner of the table is where MenSung lives.


So I built MenSung 💊

The name keeps the thread from ZamSync: it comes from Dzongkha, the language of Bhutan. Men means medicine, sung means protection. A medical shield.

Before anything else, the disclaimer that also ships inside the tool itself, because in this domain it's not legal boilerplate, it's the truth: MenSung is an offline informational aid. It does not replace professional medical judgement, clinical protocols, or qualified healthcare decisions.

What it is: one statically linked Rust binary, one database file sitting next to it. No server, no cloud, no GPU, no installation procedure beyond copying two files. You type two or more drug names, it tells you every known interaction between them, most severe first:

Between Warfarin & Ibuprofen:

Warfarin information:


The two rules everything else obeys

Before writing much code, I wrote a medical data policy. Two rules came out of it, and honestly they have vetoed more of my ideas than any technical constraint has.

Zero false negatives. If an interaction exists in the data, it is shown. Recall beats precision, every time. An extra warning costs the worker a moment of attention. A missed interaction can cost a patient's life. So there is no clever noise filtering, no "hide minor results", no pagination that quietly drops entries. Code that would remove a true interaction from the output does not get merged, period.

No silent correction. Drug names are hard to spell, and MenSung only accepts International Nonproprietary Names, no brand names, because brands change across borders and INN doesn't. When a typed name doesn't match exactly, the tool refuses to guess:

Ranked candidates, similarity scores, and it waits. There is no code path anywhere in the project where the software substitutes its own guess for what the human typed. In most software, autocorrect is a convenience. In this one, it would be a way to hurt someone.


The .men file

The database is a custom binary format. SQLite would have been reasonable, but I wanted three things it doesn't give me for free: zero-copy reads, a layout I fully control, and a file that verifies itself.

The first version of the format weighed about 28 MB. Then I noticed how absurdly repetitive medical interaction text is: the same risk descriptions reused thousands of times across drug pairs. Version 2 deduplicates every string into a shared string table. Same data, 9.3 MB. The reader maps the file and reads records in place, no deserialization, no intermediate allocations, which is how lookups stay under the 5ms budget on Core 2 Duo class hardware.

The header also embeds a SHA-256 checksum of the payload, verified on every single open. That sounds paranoid until you picture how this file actually travels: on a USB stick, laptop to laptop, through machines nobody maintains. A corrupted medical database that loads anyway is precisely the failure this project exists to prevent. Checksum mismatch, file refuses to open, end of story.

The architecture is the same hexagonal discipline as ZamSync (a workspace of five crates, dependencies pointing one way, the domain crate knowing nothing about files or networks or terminals), just enforced more strictly this time, because on ZamSync I let a couple of boundaries blur early on and paid for it for weeks.

Performance budgets, treated as bugs when violated: startup under 100ms, lookup under 5ms, memory under 50 MB, binary under 10 MB.


Where the data comes from, and the licensing rabbit hole

Interactions come from DDInter, a curated academic drug-drug interaction database. On top of it, a build pipeline enriches every drug from four more sources: RxNorm for standard identifiers, WHO ATC classification, PubChem for chemical properties, and openFDA for the drug's own label facts: boxed warnings, contraindications, pregnancy warnings.

Here is something I learned that I wish someone had told me earlier: check every data license yourself, directly, before you ship anything. I spent an entire evening reading terms-of-service pages instead of assuming, and it genuinely changed the project. DDInter is CC BY-NC-SA 4.0, which means the installed database carries a non-commercial license completely separate from the code's MIT/Apache-2.0 license, and the docs have to say so in plain words. WHO ATC data carries its own restrictions. PubChem is not the blanket public domain everyone on the internet assumes it is (their own site policy says so). openFDA, mercifully, is CC0. All of it is written down in the data policy with sources, because "I think it's fine" is not a licensing strategy for a medical tool.

The enriched database weighs about 27 MB and lives on a GitHub release. First run, MenSung asks permission, downloads it over verified HTTPS with a little progress bar, and that is the last time it ever touches the network. If the download fails mid-way (more on that below...), it falls back to fetching DDInter's public CSV export and compiling a smaller database locally, so even a half-broken connection still ends in a working tool. And you can always skip the network entirely by copying a pre-built .men file next to the binary by hand.


Small things I learned the hard way

Keyboard shortcuts are a real question. The drug-info screen was on F1. Turns out F1 is intercepted by half the terminals and operating systems on Earth for their own help screens, so for many users the key just... did nothing, silently or open Edge's help. Fine, use the letter i then. Except users are typing drug names into a text field, and "Ibuprofen" contains an i. The answer was Alt+I, and the lesson was that even a one-key decision deserves five minutes of thinking about whose hands are actually on the keyboard.

Unit tests don't look at the screen. All my TUI tests were green while the real interface was happily truncating long warning texts at the edge of the box, invisible unless you actually ran it. I found more real bugs driving the binary in a deliberately tiny tmux pane than in any test file. Tests matter, but nothing replaces looking at the thing with your own eyes.

Write the policy before the code. The medical data policy has vetoed shortcuts I absolutely would have taken at 1am. Past me, writing rules in a calm state, keeps protecting the project from tired me. I can't recommend this enough for any project where correctness has stakes.


Where this is going

The honest status: MenSung works today. Releases are built for Linux, Windows, and macOS, the database installs itself on first run, and within the limits of its data and with clinical judgement on top, it answers the question it was built to answer.

What I'm exploring next, carefully: a second, independent interaction source, so important interactions can be cross-confirmed instead of resting on one database alone. The data model already supports multiple sources per claim, that part is built and tested. The hard part turned out to be entirely non-technical.

The dataset I keep coming back to is TwoSIDES, from the Tatonetti Lab. Nicholas Tatonetti is a researcher who now directs his lab at Cedars-Sinai, and back when he was at Stanford he and Russ Altman published a now-classic 2012 paper in Science Translational Medicine on mining the FDA's adverse event reporting system for drug effects nobody had catalogued. TwoSIDES came out of that work: over 3,300 drugs and 63,000 combinations connected to millions of potential adverse reactions, all derived from real-world reports rather than curated literature. It's a genuinely different lens on interactions than DDInter, which is exactly why cross-confirming against it would mean something.

The problem is that I could not determine the license. The lab says the resources are free and open for academic use, which is lovely, but "academic use" and "an open source tool redistributing a compiled database to clinics" are not obviously the same thing, and I found different statements in different places. And the site itself notes the data is quite a bit out of date. So instead of guessing, which is precisely the mistake I already promised myself I would never make with medical data, I wrote to Nicholas Tatonetti directly to ask him what the license actually permits. I'm waiting to hear back. I'd rather ship one clean, well-licensed source than three legally ambiguous ones, even if it means the feature waits.

Further out: dosage support, and possibly translations of the clinical texts, since INN names are already international but the warnings are currently English-only.


How you can help

Same honesty as always: I can write Rust, I cannot market a project, and this one needs different kinds of eyes.

If you're a pharmacist, doctor, nurse, or have done medical work in a low-resource setting: you are the person I most want to hear from. Does the severity display make sense? Is the name-confirmation flow safe enough? What would you never trust a tool like this to do? Ten minutes of your criticism is worth more than a hundred stars to me. My email is matheo.delbarre@epitech.eu and I answer everything.

If you write Rust: the repo is open, the architecture docs are real, and I merge quickly. The fuzzy matcher and the binary format reader are the areas where a second pair of eyes would matter most.

If you know an interaction dataset with a clear, redistributable license: please, please tell me. This is currently my biggest bottleneck and it's not even a technical one.

And if you just want to help in 5 seconds: a star on github.com/Etoile-Bleu/MenSung genuinely matters, it's how the next stranger decides the project is worth their five minutes. I learned that from all of you last time.


References

Problem sources:

Data sources used by MenSung, with licenses documented in MEDICAL_DATA_POLICY.md:


Thank you for reading. And thank you, really, to everyone who starred, forked, fixed, commented, and wrote after the last articles. I said the response changed how I think about what I'm building. Here is the proof: it built the next project. 💙

-- Mathéo Delbarre

Top comments (0)