Watch a specimen become a signed result.

A multi-tenant laboratory information system. Ordering, custody, validation, quality control and release, with every rule visible and every step recorded.

A-24-0186entered
Stagepatients
NowRegistered at the front desk. One person, not one visit.
TestHaemoglobin LOINC 718-7
Containeredta_tube
Storagerefrigerated

Six links, and none of them collapses into another.

Collapse any two and a real workflow breaks. Move the specimen along the chain to see which one.

chain1 of 6

A patient is a person, not a visit.

One record carries every order they have ever had, at every laboratory that uses LabFlow. Identity is the root of the chain, so nothing below it can be attributed to the wrong human.

patients1 of 6
NameIfeoma Adeyemi
Born1987-03-11
Sexfemale
IdentifierP-0000-4471

What LabFlow is

Four claims, each one checkable further down this page.

11Multi-tenant, and role awareTwelve personas get twelve applications. A tenant's data never leaves its own boundary, and every list query has to prove that from its own filters.
2HL7 v2 and FHIRExport and import as files: a released report downloads, an order file becomes a draft. There is no live feed, and that limit is stated rather than implied.
17Offline-first collectionsA phlebotomist who loses signal keeps working. Seventeen custody actions queue on the device and reconcile on reconnect, with conflicts surfaced rather than guessed.
8Web and AndroidOne codebase and one vocabulary. Eight result states, so the status a clinician sees never depends on which button somebody pressed.

A result is a decision, not a row.

Everything else on this page follows from that one sentence.

Who may change it. What its status means, and who else is allowed to mean something different by the same word. What context has to be on screen before a person accepts it. Why it can never be quietly overwritten, and why a report issued last March still says what it said last March.

A laboratory information system that treats a result as a row in a table will get all of those wrong in the same way, and the wrongness will not show up in a demo. It shows up eighteen months later, in a case review, when nobody can say what the clinician was looking at.

So the rest of this page is not a feature list. It is six or seven places where you can operate the rule yourself and watch what it refuses to do.

The worklist, while you are reading this.

Results arrive, ages climb, and one row is validated by a person. Every flag carries an icon and a word as well as a colour.

Pending review, haematology benchreceiving
Results awaiting review. New rows arrive at the top and the oldest leaves the window.
AccessionPatientTestValueFlagStatusSince receipt
A-24-0191Declan O SuilleabhainCreatinine168 umol/LHighentered14 min
A-24-0190Sofia BerhanuHaemoglobin14.2 g/dLNormalreleased38 min
A-24-0189Tomasz WierzbickiPotassium6.9 mmol/LCritical highentered52 min
A-24-0188Priya RamanathanBasic Metabolic Panel6 of 8Partialin_progress1 h 07 min
A-24-0187Marcus VandermolenHbA1c8.4 %Highentered1 h 22 min
A-24-0186Ifeoma AdeyemiHaemoglobin9.1 g/dLLowvalidated1 h 41 min
Demonstration data. Names, accession numbers and values are invented for this page and are not anybody's results.Ages are receipt-to-result. Collection-to-result is a different number and the two are never added together.

Eight states. One writer.operable

Pick the state a result is in. The legal moves light up with the capability each one needs, and the rest say why they refuse.

A result sits at pendingTwo moves are legal from here. Choose one of the lit states to see what it costs, or a dim one to see what stops it.

Amended is deliberately not in this list. A correction is a new row at version 2 that supersedes the previous one, and the previous one stays released. There are two clinically meaningful values after an amendment, and a status field that flips destroys the first.

Auto-validation suggests. A person releases.

Rules that check a result against its resolved range, its delta from the patient's own previous value and the quality-control state of the run are genuinely useful. What they produce is a suggestion and a reason, not a release.

Anything describing itself as automatically verifying results is making a claim the product cannot back, and in a regulated setting it is the first claim anybody examines.

Whoever entered a result may not validate it, unless the tenant has explicitly turned on single-person operation. Small laboratories genuinely need that, so it is a setting rather than a default, and the mode in force is recorded on the transition.

range_resolved9.1 g/dL against 12.0 to 15.5, resolved for a female adult. Flagged low, inside the reportable interval.
qc_in_controlRun 24-0715-B passed every enabled Westgard rule.
delta_check5.1 g/dL below the same patient's value from 14 July. Above the configured limit of 2.0. Held for a person.
suggestion: hold for review

Both buttons are inert on this page on purpose. This is a design specification, not a running system, and a control that appeared to release a result would be lying about what happens next.

Haemoglobin, LOINC 718-7

A reference range is a function, not a column.operable

Move the patient and the range moves with them. Move the value and the flag steps. Both are the real rule, running here.

Sex
Condition
12.0–15.59.14.07.020.022.0
Haemoglobin, 4 to 22 g/dL. The critical thresholds, the interval resolved for this patient, and the measured value on one scale.This figure is drawn in the browser. Open the table below for the same numbers.
Show the resolved interval as a table
The interval resolved for this patient, and the fixed critical thresholds for this test.
BoundaryValueSource
Critical low7.0 g/dLper test, not per patient
Reference low12.0 g/dLadult female, not pregnant
Reference high15.5 g/dLadult female, not pregnant
Critical high20.0 g/dLper test, not per patient
Measured9.1 g/dLthis result
9.1g/dL

