A home visit and a hospital basement are the two places a phlebotomist reliably loses signal, and they are also the two places where guessing which write wins is unacceptable. What queues, what cannot queue, and why a conflict has to reach a person.
A phlebotomist loses signal in two places with great reliability: inside somebody’s house, and in the basement corridor where the phlebotomy room is. Both are places where the work continues regardless, and both are places where a laboratory system that stops working is a laboratory system that gets worked around on paper.
This post is about specimen collection only. Result entry, validation and release are online operations in LabFlow and this article does not argue otherwise — the reasons for that are at the end rather than assumed at the start.
Why the round is the offline case#
A collection round is a sequence of visits planned in advance, executed away from the building, and reconciled afterwards. Every property of that sentence pushes toward offline-first.
The work is planned, so the data needed can be fetched before leaving. The work is away, so connectivity is a variable rather than a given. The work is reconciled afterwards, so a short delay between an action and the server hearing about it is normal rather than exceptional. And crucially, the phlebotomist is the only person doing anything to these specimens while they are out — which is what makes most of the conflict problem disappear, and makes the remainder sharp.
Offline-first is not a resilience feature here. It is the normal operating mode for a shift. A design that treats it as a degraded state will get the priorities backwards — including, usually, by making the offline path the one nobody tests.
Identity is the thing you cannot defer#
Everything in a collection depends on the phlebotomist having correctly identified the patient in front of them, and that check cannot be deferred to a moment when the network returns, because by then the patient has gone.
So the round is downloaded with what identification requires: the patient’s name, date of birth and identifier, the tests requested, the tubes needed, and any special preparation. That download happens on a good connection before the round starts, and it is the one moment in the design that genuinely needs the network.
The corollary is unpleasant and worth stating: a round that was not downloaded cannot be worked offline. Not "works with reduced information" — cannot be worked. Presenting a phlebotomist with a patient record that might be stale in the fields that identify a person is worse than presenting nothing.
Labels are printed at the patient, and that is a hardware problem#
The accession identifier and the tube labels belong at the point of collection. A tube labelled later is a tube that might be labelled wrong, and mislabelling is the pre-analytical error with the worst consequences and the least visibility downstream.
That means the device must be able to allocate an identifier without asking the server. The usual answer is to pre-allocate a block of accession numbers into the round at download time, which is unglamorous and completely reliable: the identifiers are real, the server already knows they belong to this round, and there is no collision to resolve later.
The alternative — a client-generated identifier reconciled to a server one afterwards — means the barcode on the tube and the identifier in the laboratory are two different things for a while, and every system that touches the specimen in that window has to know about both.
What queues#
An action queues when it is a statement about something the phlebotomist personally observed, and nobody else is in a position to contradict it.
- The visit was attempted, at this time, at this address.
- The patient was not there.
- The specimen was collected, at this time, into these tubes, by this person.
- The volume was insufficient, and a second attempt was or was not made.
- The labels were printed and applied.
- The specimen was placed in this storage condition, in this container, at this time.
- The visit was rescheduled, with a reason.
- A note was added.
These are all events, not edits. They append to a custody record rather than changing a field, and appending is what makes them safe to replay in order when the connection returns. Two of them arriving out of order is a sorting problem, not a conflict.
What cannot queue, and why#
The list of things that must not be available offline is shorter and much more important.
- Anything that reads or writes another patient’s data. An offline cache is a copy of clinical data on a device that gets left in cars, and it holds today’s round and nothing else.
- Cancelling an order. The cancellation may have already happened centrally, or the order may already have been collected elsewhere, and a queued cancellation that replays an hour later can withdraw work that has been done.
- Anything that releases a result to anybody. Release is the line after which somebody may act on a value, and it is not a decision to take without knowing the current state of the record.
- Changing who a specimen belongs to. If identity is wrong, the correct action is to record that it is wrong, not to fix it from the field.
- Anything that spends money or sends a message to a patient or clinician.
The unifying rule: an action may queue if replaying it late is still true. "I collected this at 09:14" is still true at 11:00. "Cancel this order" is a command about the present, and the present has moved.
A queued command is a command from the past. Events survive the delay because they describe something that happened. Commands do not, because they describe something that should happen now — and by the time they arrive, now is different.
What synchronisation actually has to do#
With that split, the sync is mostly boring, which is the goal.
The device holds an append-only queue of events, each with a client identifier generated at creation, a monotonic sequence number within the round, and the time it actually occurred. On reconnect it replays them in order. The server accepts each one idempotently on the client identifier, so a partial upload retried in full changes nothing and a duplicate is a no-op rather than a second collection.
Two details are worth building in from the start. Record the time the event occurred, not the time it was uploaded, and record both — the gap between them is diagnostic. And keep the queue after a successful upload for long enough that a phlebotomist who is asked "what happened at the second address" can answer from the device rather than from memory.
The conflicts that remain, and why a person has to see them#
Most of the collection workflow cannot conflict, because only one person is doing it. What remains is the set of cases where the world changed centrally while the device was away, and every one of them is a case where guessing is unacceptable.
- The order was cancelled centrally, and the specimen was collected anyway. The specimen exists. It is in a bag. Discarding the event because the order is cancelled loses the fact that a patient was bled.
- The patient was collected at a walk-in centre while the phlebotomist was en route, so there are two collections for one order.
- The requested tests changed after download, so the tubes drawn do not match the tests now requested.
- The specimen was rejected on receipt for a reason the phlebotomist could not have known.
Last-write-wins resolves all four silently and gets at least two of them wrong. The correct behaviour is to accept the event — it is true, it happened — and raise the discrepancy for a person to settle, with both sides of it visible.
This is the same argument as versioned results, one workflow earlier. A collection that conflicts with a cancellation is not a data problem to be reconciled by a rule; it is a clinical situation in which somebody drew blood that may not be needed, and that person deserves an answer rather than a silent discard.
What the device is allowed to hold#
An offline-capable clinical application is a device carrying patient data outside a building, and the design has to be honest about that.
- Today’s round only, and only what identification and collection require. No history, no results, no other patients.
- Encrypted at rest by the platform, behind the device lock, with the application requiring authentication on resume rather than staying open.
- Purged when the round is reconciled, on a timer that runs whether or not anybody remembers.
- Remotely revocable, so that a lost device stops being a problem once it next has signal — and a device that never regains signal is why the purge timer is local rather than server-driven.
Why the rest of the laboratory stays online#
It would be consistent-sounding to extend the same model to result entry and validation. It would also be wrong.
Validation is a judgement made with context: the patient’s previous values, the delta check, the quality-control state of the run, and whether a critical value needs an escalation. Every one of those is a fact about the current state of the system, and a validation made against a cached version of them is a judgement made on stale evidence. Release is worse still, because it is the moment somebody else may act.
So collection is offline-first and the bench is online, and that is a deliberate boundary rather than an unfinished one. The place where a person is standing in front of a patient with a needle is the place where the network cannot be a prerequisite. The place where a person is deciding whether a number is safe to send to a clinician is a place where knowing the current state is the whole job.