uniquehuman
Engineering

How a logged migraine travels from your phone to your doctor

UniqueHuman Engineering · Jul 10, 2026 · 5 min read

A person living with chronic pain opens UniqueHuman on a bad morning and spends about a minute answering seven short questions: when the migraine started, how much it hurts from one to ten, which symptoms and possible triggers showed up, what they took for it. That minute of logging is the front door to the whole platform. Almost everything interesting about the engineering is what happens to those answers next, on the way to someone who can actually use them.

Two kinds of input, one person

Two very different streams describe a single person. The first is what they tell us on purpose. In the app that unit is an episode, our word for one migraine, captured through that seven-question flow. Only the start time is required. Everything after, even the pain level, is optional, because nobody mid-migraine should be marched through a form. We create the episode the instant they answer the first question and save each step as it happens, so a log abandoned halfway still keeps what was entered. On a bad day, half an answer beats none.

The second stream is passive, and the person does nothing to produce it. Whatever they wear, an Apple Watch, an Oura ring, a Garmin, writes to Apple HealthKit, the shared vault iOS keeps health data in, and the app reads heart rate, sleep, heart rate variability and more from that single place. One stream is deliberate and sparse, the other automatic and enormous, and both have to end up describing the same day in the same language.

The phone does the tidying, the server does the math

We have written separately about making wearable data comparable across devices, so briefly: before anything leaves the phone, the app groups the flood of tiny readings into fixed ten minute windows, folds a night's sleep into one session, drops duplicates when a watch and a ring both report the same thing, and tags each upload with the person's own timezone. Then it syncs about every ten minutes, sending only what is new and re-queuing anything that failed to upload.

What the phone will not do is judge. It never decides a night was unusual or a trigger mattered. That is the server's job, deliberately, because the useful math needs more history and more compute than a phone should spend, and because keeping it in one place gives one honest answer instead of a different one each time the app opens.

Learning your normal before it says anything

On the server, a FastAPI service (a standard Python web framework) writes everything into one Postgres database, keyed to each person, and rolls the raw readings into a per day summary. Only then does analysis begin, and it begins by learning what normal means for you in particular.

That is the part outsiders underestimate. There is no universal healthy heart rate variability, only yours, and the range of your own ordinary days. So for each person we train a small model on about ninety days of their history, using scikit-learn, a standard machine learning toolkit, to learn the shape of their normal and flag days that fall outside it.

A second engine scores each day against that personal baseline as a z-score, meaning how many standard deviations a reading sits from your own average, and folds that, together with the model's own verdict, into one strain score from zero to a hundred.

It is why the app can spend your first weeks openly learning your normal instead of pretending to know it. A score shows up early, but it says plainly when the picture is still thin, the anomaly detection holds off until there is about a month of history behind it, and nothing is ever filled in with a guess. We would rather tell you we are still learning than show a confident number we have not earned.

How the work comes back to you

A pattern nobody sees is just a chart, so the results go back out in two directions. In the app, the person sees their flare status and pattern cards drawn from their wearable data, next to the history of the episodes they logged, all in plain language. For their own doctor, we generate a PDF that condenses those logs and the wearable data around them into something readable in the span of an appointment, the kind of thing you can hand across a desk and actually get through in the few minutes a visit gives you.

Both draw from one Postgres database, keyed to each person, and access to it stays strict. A request only ever comes back with the data belonging to the person who asked, and that limit lives in the shared data layer rather than in something each page has to remember, the same principle behind how we secure health data everywhere else.

The last mile is the thinnest, and we know it

If you are keeping score, the front of this pipeline is more finished than the back. Capture is solid, syncing is careful, the per person modeling is real and running on a schedule. What is still catching up is the last step, putting what the math already knows in front of the people who could use it. The report a doctor sees today leans on your logs and a summary of the wearable data around them. The strain scores and anomaly flags the server already computes still sit mostly in the database, rather than folded into that report so a pattern is obvious at a glance. That order was on purpose. A polished dashboard over shaky data is worse than no dashboard, so we built the honest capture and the honest math first. The work ahead is closing that gap, turning signals the server can already see into something you and your doctor can act on, which is the whole reason the loop exists and the part we are building next.

More resources