Intervals shown here are an example configuration for one laboratory and one method. Real intervals are established by the laboratory that reports them, which is exactly why they cannot be two columns on a test row: they depend on age, sex, method, instrument and sometimes pregnancy, and they change over time.

The check that catches a swapped tube.operable

A delta check compares a result against the same patient's own previous value. Choose which previous value this specimen is compared with.

4812162014.21 day ago9.1this specimen
This patient's own previous haemoglobin against this one. A delta check compares a result to the same patient's last value for the same test, not to a population range.This figure is drawn in the browser. Open the table below for the same numbers.
Show the compared values as a table
The two values being compared and the configured delta limit.
PointValueWhen
Previous14.2 g/dL1 day ago
Current9.1 g/dLthis specimen
Limit2.0 g/dLwithin 7 days
-5.1 g/dLDelta check firesLimit for haemoglobin is 2.0 g/dL within 7 days. Flagged for a person to look at.

A failed delta check flags for review. It never blocks, because blocking would stop a genuinely deteriorating patient from being resulted, which is the opposite of the intent. Beyond the configured window the comparison is meaningless and is not made.

Quality control gates patient results.operable

Turn a rule off and watch what stops being caught, and what the release gate then allows. That coupling is the whole point of quality control.

The rules in force

1 of 3

1-2s is a warning, never a rejection. Treating it as one produces constant false alarms and the laboratory starts ignoring quality control altogether, which is worse than not having it.

The run

2 of 3
+3s+2s+1smean-1s-2s-3s123456789101112
Levey-Jennings, twelve runs of level 2 control material. Mean 7.00, standard deviation 0.15, with the 1, 2 and 3 SD bands drawn and each violating run marked.This figure is drawn in the browser. Open the table below for the same numbers, including which rules each run fired.
Show the plotted values as a table
The twelve control values, their deviation from the mean, and which enabled rules each one violates.
RunValue (%)DeviationRules fired
17.060+0.4snone
26.910-0.6snone
37.135+0.9s6x, 8x, 10x
47.195+1.3s3-1s, 4-1s, 6x, 8x, 10x
57.240+1.6s3-1s, 4-1s, 6x, 8x, 10x
67.330+2.2s1-2s, 2-2s, 2of3-2s, 3-1s, 4-1s, 6x, 8x, 10x
77.360+2.4s1-2s, 2-2s, 2of3-2s, 3-1s, 4-1s, 6x, 8x, 10x
87.210+1.4s3-1s, 4-1s, 6x, 8x, 10x
97.180+1.2s3-1s, 4-1s, 6x, 8x, 10x
107.165+1.1s3-1s, 4-1s, 6x, 8x, 10x
117.225+1.5s3-1s, 4-1s, 6x, 8x, 10x
127.480+3.2s1-2s, 1-3s, 3-1s, 4-1s, 6x, 8x, 10x

Level 2 control material, HbA1c. Mean 7.00 and standard deviation 0.15 are the laboratory's own, established over at least twenty runs, not the figures on the manufacturer's insert.

The gate

3 of 3
Release is lockedRejection rules fired on this run, so patient results from it are not releasable.
A-24-0187 · Marcus Vandermolen, HbA1centered
A-24-0193 · Aoife Ntuli, HbA1centered

A rejected run is investigated, the cause is recorded, corrective action is taken and quality control is re-run before patient testing resumes. The record is the part that gets skipped and the part an inspector asks for.

Potassium 6.9 mmol/L

A critical value is a phone call, and the phone call is a record.

Critical is not a stronger shade of abnormal. It means delay causes harm, so the obligation is not to display it prominently but to close a loop: identify it against per-test thresholds, escalate it to a responsible clinician, and record who was told, when, by which channel and who acknowledged it.

A notification that was sent and never acknowledged is an open safety issue with its own ageing, not a completed task. And a critical result cannot reach released without a recorded escalation, enforced in the transition function rather than in the interface, because the interface is not the only path to the field.

1 escalation open
critical_escalations · A-24-0189append only
Potassium, critical high6.9 mmol/Lthreshold 6.0 mmol/L · Tomasz Wierzbicki, ordered by Dr H. Lindqvist
identified · threshold 6.0 mmol/L exceeded
15 Jul 11:02:14 · automatic
notified · Dr H. Lindqvist, telephone
15 Jul 11:04:41 · by S. Okonkwo, technician
notified · on-call registrar, secure message
15 Jul 11:09:03 · escalated, no answer on first attempt

Custody is a history, not a column.

When a specimen's integrity is questioned, the history is the answer. A location field that gets overwritten has already thrown the answer away.

requested14 Jul 16:20 · Dr H. Lindqvist, clinician
assigned_collector14 Jul 18:02 · S. Okonkwo, phlebotomist
added_to_route15 Jul 07:03 · route R-118, six stops
attempted_visit15 Jul 08:41 · no answer at the door
patient_no_show15 Jul 08:44 · recorded, not deleted
rescheduled15 Jul 08:52 · patient called back, same morning
collected15 Jul 09:04 · offline, queued on device
label_printed15 Jul 09:04 · A-24-0186
transported15 Jul 09:07 · refrigerated carrier
received15 Jul 09:12 · accessioned, check digit verified
processed15 Jul 09:21 · centrifuged, aliquoted
stored15 Jul 09:26 · refrigerated, rack 4, position 12

Seventeen actions exist, and the awkward ones are the point. A specimen that could not be collected, or was collected badly, is part of its history.

requestedassigned_collectoradded_to_routeattempted_visitpatient_no_showrescheduledcollectedinsufficient_volumelabel_printedtransportedreceivedprocessedstoredretrievedmodifieddisposedcancelled

Storage is one of room_temp, refrigerated, frozen or ultra_frozen, and a change of storage is itself an action rather than an edit to a field.

For patients

One history, every laboratory you have used.

Your results are yours. When two laboratories both run on LabFlow you do not get two accounts and two portals — you get one timeline, with the laboratory named on every entry.

Meridian Pathology15 Jul 2024 · accession A-24-0186
Haemoglobin9.1 g/dLLow
Ferritin11 ug/LLow
Platelets288 x10^9/LNormal

Booking, results and sharing are one account across every participating laboratory. A laboratory that does not use LabFlow is not in this timeline, and the timeline says so rather than looking complete.

You choose what each laboratory sees.

A share grant is scoped to categories, has an expiry, and can be revoked. Turn a category off and it leaves the grant immediately.

Dr H. Lindqvist
clinician · Riverbend Family Practice
expires 12 Oct 2024

Dr H. Lindqvist can see haematology, chemistry and imaging. microbiology and genetics are excluded, and results in those categories are not returned by any query this grant authorises.

Scoped, not all or nothingA cardiologist gets your chemistry and haematology. They do not get your genetics because nobody thought to separate them.
Expiring by defaultEvery grant has an end date. Access you forgot you gave stops on its own rather than lasting forever.
Revocable, and the revocation is recordedTurning access off is itself an event with a time and an actor, so the question of who could see what, and when, has an answer.
Deletion is a real routeAccount and data deletion lives at /data-deletion and reads as an action rather than an essay.

Twelve personas, twelve applications.

Not one screen with permission holes cut into it. Pick a role and the shell changes, because a phlebotomist on a doorstep and a pathologist validating a panel are doing different jobs.

Application shelltechnician
Result entry
My worklist
Quality control
Instruments
Validatenot available to this role

A technician enters results and may not validate them. That is not a permission checkbox somebody can tick, it is the four-eyes principle expressed as two distinct capabilities, and the transition function is what enforces it.

Honest limits

What LabFlow does not do.

Every one of these is a real boundary rather than a roadmap tease. Finding one of them out after you have committed is worse than reading it here.

It is not a hospital EHRThere is no inpatient chart, no medication administration, no bed management. It is a laboratory system that talks to an EHR rather than replacing one.
There is no iOS applicationWeb and Android only. iOS needs an Apple developer account, which does not exist for this project, so the platform is left out rather than promised.
There is no DICOM viewerRadiology reports are text and structured findings. Images are linked, not rendered, and interpreting them is somebody else's software.
It is not a blood-bank LISNo donor management, no crossmatch, no component tracking. Transfusion medicine has its own regulatory surface and pretending otherwise would be dangerous.
There is no live HL7 feedHL7 v2 and FHIR move as files: a released report downloads, an order file imports as a draft. Nothing listens for messages on your infrastructure.
Part 11 documentation is roadmap, not shippedThe audit trail, versioning and capability model are built. The validation documentation package that a Part 11 assessment expects is planned work, and calling it done would be the easiest and worst lie on this page.

LabFlow is HIPAA conscious: audit logging, least-privilege access, tenant isolation and recorded consent are designed in. It is not certified, and no software can be, so the word compliant does not appear.

How a laboratory joins.

An application moves through five states and a person reviews it. Listing a laboratory that runs clinical tests is not a self-serve checkout.

Start an applicationdraftYours to edit. Nothing is visible to anyone else.
Verify who you arepending_verificationIdentity and accreditation documents.
Submitpending_reviewIn the queue, not yet opened.
Be reviewedunder_reviewA person is reading it, and may ask for changes.
Go liveapprovedListed in the marketplace and able to take bookings.

Nothing here is purchasable yet.

There is no payment gateway, by design. Quotes are given by conversation. LabFlow is privately developed and self-funded, so a quote reflects actual engineering and infrastructure cost rather than a markup priced for a funding round.

Every message lands in a real inbox rather than a ticket queue, which is a consequence of the size of the team and not a service promise.

Deliberately unavailable. No payment gateway exists, so a button that took your card details would be a lie about what happens next. Pricing is published at /pricing and quoted in conversation.